commit 0cdec976e4eaf96e1735ff417b222ab1463727e8 (tree)
parent 085cc54aadb327b9910be2c72b31ea046e7e8f52
Author: Andrew Kelley <andrew@ziglang.org>
Date: Sat, 28 Sep 2024 15:58:41 -0700
Merge pull request #21520 from ziglang/no-formatted-panics
formalize the panic interface
closes #17969
closes #20240
Diffstat:
23 files changed, 734 insertions(+), 843 deletions(-)
diff --git a/lib/compiler_rt/common.zig b/lib/compiler_rt/common.zig
@@ -75,13 +75,14 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {
pub const want_sparc_abi = builtin.cpu.arch.isSPARC();
-// Avoid dragging in the runtime safety mechanisms into this .o file,
-// unless we're trying to test compiler-rt.
-pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
- _ = error_return_trace;
+// Avoid dragging in the runtime safety mechanisms into this .o file, unless
+// we're trying to test compiler-rt.
+pub const Panic = if (builtin.is_test) std.debug.FormattedPanic else struct {};
+
+/// To be deleted after zig1.wasm is updated.
+pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
if (builtin.is_test) {
- @branchHint(.cold);
- std.debug.panic("{s}", .{msg});
+ std.debug.defaultPanic(msg, error_return_trace, ret_addr orelse @returnAddress());
} else {
unreachable;
}
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
@@ -22,6 +22,83 @@ pub const WaitGroup = @import("Thread/WaitGroup.zig");
pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc;
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
+pub fn sleep(nanoseconds: u64) void {
+ if (builtin.os.tag == .windows) {
+ const big_ms_from_ns = nanoseconds / std.time.ns_per_ms;
+ const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD);
+ windows.kernel32.Sleep(ms);
+ return;
+ }
+
+ if (builtin.os.tag == .wasi) {
+ const w = std.os.wasi;
+ const userdata: w.userdata_t = 0x0123_45678;
+ const clock: w.subscription_clock_t = .{
+ .id = .MONOTONIC,
+ .timeout = nanoseconds,
+ .precision = 0,
+ .flags = 0,
+ };
+ const in: w.subscription_t = .{
+ .userdata = userdata,
+ .u = .{
+ .tag = .CLOCK,
+ .u = .{ .clock = clock },
+ },
+ };
+
+ var event: w.event_t = undefined;
+ var nevents: usize = undefined;
+ _ = w.poll_oneoff(&in, &event, 1, &nevents);
+ return;
+ }
+
+ if (builtin.os.tag == .uefi) {
+ const boot_services = std.os.uefi.system_table.boot_services.?;
+ const us_from_ns = nanoseconds / std.time.ns_per_us;
+ const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize);
+ _ = boot_services.stall(us);
+ return;
+ }
+
+ const s = nanoseconds / std.time.ns_per_s;
+ const ns = nanoseconds % std.time.ns_per_s;
+
+ // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around
+ // since Linux 2.6 and glibc 2.1 anyway.
+ if (builtin.os.tag == .linux) {
+ const linux = std.os.linux;
+
+ var req: linux.timespec = .{
+ .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t),
+ .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t),
+ };
+ var rem: linux.timespec = undefined;
+
+ while (true) {
+ switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) {
+ .SUCCESS => return,
+ .INTR => {
+ req = rem;
+ continue;
+ },
+ .FAULT,
+ .INVAL,
+ .OPNOTSUPP,
+ => unreachable,
+ else => return,
+ }
+ }
+ }
+
+ posix.nanosleep(s, ns);
+}
+
+test sleep {
+ sleep(1);
+}
+
const Thread = @This();
const Impl = if (native_os == .windows)
WindowsThreadImpl
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
@@ -761,195 +761,54 @@ pub const TestFn = struct {
func: *const fn () anyerror!void,
};
-/// This function type is used by the Zig language code generation and
-/// therefore must be kept in sync with the compiler implementation.
+/// Deprecated, use the `Panic` namespace instead.
+/// To be deleted after 0.14.0 is released.
pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn;
-
-/// This function is used by the Zig language code generation and
-/// therefore must be kept in sync with the compiler implementation.
-pub const panic: PanicFn = if (@hasDecl(root, "panic"))
- root.panic
-else if (@hasDecl(root, "os") and @hasDecl(root.os, "panic"))
- root.os.panic
+/// Deprecated, use the `Panic` namespace instead.
+/// To be deleted after 0.14.0 is released.
+pub const panic: PanicFn = Panic.call;
+
+/// This namespace is used by the Zig compiler to emit various kinds of safety
+/// panics. These can be overridden by making a public `Panic` namespace in the
+/// root source file.
+pub const Panic: type = if (@hasDecl(root, "Panic"))
+ root.Panic
+else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead.
+ DeprecatedPanic
+else if (builtin.zig_backend == .stage2_riscv64)
+ std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519
else
- default_panic;
-
-/// This function is used by the Zig language code generation and
-/// therefore must be kept in sync with the compiler implementation.
-pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr: ?usize) noreturn {
- @branchHint(.cold);
-
- // For backends that cannot handle the language features depended on by the
- // default panic handler, we have a simpler panic handler:
- if (builtin.zig_backend == .stage2_wasm or
- builtin.zig_backend == .stage2_arm or
- builtin.zig_backend == .stage2_aarch64 or
- builtin.zig_backend == .stage2_x86 or
- (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or
- builtin.zig_backend == .stage2_sparc64 or
- builtin.zig_backend == .stage2_spirv64)
- {
- while (true) {
- @breakpoint();
- }
- }
-
- if (builtin.zig_backend == .stage2_riscv64) {
- std.debug.print("panic: {s}\n", .{msg});
- @breakpoint();
- std.posix.exit(127);
- }
-
- switch (builtin.os.tag) {
- .freestanding => {
- while (true) {
- @breakpoint();
- }
- },
- .wasi => {
- std.debug.print("{s}", .{msg});
- std.posix.abort();
- },
- .uefi => {
- const uefi = std.os.uefi;
-
- const Formatter = struct {
- pub fn fmt(exit_msg: []const u8, out: []u16) ![:0]u16 {
- var u8_buf: [256]u8 = undefined;
- const slice = try std.fmt.bufPrint(&u8_buf, "err: {s}\r\n", .{exit_msg});
- // We pass len - 1 because we need to add a null terminator after
- const len = try std.unicode.utf8ToUtf16Le(out[0 .. out.len - 1], slice);
-
- out[len] = 0;
-
- return out[0..len :0];
- }
- };
-
- const ExitData = struct {
- pub fn create_exit_data(exit_msg: [:0]u16, exit_size: *usize) ![*:0]u16 {
- // Need boot services for pool allocation
- if (uefi.system_table.boot_services == null) {
- return error.BootServicesUnavailable;
- }
-
- // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
- const exit_data: []u16 = try uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1);
-
- @memcpy(exit_data[0 .. exit_msg.len + 1], exit_msg[0 .. exit_msg.len + 1]);
- exit_size.* = exit_msg.len + 1;
-
- return @as([*:0]u16, @ptrCast(exit_data.ptr));
- }
- };
-
- var buf: [256]u16 = undefined;
- const utf16 = Formatter.fmt(msg, &buf) catch null;
-
- var exit_size: usize = 0;
- const exit_data = if (utf16) |u|
- ExitData.create_exit_data(u, &exit_size) catch null
- else
- null;
-
- if (utf16) |str| {
- // Output to both std_err and con_out, as std_err is easier
- // to read in stuff like QEMU at times, but, unlike con_out,
- // isn't visible on actual hardware if directly booted into
- inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
- if (o) |out| {
- _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
- _ = out.outputString(str);
- _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
- }
- }
- }
-
- if (uefi.system_table.boot_services) |bs| {
- _ = bs.exit(uefi.handle, .Aborted, exit_size, exit_data);
- }
-
- // Didn't have boot_services, just fallback to whatever.
- std.posix.abort();
- },
- .cuda, .amdhsa => std.posix.abort(),
- .plan9 => {
- var status: [std.os.plan9.ERRMAX]u8 = undefined;
- const len = @min(msg.len, status.len - 1);
- @memcpy(status[0..len], msg[0..len]);
- status[len] = 0;
- std.os.plan9.exits(status[0..len :0]);
- },
- else => {
- const first_trace_addr = ret_addr orelse @returnAddress();
- std.debug.panicImpl(error_return_trace, first_trace_addr, msg);
- },
- }
-}
-
-pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {
- @branchHint(.cold);
- std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual });
-}
-
-pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
- @branchHint(.cold);
- std.debug.panicExtra(st, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
-}
-
-pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
- @branchHint(.cold);
- std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
-}
-
-pub fn panicStartGreaterThanEnd(start: usize, end: usize) noreturn {
- @branchHint(.cold);
- std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
-}
-
-pub fn panicInactiveUnionField(active: anytype, wanted: @TypeOf(active)) noreturn {
- @branchHint(.cold);
- std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ @tagName(wanted), @tagName(active) });
-}
-
-pub const panic_messages = struct {
- pub const unreach = "reached unreachable code";
- pub const unwrap_null = "attempt to use null value";
- pub const cast_to_null = "cast causes pointer to be null";
- pub const incorrect_alignment = "incorrect alignment";
- pub const invalid_error_code = "invalid error code";
- pub const cast_truncated_data = "integer cast truncated bits";
- pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
- pub const integer_overflow = "integer overflow";
- pub const shl_overflow = "left shift overflowed bits";
- pub const shr_overflow = "right shift overflowed bits";
- pub const divide_by_zero = "division by zero";
- pub const exact_division_remainder = "exact division produced remainder";
- pub const inactive_union_field = "access of inactive union field";
- pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
- pub const corrupt_switch = "switch on corrupt value";
- pub const shift_rhs_too_big = "shift amount is greater than the type size";
- pub const invalid_enum_value = "invalid enum value";
- pub const sentinel_mismatch = "sentinel mismatch";
- pub const unwrap_error = "attempt to unwrap error";
- pub const index_out_of_bounds = "index out of bounds";
- pub const start_index_greater_than_end = "start index is larger than end index";
- pub const for_len_mismatch = "for loop over objects with non-equal lengths";
- pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
- pub const memcpy_alias = "@memcpy arguments alias";
- pub const noreturn_returned = "'noreturn' function returned";
-};
+ std.debug.FormattedPanic;
+
+/// To be deleted after 0.14.0 is released.
+const DeprecatedPanic = struct {
+ pub const call = root.panic;
+ pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
+ pub const unwrapError = std.debug.FormattedPanic.unwrapError;
+ pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
+ pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
+ pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
+ pub const messages = std.debug.FormattedPanic.messages;
+};
+
+/// To be deleted after zig1.wasm is updated.
+pub const panicSentinelMismatch = Panic.sentinelMismatch;
+/// To be deleted after zig1.wasm is updated.
+pub const panicUnwrapError = Panic.unwrapError;
+/// To be deleted after zig1.wasm is updated.
+pub const panicOutOfBounds = Panic.outOfBounds;
+/// To be deleted after zig1.wasm is updated.
+pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd;
+/// To be deleted after zig1.wasm is updated.
+pub const panicInactiveUnionField = Panic.inactiveUnionField;
+/// To be deleted after zig1.wasm is updated.
+pub const panic_messages = Panic.messages;
pub noinline fn returnError(st: *StackTrace) void {
- @branchHint(.cold);
+ @branchHint(.unlikely);
@setRuntimeSafety(false);
- addErrRetTraceAddr(st, @returnAddress());
-}
-
-pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
if (st.index < st.instruction_addresses.len)
- st.instruction_addresses[st.index] = addr;
-
+ st.instruction_addresses[st.index] = @returnAddress();
st.index += 1;
}
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
@@ -21,6 +21,9 @@ pub const SelfInfo = @import("debug/SelfInfo.zig");
pub const Info = @import("debug/Info.zig");
pub const Coverage = @import("debug/Coverage.zig");
+pub const FormattedPanic = @import("debug/FormattedPanic.zig");
+pub const SimplePanic = @import("debug/SimplePanic.zig");
+
/// Unresolved source locations can be represented with a single `usize` that
/// corresponds to a virtual memory address of the program counter. Combined
/// with debug information, those values can be converted into a resolved
@@ -408,14 +411,21 @@ pub fn assertReadable(slice: []const volatile u8) void {
for (slice) |*byte| _ = byte.*;
}
+/// By including a call to this function, the caller gains an error return trace
+/// secret parameter, making `@errorReturnTrace()` more useful. This is not
+/// necessary if the function already contains a call to an errorable function
+/// elsewhere.
+pub fn errorReturnTraceHelper() anyerror!void {}
+
+/// Equivalent to `@panic` but with a formatted message.
pub fn panic(comptime format: []const u8, args: anytype) noreturn {
@branchHint(.cold);
-
+ errorReturnTraceHelper() catch unreachable;
panicExtra(@errorReturnTrace(), @returnAddress(), format, args);
}
-/// `panicExtra` is useful when you want to print out an `@errorReturnTrace`
-/// and also print out some values.
+/// Equivalent to `@panic` but with a formatted message, and with an explicitly
+/// provided `@errorReturnTrace` and return address.
pub fn panicExtra(
trace: ?*std.builtin.StackTrace,
ret_addr: ?usize,
@@ -436,7 +446,7 @@ pub fn panicExtra(
break :blk &buf;
},
};
- std.builtin.panic(msg, trace, ret_addr);
+ std.builtin.Panic.call(msg, trace, ret_addr);
}
/// Non-zero whenever the program triggered a panic.
@@ -447,11 +457,70 @@ var panicking = std.atomic.Value(u8).init(0);
/// This is used to catch and handle panics triggered by the panic handler.
threadlocal var panic_stage: usize = 0;
-// `panicImpl` could be useful in implementing a custom panic handler which
-// calls the default handler (on supported platforms)
-pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize, msg: []const u8) noreturn {
+/// Dumps a stack trace to standard error, then aborts.
+pub fn defaultPanic(
+ msg: []const u8,
+ error_return_trace: ?*const std.builtin.StackTrace,
+ first_trace_addr: ?usize,
+) noreturn {
@branchHint(.cold);
+ // For backends that cannot handle the language features depended on by the
+ // default panic handler, we have a simpler panic handler:
+ if (builtin.zig_backend == .stage2_wasm or
+ builtin.zig_backend == .stage2_arm or
+ builtin.zig_backend == .stage2_aarch64 or
+ builtin.zig_backend == .stage2_x86 or
+ (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or
+ builtin.zig_backend == .stage2_sparc64 or
+ builtin.zig_backend == .stage2_spirv64)
+ {
+ @trap();
+ }
+
+ switch (builtin.os.tag) {
+ .freestanding => {
+ @trap();
+ },
+ .uefi => {
+ const uefi = std.os.uefi;
+
+ var utf16_buffer: [1000]u16 = undefined;
+ const len_minus_3 = std.unicode.utf8ToUtf16Le(&utf16_buffer, msg) catch 0;
+ utf16_buffer[len_minus_3][0..3].* = .{ '\r', '\n', 0 };
+ const len = len_minus_3 + 3;
+ const exit_msg = utf16_buffer[0 .. len - 1 :0];
+
+ // Output to both std_err and con_out, as std_err is easier
+ // to read in stuff like QEMU at times, but, unlike con_out,
+ // isn't visible on actual hardware if directly booted into
+ inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
+ if (o) |out| {
+ _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
+ _ = out.outputString(exit_msg);
+ _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
+ }
+ }
+
+ if (uefi.system_table.boot_services) |bs| {
+ // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
+ const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap();
+ @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator.
+ _ = bs.exit(uefi.handle, .Aborted, exit_msg.len + 1, exit_data);
+ }
+ @trap();
+ },
+ .cuda, .amdhsa => std.posix.abort(),
+ .plan9 => {
+ var status: [std.os.plan9.ERRMAX]u8 = undefined;
+ const len = @min(msg.len, status.len - 1);
+ @memcpy(status[0..len], msg[0..len]);
+ status[len] = 0;
+ std.os.plan9.exits(status[0..len :0]);
+ },
+ else => {},
+ }
+
if (enable_segfault_handler) {
// If a segfault happens while panicking, we want it to actually segfault, not trigger
// the handler.
@@ -465,7 +534,6 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
_ = panicking.fetchAdd(1, .seq_cst);
- // Make sure to release the mutex when done
{
lockStdErr();
defer unlockStdErr();
@@ -478,10 +546,9 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
stderr.print("thread {} panic: ", .{current_thread_id}) catch posix.abort();
}
stderr.print("{s}\n", .{msg}) catch posix.abort();
- if (trace) |t| {
- dumpStackTrace(t.*);
- }
- dumpCurrentStackTrace(first_trace_addr);
+
+ if (error_return_trace) |t| dumpStackTrace(t.*);
+ dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());
}
waitForOtherThreadToFinishPanicking();
@@ -489,15 +556,12 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
1 => {
panic_stage = 2;
- // A panic happened while trying to print a previous panic message,
- // we're still holding the mutex but that's fine as we're going to
- // call abort()
- const stderr = io.getStdErr().writer();
- stderr.print("Panicked during a panic. Aborting.\n", .{}) catch posix.abort();
- },
- else => {
- // Panicked while printing "Panicked during a panic."
+ // A panic happened while trying to print a previous panic message.
+ // We're still holding the mutex but that's fine as we're going to
+ // call abort().
+ io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};
},
+ else => {}, // Panicked while printing the recursive panic message.
};
posix.abort();
@@ -1157,7 +1221,7 @@ pub const default_enable_segfault_handler = runtime_safety and have_segfault_han
pub fn maybeEnableSegfaultHandler() void {
if (enable_segfault_handler) {
- std.debug.attachSegfaultHandler();
+ attachSegfaultHandler();
}
}
@@ -1289,46 +1353,29 @@ fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(windows.WIN
}
}
-fn handleSegfaultWindowsExtra(
- info: *windows.EXCEPTION_POINTERS,
- msg: u8,
- label: ?[]const u8,
-) noreturn {
- const exception_address = @intFromPtr(info.ExceptionRecord.ExceptionAddress);
- if (windows.CONTEXT != void) {
- nosuspend switch (panic_stage) {
- 0 => {
- panic_stage = 1;
- _ = panicking.fetchAdd(1, .seq_cst);
-
- {
- lockStdErr();
- defer unlockStdErr();
-
- dumpSegfaultInfoWindows(info, msg, label);
- }
+fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) noreturn {
+ comptime assert(windows.CONTEXT != void);
+ nosuspend switch (panic_stage) {
+ 0 => {
+ panic_stage = 1;
+ _ = panicking.fetchAdd(1, .seq_cst);
+
+ {
+ lockStdErr();
+ defer unlockStdErr();
- waitForOtherThreadToFinishPanicking();
- },
- else => {
- // panic mutex already locked
dumpSegfaultInfoWindows(info, msg, label);
- },
- };
- posix.abort();
- } else {
- switch (msg) {
- 0 => panicImpl(null, exception_address, "{s}", label.?),
- 1 => {
- const format_item = "Segmentation fault at address 0x{x}";
- var buf: [format_item.len + 64]u8 = undefined; // 64 is arbitrary, but sufficiently large
- const to_print = std.fmt.bufPrint(buf[0..buf.len], format_item, .{info.ExceptionRecord.ExceptionInformation[1]}) catch unreachable;
- panicImpl(null, exception_address, to_print);
- },
- 2 => panicImpl(null, exception_address, "Illegal Instruction"),
- else => unreachable,
- }
- }
+ }
+
+ waitForOtherThreadToFinishPanicking();
+ },
+ 1 => {
+ panic_stage = 2;
+ io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};
+ },
+ else => {},
+ };
+ posix.abort();
}
fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
@@ -1347,7 +1394,7 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
const sp = asm (""
: [argc] "={rsp}" (-> usize),
);
- std.debug.print("{s} sp = 0x{x}\n", .{ prefix, sp });
+ print("{s} sp = 0x{x}\n", .{ prefix, sp });
}
test "manage resources correctly" {
diff --git a/lib/std/debug/FormattedPanic.zig b/lib/std/debug/FormattedPanic.zig
@@ -0,0 +1,45 @@
+//! This namespace is the default one used by the Zig compiler to emit various
+//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
+//!
+//! Since Zig does not have interfaces, this file serves as an example template
+//! for users to provide their own alternative panic handling.
+//!
+//! As an alternative, see `std.debug.SimplePanic`.
+
+const std = @import("../std.zig");
+
+/// Dumps a stack trace to standard error, then aborts.
+///
+/// Explicit calls to `@panic` lower to calling this function.
+pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic;
+
+pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
+ expected, found,
+ });
+}
+
+pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
+}
+
+pub fn outOfBounds(index: usize, len: usize) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
+}
+
+pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
+}
+
+pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
+ @tagName(accessed), @tagName(active),
+ });
+}
+
+pub const messages = std.debug.SimplePanic.messages;
diff --git a/lib/std/debug/SimplePanic.zig b/lib/std/debug/SimplePanic.zig
@@ -0,0 +1,86 @@
+//! This namespace is the default one used by the Zig compiler to emit various
+//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
+//!
+//! Since Zig does not have interfaces, this file serves as an example template
+//! for users to provide their own alternative panic handling.
+//!
+//! As an alternative, see `std.debug.FormattedPanic`.
+
+const std = @import("../std.zig");
+
+/// Prints the message to stderr without a newline and then traps.
+///
+/// Explicit calls to `@panic` lower to calling this function.
+pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn {
+ @branchHint(.cold);
+ _ = ert;
+ _ = ra;
+ std.debug.lockStdErr();
+ const stderr = std.io.getStdErr();
+ stderr.writeAll(msg) catch {};
+ @trap();
+}
+
+pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
+ _ = found;
+ call("sentinel mismatch", null, null);
+}
+
+pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
+ _ = ert;
+ _ = &err;
+ call("attempt to unwrap error", null, null);
+}
+
+pub fn outOfBounds(index: usize, len: usize) noreturn {
+ _ = index;
+ _ = len;
+ call("index out of bounds", null, null);
+}
+
+pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
+ _ = start;
+ _ = end;
+ call("start index is larger than end index", null, null);
+}
+
+pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
+ _ = accessed;
+ call("access of inactive union field", null, null);
+}
+
+pub const messages = struct {
+ pub const reached_unreachable = "reached unreachable code";
+ pub const unwrap_null = "attempt to use null value";
+ pub const cast_to_null = "cast causes pointer to be null";
+ pub const incorrect_alignment = "incorrect alignment";
+ pub const invalid_error_code = "invalid error code";
+ pub const cast_truncated_data = "integer cast truncated bits";
+ pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
+ pub const integer_overflow = "integer overflow";
+ pub const shl_overflow = "left shift overflowed bits";
+ pub const shr_overflow = "right shift overflowed bits";
+ pub const divide_by_zero = "division by zero";
+ pub const exact_division_remainder = "exact division produced remainder";
+ pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
+ pub const corrupt_switch = "switch on corrupt value";
+ pub const shift_rhs_too_big = "shift amount is greater than the type size";
+ pub const invalid_enum_value = "invalid enum value";
+ pub const for_len_mismatch = "for loop over objects with non-equal lengths";
+ pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
+ pub const memcpy_alias = "@memcpy arguments alias";
+ pub const noreturn_returned = "'noreturn' function returned";
+
+ /// To be deleted after zig1.wasm is updated.
+ pub const inactive_union_field = "access of inactive union field";
+ /// To be deleted after zig1.wasm is updated.
+ pub const sentinel_mismatch = "sentinel mismatch";
+ /// To be deleted after zig1.wasm is updated.
+ pub const unwrap_error = "attempt to unwrap error";
+ /// To be deleted after zig1.wasm is updated.
+ pub const index_out_of_bounds = "index out of bounds";
+ /// To be deleted after zig1.wasm is updated.
+ pub const start_index_greater_than_end = "start index is larger than end index";
+ /// To be deleted after zig1.wasm is updated.
+ pub const unreach = reached_unreachable;
+};
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
@@ -1197,7 +1197,7 @@ pub fn formatInt(
if (base == 10) {
while (a >= 100) : (a = @divTrunc(a, 100)) {
index -= 2;
- buf[index..][0..2].* = digits2(@as(usize, @intCast(a % 100)));
+ buf[index..][0..2].* = digits2(@intCast(a % 100));
}
if (a < 10) {
@@ -1205,13 +1205,13 @@ pub fn formatInt(
buf[index] = '0' + @as(u8, @intCast(a));
} else {
index -= 2;
- buf[index..][0..2].* = digits2(@as(usize, @intCast(a)));
+ buf[index..][0..2].* = digits2(@intCast(a));
}
} else {
while (true) {
const digit = a % base;
index -= 1;
- buf[index] = digitToChar(@as(u8, @intCast(digit)), case);
+ buf[index] = digitToChar(@intCast(digit), case);
a /= base;
if (a == 0) break;
}
@@ -1242,11 +1242,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options
// Converts values in the range [0, 100) to a string.
pub fn digits2(value: usize) [2]u8 {
- return ("0001020304050607080910111213141516171819" ++
- "2021222324252627282930313233343536373839" ++
- "4041424344454647484950515253545556575859" ++
- "6061626364656667686970717273747576777879" ++
- "8081828384858687888990919293949596979899")[value * 2 ..][0..2].*;
+ return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
}
const FormatDurationData = struct {
diff --git a/lib/std/time.zig b/lib/std/time.zig
@@ -8,82 +8,8 @@ const posix = std.posix;
pub const epoch = @import("time/epoch.zig");
-/// Spurious wakeups are possible and no precision of timing is guaranteed.
-pub fn sleep(nanoseconds: u64) void {
- if (builtin.os.tag == .windows) {
- const big_ms_from_ns = nanoseconds / ns_per_ms;
- const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD);
- windows.kernel32.Sleep(ms);
- return;
- }
-
- if (builtin.os.tag == .wasi) {
- const w = std.os.wasi;
- const userdata: w.userdata_t = 0x0123_45678;
- const clock: w.subscription_clock_t = .{
- .id = .MONOTONIC,
- .timeout = nanoseconds,
- .precision = 0,
- .flags = 0,
- };
- const in: w.subscription_t = .{
- .userdata = userdata,
- .u = .{
- .tag = .CLOCK,
- .u = .{ .clock = clock },
- },
- };
-
- var event: w.event_t = undefined;
- var nevents: usize = undefined;
- _ = w.poll_oneoff(&in, &event, 1, &nevents);
- return;
- }
-
- if (builtin.os.tag == .uefi) {
- const boot_services = std.os.uefi.system_table.boot_services.?;
- const us_from_ns = nanoseconds / ns_per_us;
- const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize);
- _ = boot_services.stall(us);
- return;
- }
-
- const s = nanoseconds / ns_per_s;
- const ns = nanoseconds % ns_per_s;
-
- // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around
- // since Linux 2.6 and glibc 2.1 anyway.
- if (builtin.os.tag == .linux) {
- const linux = std.os.linux;
-
- var req: linux.timespec = .{
- .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t),
- .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t),
- };
- var rem: linux.timespec = undefined;
-
- while (true) {
- switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) {
- .SUCCESS => return,
- .INTR => {
- req = rem;
- continue;
- },
- .FAULT,
- .INVAL,
- .OPNOTSUPP,
- => unreachable,
- else => return,
- }
- }
- }
-
- posix.nanosleep(s, ns);
-}
-
-test sleep {
- sleep(1);
-}
+/// Deprecated: moved to std.Thread.sleep
+pub const sleep = std.Thread.sleep;
/// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01.
/// Precision of timing depends on the hardware and operating system.
@@ -155,7 +81,7 @@ test milliTimestamp {
const margin = ns_per_ms * 50;
const time_0 = milliTimestamp();
- sleep(ns_per_ms);
+ std.Thread.sleep(ns_per_ms);
const time_1 = milliTimestamp();
const interval = time_1 - time_0;
try testing.expect(interval > 0);
@@ -359,7 +285,7 @@ test Timer {
const margin = ns_per_ms * 150;
var timer = try Timer.start();
- sleep(10 * ns_per_ms);
+ std.Thread.sleep(10 * ns_per_ms);
const time_0 = timer.read();
try testing.expect(time_0 > 0);
// Tests should not depend on timings: skip test if outside margin.
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -195,7 +195,6 @@ job_queued_compiler_rt_obj: bool = false,
job_queued_fuzzer_lib: bool = false,
job_queued_update_builtin_zig: bool,
alloc_failure_occurred: bool = false,
-formatted_panics: bool = false,
last_update_was_cache_hit: bool = false,
c_source_files: []const CSourceFile,
@@ -1088,7 +1087,6 @@ pub const CreateOptions = struct {
/// executable this field is ignored.
want_compiler_rt: ?bool = null,
want_lto: ?bool = null,
- formatted_panics: ?bool = null,
function_sections: bool = false,
data_sections: bool = false,
no_builtin: bool = false,
@@ -1357,9 +1355,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
}
}
- // TODO: https://github.com/ziglang/zig/issues/17969
- const formatted_panics = options.formatted_panics orelse (options.root_mod.optimize_mode == .Debug);
-
const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
// We put everything into the cache hash that *cannot be modified
@@ -1520,7 +1515,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.verbose_link = options.verbose_link,
.disable_c_depfile = options.disable_c_depfile,
.reference_trace = options.reference_trace,
- .formatted_panics = formatted_panics,
.time_report = options.time_report,
.stack_report = options.stack_report,
.test_filters = options.test_filters,
@@ -1638,7 +1632,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
hash.addListOfBytes(options.test_filters);
hash.addOptionalBytes(options.test_name_prefix);
hash.add(options.skip_linker_dependencies);
- hash.add(formatted_panics);
hash.add(options.emit_h != null);
hash.add(error_limit);
@@ -2564,7 +2557,6 @@ fn addNonIncrementalStuffToCacheManifest(
man.hash.addListOfBytes(comp.test_filters);
man.hash.addOptionalBytes(comp.test_name_prefix);
man.hash.add(comp.skip_linker_dependencies);
- man.hash.add(comp.formatted_panics);
//man.hash.add(mod.emit_h != null);
man.hash.add(mod.error_limit);
} else {
diff --git a/src/InternPool.zig b/src/InternPool.zig
@@ -7353,6 +7353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
.func_type => unreachable, // use getFuncType() instead
.@"extern" => unreachable, // use getExtern() instead
.func => unreachable, // use getFuncInstance() or getFuncDecl() instead
+ .un => unreachable, // use getUnion instead
.variable => |variable| {
const has_init = variable.init != .none;
@@ -7968,15 +7969,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
if (sentinel != .none) extra.appendAssumeCapacity(.{@intFromEnum(sentinel)});
},
- .un => |un| {
- assert(un.ty != .none);
- assert(un.val != .none);
- items.appendAssumeCapacity(.{
- .tag = .union_value,
- .data = try addExtra(extra, un),
- });
- },
-
.memoized_call => |memoized_call| {
for (memoized_call.arg_values) |arg| assert(arg != .none);
try extra.ensureUnusedCapacity(@typeInfo(MemoizedCall).@"struct".fields.len +
@@ -7996,6 +7988,30 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
return gop.put();
}
+pub fn getUnion(
+ ip: *InternPool,
+ gpa: Allocator,
+ tid: Zcu.PerThread.Id,
+ un: Key.Union,
+) Allocator.Error!Index {
+ var gop = try ip.getOrPutKey(gpa, tid, .{ .un = un });
+ defer gop.deinit();
+ if (gop == .existing) return gop.existing;
+ const local = ip.getLocal(tid);
+ const items = local.getMutableItems(gpa);
+ const extra = local.getMutableExtra(gpa);
+ try items.ensureUnusedCapacity(1);
+
+ assert(un.ty != .none);
+ assert(un.val != .none);
+ items.appendAssumeCapacity(.{
+ .tag = .union_value,
+ .data = try addExtra(extra, un),
+ });
+
+ return gop.put();
+}
+
pub const UnionTypeInit = struct {
flags: packed struct {
runtime_tag: LoadedUnionType.RuntimeTag,
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -2141,7 +2141,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty));
// var st: StackTrace = undefined;
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
@@ -4854,11 +4854,11 @@ fn validateUnionInit(
}
block.instructions.shrinkRetainingCapacity(block_index);
- const union_val = try pt.intern(.{ .un = .{
+ const union_val = try pt.internUnion(.{
.ty = union_ty.toIntern(),
.tag = tag_val.toIntern(),
.val = val.toIntern(),
- } });
+ });
const union_init = Air.internedToRef(union_val);
try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
return;
@@ -5703,27 +5703,7 @@ fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.
}
fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
- return Air.internedToRef(try sema.refValue(val));
-}
-
-fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {
- const pt = sema.pt;
- const ptr_ty = (try pt.ptrTypeSema(.{
- .child = pt.zcu.intern_pool.typeOf(val),
- .flags = .{
- .alignment = .none,
- .is_const = true,
- .address_space = .generic,
- },
- })).toIntern();
- return pt.intern(.{ .ptr = .{
- .ty = ptr_ty,
- .base_addr = .{ .uav = .{
- .val = val,
- .orig_ty = ptr_ty,
- } },
- .byte_offset = 0,
- } });
+ return Air.internedToRef(try sema.pt.refValue(val));
}
fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -6965,7 +6945,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
if (!block.ownerModule().error_tracing) return .none;
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
@@ -7007,7 +6987,7 @@ fn popErrorReturnTrace(
// AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or
// the result is comptime-known to be a non-error. Either way, pop unconditionally.
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
@@ -7033,7 +7013,7 @@ fn popErrorReturnTrace(
defer then_block.instructions.deinit(gpa);
// If non-error, then pop the error return trace by restoring the index.
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
@@ -7176,7 +7156,7 @@ fn zirCall(
// If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
// need to clean-up our own trace if we were passed to a non-error-handling expression.
if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) {
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "index", .no_embedded_nulls);
const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
@@ -9327,7 +9307,7 @@ fn analyzeErrUnionPayload(
if (safety_check and block.wantSafety() and
!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))
{
- try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
+ try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
}
return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);
@@ -9411,7 +9391,7 @@ fn analyzeErrUnionPayloadPtr(
if (safety_check and block.wantSafety() and
!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))
{
- try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
+ try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
}
if (initializing) {
@@ -10231,7 +10211,7 @@ fn finishFunc(
if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
// Make sure that StackTrace's fields are resolved so that the backend can
// lower this fn type.
- const unresolved_stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
try unresolved_stack_trace_ty.resolveFields(pt);
}
@@ -14190,7 +14170,6 @@ fn maybeErrorUnwrap(
) !bool {
const pt = sema.pt;
const zcu = pt.zcu;
- if (!zcu.backendSupportsFeature(.panic_unwrap_error)) return false;
const tags = sema.code.instructions.items(.tag);
for (body) |inst| {
@@ -14223,25 +14202,17 @@ fn maybeErrorUnwrap(
.as_node => try sema.zirAsNode(block, inst),
.field_val => try sema.zirFieldVal(block, inst),
.@"unreachable" => {
- if (!zcu.comp.formatted_panics) {
- try sema.safetyPanic(block, operand_src, .unwrap_error);
- return true;
- }
-
- const panic_fn = try pt.getBuiltin("panicUnwrapError");
- const err_return_trace = try sema.getErrorReturnTrace(block);
- const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };
- try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
+ try safetyPanicUnwrapError(sema, block, operand_src, operand);
return true;
},
.panic => {
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const msg_inst = try sema.resolveInst(inst_data.operand);
- const panic_fn = try pt.getBuiltin("panic");
+ const panic_fn = try getPanicInnerFn(sema, block, operand_src, "call");
const err_return_trace = try sema.getErrorReturnTrace(block);
const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
- try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
+ try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
return true;
},
else => unreachable,
@@ -18275,7 +18246,7 @@ fn zirBuiltinSrc(
} });
};
- const src_loc_ty = try pt.getBuiltinType("SourceLocation");
+ const src_loc_ty = try sema.getBuiltinType("SourceLocation");
const fields = .{
// module: [:0]const u8,
module_name_val,
@@ -18302,7 +18273,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const src = block.nodeOffset(inst_data.src_node);
const ty = try sema.resolveType(block, src, inst_data.operand);
- const type_info_ty = try pt.getBuiltinType("Type");
+ const type_info_ty = try sema.getBuiltinType("Type");
const type_info_tag_ty = type_info_ty.unionTagType(zcu).?;
if (ty.typeDeclInst(zcu)) |type_decl_inst| {
@@ -18319,29 +18290,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.undefined,
.null,
.enum_literal,
- => |type_info_tag| return Air.internedToRef((try pt.intern(.{ .un = .{
- .ty = type_info_ty.toIntern(),
- .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(type_info_tag))).toIntern(),
- .val = .void_value,
- } }))),
- .@"fn" => {
- const fn_info_nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Fn", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, fn_info_nav);
- const fn_info_ty = Type.fromInterned(ip.getNav(fn_info_nav).status.resolved.val);
+ => |type_info_tag| return unionInitFromEnumTag(sema, block, src, type_info_ty, @intFromEnum(type_info_tag), .void_value),
- const param_info_nav = try sema.namespaceLookup(
- block,
- src,
- fn_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Param", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, param_info_nav);
- const param_info_ty = Type.fromInterned(ip.getNav(param_info_nav).status.resolved.val);
+ .@"fn" => {
+ const fn_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Fn");
+ const param_info_ty = try getBuiltinInnerType(sema, block, src, fn_info_ty, "Type.Fn", "Param");
const func_ty_info = zcu.typeToFunc(ty).?;
const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
@@ -18411,7 +18364,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
func_ty_info.return_type,
} });
- const callconv_ty = try pt.getBuiltinType("CallingConvention");
+ const callconv_ty = try sema.getBuiltinType("CallingConvention");
const field_values = .{
// calling_convention: CallingConvention,
@@ -18425,26 +18378,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// args: []const Fn.Param,
args_val,
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"fn"))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = fn_info_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.int => {
- const int_info_nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Int", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, int_info_nav);
- const int_info_ty = Type.fromInterned(ip.getNav(int_info_nav).status.resolved.val);
-
- const signedness_ty = try pt.getBuiltinType("Signedness");
+ const int_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Int");
+ const signedness_ty = try sema.getBuiltinType("Signedness");
const info = ty.intInfo(zcu);
const field_values = .{
// signedness: Signedness,
@@ -18452,37 +18397,30 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// bits: u16,
(try pt.intValue(Type.u16, info.bits)).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.int))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = int_info_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.float => {
- const float_info_nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Float", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, float_info_nav);
- const float_info_ty = Type.fromInterned(ip.getNav(float_info_nav).status.resolved.val);
+ const float_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Float");
const field_vals = .{
// bits: u16,
(try pt.intValue(Type.u16, ty.bitSize(zcu))).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.float))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = float_info_ty.toIntern(),
.storage = .{ .elems = &field_vals },
} }),
- } })));
+ })));
},
.pointer => {
const info = ty.ptrInfo(zcu);
@@ -18491,27 +18429,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
else
try Type.fromInterned(info.child).lazyAbiAlignment(pt);
- const addrspace_ty = try pt.getBuiltinType("AddressSpace");
- const pointer_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Pointer", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
- const ptr_size_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- pointer_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Size", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const addrspace_ty = try sema.getBuiltinType("AddressSpace");
+ const pointer_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Pointer");
+ const ptr_size_ty = try getBuiltinInnerType(sema, block, src, pointer_ty, "Type.Pointer", "Size");
const field_values = .{
// size: Size,
@@ -18534,26 +18454,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
else => Value.fromInterned(info.sentinel),
})).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.pointer))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = pointer_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.array => {
- const array_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Array", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const array_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Array");
const info = ty.arrayInfo(zcu);
const field_values = .{
@@ -18564,26 +18475,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// sentinel: ?*const anyopaque,
(try sema.optRefValue(info.sentinel)).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.array))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = array_field_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.vector => {
- const vector_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Vector", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const vector_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Vector");
const info = ty.arrayInfo(zcu);
const field_values = .{
@@ -18592,52 +18494,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// child: type,
info.elem_type.toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.vector))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = vector_field_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.optional => {
- const optional_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Optional", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const optional_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Optional");
const field_values = .{
// child: type,
ty.optionalChild(zcu).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.optional))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = optional_field_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.error_set => {
// Get the Error type
- const error_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Error", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const error_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Error");
// Build our list of Error values
// Optional value is only null if anyerror
@@ -18726,23 +18610,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} });
// Construct Type{ .error_set = errors_val }
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_set))).toIntern(),
.val = errors_val,
- } })));
+ })));
},
.error_union => {
- const error_union_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "ErrorUnion", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const error_union_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ErrorUnion");
const field_values = .{
// error_set: type,
@@ -18750,28 +18625,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// payload: type,
ty.errorUnionPayload(zcu).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_union))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = error_union_field_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.@"enum" => {
const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);
- const enum_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "EnumField", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const enum_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "EnumField");
const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);
for (enum_field_vals, 0..) |*field_val, tag_index| {
@@ -18858,16 +18724,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
- const type_enum_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Enum", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const type_enum_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Enum");
const field_values = .{
// tag_type: type,
@@ -18879,37 +18736,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// is_exhaustive: bool,
is_exhaustive.toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"enum"))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = type_enum_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.@"union" => {
- const type_union_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Union", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
-
- const union_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "UnionField", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const type_union_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Union");
+ const union_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "UnionField");
try ty.resolveLayout(pt); // Getting alignment requires type layout
const union_obj = zcu.typeToUnion(ty).?;
@@ -19004,16 +18842,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.val = if (ty.unionTagType(zcu)) |tag_ty| tag_ty.toIntern() else .none,
} });
- const container_layout_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const container_layout_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ContainerLayout");
const field_values = .{
// layout: ContainerLayout,
@@ -19026,37 +18855,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// decls: []const Declaration,
decls_val,
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"union"))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = type_union_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.@"struct" => {
- const type_struct_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Struct", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
-
- const struct_field_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "StructField", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const type_struct_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Struct");
+ const struct_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "StructField");
try ty.resolveLayout(pt); // Getting alignment requires type layout
@@ -19233,16 +19043,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
} else .none,
} });
- const container_layout_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const container_layout_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ContainerLayout");
const layout = ty.containerLayout(zcu);
@@ -19258,26 +19059,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// is_tuple: bool,
Value.makeBool(ty.isTuple(zcu)).toIntern(),
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"struct"))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = type_struct_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.@"opaque" => {
- const type_opaque_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Opaque", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const type_opaque_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Opaque");
try ty.resolveFields(pt);
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(zcu));
@@ -19286,14 +19078,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// decls: []const Declaration,
decls_val,
};
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = type_info_ty.toIntern(),
.tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"opaque"))).toIntern(),
.val = try pt.intern(.{ .aggregate = .{
.ty = type_opaque_ty.toIntern(),
.storage = .{ .elems = &field_values },
} }),
- } })));
+ })));
},
.frame => return sema.failWithUseOfAsync(block, src),
.@"anyframe" => return sema.failWithUseOfAsync(block, src),
@@ -19309,19 +19101,9 @@ fn typeInfoDecls(
) CompileError!InternPool.Index {
const pt = sema.pt;
const zcu = pt.zcu;
- const ip = &zcu.intern_pool;
const gpa = sema.gpa;
- const declaration_ty = t: {
- const nav = try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(zcu),
- try ip.getOrPutString(gpa, pt.tid, "Declaration", .no_embedded_nulls),
- ) orelse @panic("std.builtin.Type is corrupt");
- try sema.ensureNavResolved(src, nav);
- break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
- };
+ const declaration_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Declaration");
var decl_vals = std.ArrayList(InternPool.Index).init(gpa);
defer decl_vals.deinit();
@@ -20265,11 +20047,11 @@ fn retWithErrTracing(
else => true,
};
const gpa = sema.gpa;
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
- const return_err_fn = try pt.getBuiltin("returnError");
+ const return_err_fn = try sema.getBuiltin("returnError");
const args: [1]Air.Inst.Ref = .{err_return_trace};
if (!need_check) {
@@ -20805,19 +20587,32 @@ fn unionInit(
const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src);
const field_ty = Type.fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]);
const init = try sema.coerce(block, field_ty, uncasted_init, init_src);
+ _ = union_ty_src;
+ return unionInitFromEnumTag(sema, block, init_src, union_ty, field_index, init);
+}
+
+fn unionInitFromEnumTag(
+ sema: *Sema,
+ block: *Block,
+ init_src: LazySrcLoc,
+ union_ty: Type,
+ field_index: u32,
+ init: Air.Inst.Ref,
+) !Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
if (try sema.resolveValue(init)) |init_val| {
const tag_ty = union_ty.unionTagTypeHypothetical(zcu);
const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
- return Air.internedToRef((try pt.intern(.{ .un = .{
+ return Air.internedToRef((try pt.internUnion(.{
.ty = union_ty.toIntern(),
.tag = tag_val.toIntern(),
.val = init_val.toIntern(),
- } })));
+ })));
}
try sema.requireRuntimeBlock(block, init_src, null);
- _ = union_ty_src;
return block.addUnionInit(union_ty, field_index, init);
}
@@ -20949,11 +20744,11 @@ fn zirStructInit(
const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src);
if (try sema.resolveValue(init_inst)) |val| {
- const struct_val = Value.fromInterned(try pt.intern(.{ .un = .{
+ const struct_val = Value.fromInterned(try pt.internUnion(.{
.ty = resolved_ty.toIntern(),
.tag = tag_val.toIntern(),
.val = val.toIntern(),
- } }));
+ }));
const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);
const final_val = (try sema.resolveValue(final_val_inst)).?;
return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
@@ -21660,7 +21455,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
@@ -21873,7 +21668,6 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
-
try operand_ty.resolveLayout(pt);
const enum_ty = switch (operand_ty.zigTypeTag(zcu)) {
.enum_literal => {
@@ -21950,7 +21744,7 @@ fn zirReify(
},
},
};
- const type_info_ty = try pt.getBuiltinType("Type");
+ const type_info_ty = try sema.getBuiltinType("Type");
const uncasted_operand = try sema.resolveInst(extra.operand);
const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{
@@ -23152,7 +22946,7 @@ fn reifyStruct(
fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
const pt = sema.pt;
- const va_list_ty = try pt.getBuiltinType("VaList");
+ const va_list_ty = try sema.getBuiltinType("VaList");
const va_list_ptr = try pt.singleMutPtrType(va_list_ty);
const inst = try sema.resolveInst(zir_ref);
@@ -23191,7 +22985,7 @@ fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
const va_list_src = block.builtinCallArgSrc(extra.node, 0);
const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand);
- const va_list_ty = try sema.pt.getBuiltinType("VaList");
+ const va_list_ty = try sema.getBuiltinType("VaList");
try sema.requireRuntimeBlock(block, src, null);
return block.addTyOp(.c_va_copy, va_list_ty, va_list_ref);
@@ -23211,7 +23005,7 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
const src = block.nodeOffset(@bitCast(extended.operand));
- const va_list_ty = try sema.pt.getBuiltinType("VaList");
+ const va_list_ty = try sema.getBuiltinType("VaList");
try sema.requireRuntimeBlock(block, src, null);
return block.addInst(.{
.tag = .c_va_start,
@@ -24823,7 +24617,7 @@ fn resolveExportOptions(
const zcu = pt.zcu;
const gpa = sema.gpa;
const ip = &zcu.intern_pool;
- const export_options_ty = try pt.getBuiltinType("ExportOptions");
+ const export_options_ty = try sema.getBuiltinType("ExportOptions");
const air_ref = try sema.resolveInst(zir_ref);
const options = try sema.coerce(block, export_options_ty, air_ref, src);
@@ -24887,7 +24681,7 @@ fn resolveBuiltinEnum(
reason: NeededComptimeReason,
) CompileError!@field(std.builtin, name) {
const pt = sema.pt;
- const ty = try pt.getBuiltinType(name);
+ const ty = try sema.getBuiltinType(name);
const air_ref = try sema.resolveInst(zir_ref);
const coerced = try sema.coerce(block, ty, air_ref, src);
const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);
@@ -25656,7 +25450,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
const func = try sema.resolveInst(extra.callee);
- const modifier_ty = try pt.getBuiltinType("CallModifier");
+ const modifier_ty = try sema.getBuiltinType("CallModifier");
const air_ref = try sema.resolveInst(extra.modifier);
const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);
const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{
@@ -26782,7 +26576,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const body = sema.code.bodySlice(extra_index, body_len);
extra_index += body.len;
- const addrspace_ty = try pt.getBuiltinType("AddressSpace");
+ const addrspace_ty = try sema.getBuiltinType("AddressSpace");
const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, .{
.needed_comptime_reason = "addrspace must be comptime-known",
});
@@ -26793,7 +26587,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_addrspace_ref) blk: {
const addrspace_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const addrspace_ty = try pt.getBuiltinType("AddressSpace");
+ const addrspace_ty = try sema.getBuiltinType("AddressSpace");
const uncoerced_addrspace = sema.resolveInst(addrspace_ref) catch |err| switch (err) {
error.GenericPoison => break :blk null,
else => |e| return e,
@@ -26847,7 +26641,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const body = sema.code.bodySlice(extra_index, body_len);
extra_index += body.len;
- const cc_ty = try pt.getBuiltinType("CallingConvention");
+ const cc_ty = try sema.getBuiltinType("CallingConvention");
const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, .{
.needed_comptime_reason = "calling convention must be comptime-known",
});
@@ -26858,7 +26652,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_cc_ref) blk: {
const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const cc_ty = try pt.getBuiltinType("CallingConvention");
+ const cc_ty = try sema.getBuiltinType("CallingConvention");
const uncoerced_cc = sema.resolveInst(cc_ref) catch |err| switch (err) {
error.GenericPoison => break :blk null,
else => |e| return e,
@@ -27075,7 +26869,7 @@ fn resolvePrefetchOptions(
const zcu = pt.zcu;
const gpa = sema.gpa;
const ip = &zcu.intern_pool;
- const options_ty = try pt.getBuiltinType("PrefetchOptions");
+ const options_ty = try sema.getBuiltinType("PrefetchOptions");
const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node });
@@ -27148,7 +26942,7 @@ fn resolveExternOptions(
const gpa = sema.gpa;
const ip = &zcu.intern_pool;
const options_inst = try sema.resolveInst(zir_ref);
- const extern_options_ty = try pt.getBuiltinType("ExternOptions");
+ const extern_options_ty = try sema.getBuiltinType("ExternOptions");
const options = try sema.coerce(block, extern_options_ty, options_inst, src);
const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node });
@@ -27335,7 +27129,7 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr
// Values are handled here.
.calling_convention_c => {
- const callconv_ty = try pt.getBuiltinType("CallingConvention");
+ const callconv_ty = try sema.getBuiltinType("CallingConvention");
comptime assert(@intFromEnum(std.builtin.CallingConvention.C) == 1);
const val = try pt.intern(.{ .enum_tag = .{
.ty = callconv_ty.toIntern(),
@@ -27344,7 +27138,7 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr
return Air.internedToRef(val);
},
.calling_convention_inline => {
- const callconv_ty = try pt.getBuiltinType("CallingConvention");
+ const callconv_ty = try sema.getBuiltinType("CallingConvention");
comptime assert(@intFromEnum(std.builtin.CallingConvention.Inline) == 4);
const val = try pt.intern(.{ .enum_tag = .{
.ty = callconv_ty.toIntern(),
@@ -27353,7 +27147,7 @@ fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileErr
return Air.internedToRef(val);
},
};
- const ty = try pt.getBuiltinType(type_name);
+ const ty = try sema.getBuiltinType(type_name);
return Air.internedToRef(ty.toIntern());
}
@@ -27392,7 +27186,7 @@ fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
const uncoerced_hint = try sema.resolveInst(extra.operand);
const operand_src = block.builtinCallArgSrc(extra.node, 0);
- const hint_ty = try pt.getBuiltinType("BranchHint");
+ const hint_ty = try sema.getBuiltinType("BranchHint");
const coerced_hint = try sema.coerce(block, hint_ty, uncoerced_hint, operand_src);
const hint_val = try sema.resolveConstDefinedValue(block, operand_src, coerced_hint, .{
.needed_comptime_reason = "operand to '@branchHint' must be comptime-known",
@@ -27845,18 +27639,14 @@ fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
const zcu = pt.zcu;
if (zcu.panic_func_index == .none) {
- const fn_ref = try sema.analyzeNavVal(block, src, try pt.getBuiltinNav("panic"));
- const fn_val = try sema.resolveConstValue(block, src, fn_ref, .{
- .needed_comptime_reason = "panic handler must be comptime-known",
- });
- assert(fn_val.typeOf(zcu).zigTypeTag(zcu) == .@"fn");
- assert(try fn_val.typeOf(zcu).fnHasRuntimeBitsSema(pt));
- try zcu.ensureFuncBodyAnalysisQueued(fn_val.toIntern());
- zcu.panic_func_index = fn_val.toIntern();
+ zcu.panic_func_index = try sema.getPanicInnerFn(block, src, "call");
+ // Here, function body analysis must be queued up so that backends can
+ // make calls to this function.
+ try zcu.ensureFuncBodyAnalysisQueued(zcu.panic_func_index);
}
if (zcu.null_stack_trace == .none) {
- const stack_trace_ty = try pt.getBuiltinType("StackTrace");
+ const stack_trace_ty = try sema.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const target = zcu.getTarget();
const ptr_stack_trace_ty = try pt.ptrTypeSema(.{
@@ -27884,14 +27674,15 @@ fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.Pan
try sema.prepareSimplePanic(block, src);
- const panic_messages_ty = try pt.getBuiltinType("panic_messages");
+ const panic_ty = try sema.getBuiltinType("Panic");
+ const panic_messages_ty = try sema.getBuiltinInnerType(block, src, panic_ty, "Panic", "messages");
const msg_nav_index = (sema.namespaceLookup(
block,
LazySrcLoc.unneeded,
panic_messages_ty.getNamespaceIndex(zcu),
try zcu.intern_pool.getOrPutString(gpa, pt.tid, @tagName(panic_id), .no_embedded_nulls),
) catch |err| switch (err) {
- error.AnalysisFail => @panic("std.builtin.panic_messages is corrupt"),
+ error.AnalysisFail => return error.AnalysisFail,
error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
error.OutOfMemory => |e| return e,
}).?;
@@ -28015,7 +27806,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.
try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation);
}
-fn panicUnwrapError(
+fn addSafetyCheckUnwrapError(
sema: *Sema,
parent_block: *Block,
src: LazySrcLoc,
@@ -28023,12 +27814,8 @@ fn panicUnwrapError(
unwrap_err_tag: Air.Inst.Tag,
is_non_err_tag: Air.Inst.Tag,
) !void {
- const pt = sema.pt;
assert(!parent_block.is_comptime);
const ok = try parent_block.addUnOp(is_non_err_tag, operand);
- if (!pt.zcu.comp.formatted_panics) {
- return sema.addSafetyCheck(parent_block, src, ok, .unwrap_error);
- }
const gpa = sema.gpa;
var fail_block: Block = .{
@@ -28044,21 +27831,26 @@ fn panicUnwrapError(
defer fail_block.instructions.deinit(gpa);
- {
- if (!pt.zcu.backendSupportsFeature(.panic_unwrap_error)) {
- _ = try fail_block.addNoOp(.trap);
- } else {
- const panic_fn = try sema.pt.getBuiltin("panicUnwrapError");
- const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
- const err_return_trace = try sema.getErrorReturnTrace(&fail_block);
- const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
- try sema.callBuiltin(&fail_block, src, panic_fn, .auto, &args, .@"safety check");
- }
- }
+ const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
+ try safetyPanicUnwrapError(sema, &fail_block, src, err);
+
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
}
-fn panicIndexOutOfBounds(
+fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.Inst.Ref) !void {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ if (!zcu.backendSupportsFeature(.panic_fn)) {
+ _ = try block.addNoOp(.trap);
+ } else {
+ const panic_fn = try getPanicInnerFn(sema, block, src, "unwrapError");
+ const err_return_trace = try sema.getErrorReturnTrace(block);
+ const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
+ try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
+ }
+}
+
+fn addSafetyCheckIndexOob(
sema: *Sema,
parent_block: *Block,
src: LazySrcLoc,
@@ -28068,13 +27860,10 @@ fn panicIndexOutOfBounds(
) !void {
assert(!parent_block.is_comptime);
const ok = try parent_block.addBinOp(cmp_op, index, len);
- if (!sema.pt.zcu.comp.formatted_panics) {
- return sema.addSafetyCheck(parent_block, src, ok, .index_out_of_bounds);
- }
- try sema.safetyCheckFormatted(parent_block, src, ok, "panicOutOfBounds", &.{ index, len });
+ return addSafetyCheckCall(sema, parent_block, src, ok, "outOfBounds", &.{ index, len });
}
-fn panicInactiveUnionField(
+fn addSafetyCheckInactiveUnionField(
sema: *Sema,
parent_block: *Block,
src: LazySrcLoc,
@@ -28083,13 +27872,10 @@ fn panicInactiveUnionField(
) !void {
assert(!parent_block.is_comptime);
const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
- if (!sema.pt.zcu.comp.formatted_panics) {
- return sema.addSafetyCheck(parent_block, src, ok, .inactive_union_field);
- }
- try sema.safetyCheckFormatted(parent_block, src, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag });
+ return addSafetyCheckCall(sema, parent_block, src, ok, "inactiveUnionField", &.{ active_tag, wanted_tag });
}
-fn panicSentinelMismatch(
+fn addSafetyCheckSentinelMismatch(
sema: *Sema,
parent_block: *Block,
src: LazySrcLoc,
@@ -28114,8 +27900,7 @@ fn panicSentinelMismatch(
};
const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {
- const eql =
- try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
+ const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
break :ok try parent_block.addInst(.{
.tag = .reduce,
.data = .{ .reduce = .{
@@ -28128,24 +27913,23 @@ fn panicSentinelMismatch(
break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
};
- if (!pt.zcu.comp.formatted_panics) {
- return sema.addSafetyCheck(parent_block, src, ok, .sentinel_mismatch);
- }
- try sema.safetyCheckFormatted(parent_block, src, ok, "panicSentinelMismatch", &.{ expected_sentinel, actual_sentinel });
+ return addSafetyCheckCall(sema, parent_block, src, ok, "sentinelMismatch", &.{
+ expected_sentinel, actual_sentinel,
+ });
}
-fn safetyCheckFormatted(
+fn addSafetyCheckCall(
sema: *Sema,
parent_block: *Block,
src: LazySrcLoc,
ok: Air.Inst.Ref,
- func: []const u8,
+ func_name: []const u8,
args: []const Air.Inst.Ref,
-) CompileError!void {
+) !void {
+ assert(!parent_block.is_comptime);
+ const gpa = sema.gpa;
const pt = sema.pt;
const zcu = pt.zcu;
- assert(zcu.comp.formatted_panics);
- const gpa = sema.gpa;
var fail_block: Block = .{
.parent = parent_block,
@@ -28160,12 +27944,13 @@ fn safetyCheckFormatted(
defer fail_block.instructions.deinit(gpa);
- if (!zcu.backendSupportsFeature(.safety_check_formatted)) {
+ if (!zcu.backendSupportsFeature(.panic_fn)) {
_ = try fail_block.addNoOp(.trap);
} else {
- const panic_fn = try pt.getBuiltin(func);
- try sema.callBuiltin(&fail_block, src, panic_fn, .auto, args, .@"safety check");
+ const panic_fn = try getPanicInnerFn(sema, &fail_block, src, func_name);
+ try sema.callBuiltin(&fail_block, src, Air.internedToRef(panic_fn), .auto, args, .@"safety check");
}
+
try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
}
@@ -29229,7 +29014,7 @@ fn unionFieldPtr(
// TODO would it be better if get_union_tag supported pointers to unions?
const union_val = try block.addTyOp(.load, union_ty, union_ptr);
const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_val);
- try sema.panicInactiveUnionField(block, src, active_tag, wanted_tag);
+ try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
}
if (field_ty.zigTypeTag(zcu) == .noreturn) {
_ = try block.addNoOp(.unreach);
@@ -29304,7 +29089,7 @@ fn unionFieldVal(
const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_byval);
- try sema.panicInactiveUnionField(block, src, active_tag, wanted_tag);
+ try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
}
if (field_ty.zigTypeTag(zcu) == .noreturn) {
_ = try block.addNoOp(.unreach);
@@ -29668,11 +29453,11 @@ fn elemValArray(
const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;
if (oob_safety and block.wantSafety()) {
- // Runtime check is only needed if unable to comptime check
+ // Runtime check is only needed if unable to comptime check.
if (maybe_index_val == null) {
const len_inst = try pt.intRef(Type.usize, array_len);
const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt;
- try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);
+ try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
}
}
@@ -29740,7 +29525,7 @@ fn elemPtrArray(
if (oob_safety and block.wantSafety() and offset == null) {
const len_inst = try pt.intRef(Type.usize, array_len);
const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt;
- try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);
+ try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
}
return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
@@ -29799,7 +29584,7 @@ fn elemValSlice(
else
try block.addTyOp(.slice_len, Type.usize, slice);
const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
- try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);
+ try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
}
return block.addBinOp(.slice_elem_val, slice, elem_index);
}
@@ -29859,7 +29644,7 @@ fn elemPtrSlice(
break :len try block.addTyOp(.slice_len, Type.usize, slice);
};
const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
- try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);
+ try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
}
return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
}
@@ -32891,7 +32676,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
return Value.fromInterned(try pt.intern(.{ .opt = .{
.ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
.val = if (opt_val) |val| (try pt.getCoerced(
- Value.fromInterned(try sema.refValue(val.toIntern())),
+ Value.fromInterned(try pt.refValue(val.toIntern())),
ptr_anyopaque_ty,
)).toIntern() else .none,
} }));
@@ -33667,11 +33452,7 @@ fn analyzeSlice(
assert(!block.is_comptime);
try sema.requireRuntimeBlock(block, src, runtime_src.?);
const ok = try block.addBinOp(.cmp_lte, start, end);
- if (!pt.zcu.comp.formatted_panics) {
- try sema.addSafetyCheck(block, src, ok, .start_index_greater_than_end);
- } else {
- try sema.safetyCheckFormatted(block, src, ok, "panicStartGreaterThanEnd", &.{ start, end });
- }
+ try sema.addSafetyCheckCall(block, src, ok, "startGreaterThanEnd", &.{ start, end });
}
const new_len = if (by_length)
try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
@@ -33726,11 +33507,11 @@ fn analyzeSlice(
else
end;
- try sema.panicIndexOutOfBounds(block, src, actual_end, actual_len, .cmp_lte);
+ try sema.addSafetyCheckIndexOob(block, src, actual_end, actual_len, .cmp_lte);
}
// requirement: result[new_len] == slice_sentinel
- try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
+ try sema.addSafetyCheckSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
}
return result;
};
@@ -33789,11 +33570,11 @@ fn analyzeSlice(
try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
else
end;
- try sema.panicIndexOutOfBounds(block, src, actual_end, len_inst, .cmp_lte);
+ try sema.addSafetyCheckIndexOob(block, src, actual_end, len_inst, .cmp_lte);
}
// requirement: start <= end
- try sema.panicIndexOutOfBounds(block, src, start, end, .cmp_lte);
+ try sema.addSafetyCheckIndexOob(block, src, start, end, .cmp_lte);
}
const result = try block.addInst(.{
.tag = .slice,
@@ -33807,7 +33588,7 @@ fn analyzeSlice(
});
if (block.wantSafety()) {
// requirement: result[new_len] == slice_sentinel
- try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
+ try sema.addSafetyCheckSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
}
return result;
}
@@ -35820,7 +35601,7 @@ pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
Type.fromInterned(fn_ty_info.return_type).isError(zcu))
{
// Ensure the type exists so that backends can assume that.
- _ = try pt.getBuiltinType("StackTrace");
+ _ = try sema.getBuiltinType("StackTrace");
}
for (0..fn_ty_info.param_types.len) |i| {
@@ -37688,11 +37469,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse
return null;
- const only = try pt.intern(.{ .un = .{
+ const only = try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = tag_val.toIntern(),
.val = val_val.toIntern(),
- } });
+ });
return Value.fromInterned(only);
},
@@ -37866,7 +37647,7 @@ pub fn analyzeAsAddressSpace(
) !std.builtin.AddressSpace {
const pt = sema.pt;
const zcu = pt.zcu;
- const addrspace_ty = try pt.getBuiltinType("AddressSpace");
+ const addrspace_ty = try sema.getBuiltinType("AddressSpace");
const coerced = try sema.coerce(block, addrspace_ty, air_ref, src);
const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{
.needed_comptime_reason = "address space must be comptime-known",
@@ -38849,7 +38630,7 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check:
sema.branch_hint = .cold;
}
- try sema.safetyPanic(block, src, .unreach);
+ try sema.safetyPanic(block, src, .reached_unreachable);
} else {
_ = try block.addNoOp(.unreach);
}
@@ -39123,3 +38904,70 @@ const loadComptimePtr = @import("Sema/comptime_ptr_access.zig").loadComptimePtr;
const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadResult;
const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr;
const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult;
+
+fn getPanicInnerFn(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ inner_name: []const u8,
+) !InternPool.Index {
+ const gpa = sema.gpa;
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+ const outer_ty = try sema.getBuiltinType("Panic");
+ const inner_name_ip = try ip.getOrPutString(gpa, pt.tid, inner_name, .no_embedded_nulls);
+ const opt_fn_ref = try namespaceLookupVal(sema, block, src, outer_ty.getNamespaceIndex(zcu), inner_name_ip);
+ const fn_ref = opt_fn_ref orelse return sema.fail(block, src, "std.builtin.Panic missing {s}", .{inner_name});
+ const fn_val = try sema.resolveConstValue(block, src, fn_ref, .{
+ .needed_comptime_reason = "panic handler must be comptime-known",
+ });
+ if (fn_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
+ return sema.fail(block, src, "std.builtin.Panic.{s} is not a function", .{inner_name});
+ }
+ // Better not to queue up function body analysis because the function might be generic, and
+ // the semantic analysis for the call will already queue if necessary.
+ return fn_val.toIntern();
+}
+
+fn getBuiltinType(sema: *Sema, name: []const u8) SemaError!Type {
+ const pt = sema.pt;
+ const ty_inst = try sema.getBuiltin(name);
+ const ty = Type.fromInterned(ty_inst.toInterned() orelse @panic("std.builtin is corrupt"));
+ try ty.resolveFully(pt);
+ return ty;
+}
+
+fn getBuiltinInnerType(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ outer_ty: Type,
+ /// Relative to "std.builtin".
+ compile_error_parent_name: []const u8,
+ inner_name: []const u8,
+) !Type {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+ const gpa = sema.gpa;
+ const inner_name_ip = try ip.getOrPutString(gpa, pt.tid, inner_name, .no_embedded_nulls);
+ const opt_nav = try sema.namespaceLookup(block, src, outer_ty.getNamespaceIndex(zcu), inner_name_ip);
+ const nav = opt_nav orelse return sema.fail(block, src, "std.builtin.{s} missing {s}", .{
+ compile_error_parent_name, inner_name,
+ });
+ try sema.ensureNavResolved(src, nav);
+ const val = Value.fromInterned(ip.getNav(nav).status.resolved.val);
+ const ty = val.toType();
+ try ty.resolveFully(pt);
+ return ty;
+}
+
+fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {
+ const pt = sema.pt;
+ const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
+ const nav = try pt.getBuiltinNav(name);
+ try pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?);
+ return Air.internedToRef(ip.getNav(nav).status.resolved.val);
+}
diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig
@@ -613,11 +613,11 @@ const PackValueBits = struct {
pack.bit_offset = prev_bit_offset;
break :backing;
}
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ return Value.fromInterned(try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = .none,
.val = backing_val.toIntern(),
- } }));
+ }));
}
const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu));
@@ -658,21 +658,21 @@ const PackValueBits = struct {
continue;
}
const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx);
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ return Value.fromInterned(try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = tag_val.toIntern(),
.val = field_val.toIntern(),
- } }));
+ }));
}
// No field could represent the value. Just do whatever happens when we try to read
// the backing type - either `undefined` or `error.ReinterpretDeclRef`.
const backing_val = try pack.get(backing_ty);
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ return Value.fromInterned(try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = .none,
.val = backing_val.toIntern(),
- } }));
+ }));
},
else => return pack.primitive(ty),
}
diff --git a/src/Type.zig b/src/Type.zig
@@ -2677,11 +2677,11 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
const only_field_ty = union_obj.field_types.get(ip)[0];
const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse
return null;
- const only = try pt.intern(.{ .un = .{
+ const only = try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = tag_val.toIntern(),
.val = val_val.toIntern(),
- } });
+ });
return Value.fromInterned(only);
},
.opaque_type => return null,
diff --git a/src/Value.zig b/src/Value.zig
@@ -713,11 +713,11 @@ pub fn readFromMemory(
const union_size = ty.abiSize(zcu);
const array_ty = try zcu.arrayType(.{ .len = union_size, .child = .u8_type });
const val = (try readFromMemory(array_ty, zcu, buffer, arena)).toIntern();
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ return Value.fromInterned(try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = .none,
.val = val,
- } }));
+ }));
},
.@"packed" => {
const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8;
@@ -860,11 +860,11 @@ pub fn readFromPackedMemory(
.@"packed" => {
const backing_ty = try ty.unionBackingType(pt);
const val = (try readFromPackedMemory(backing_ty, pt, buffer, bit_offset, arena)).toIntern();
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ return Value.fromInterned(try pt.internUnion(.{
.ty = ty.toIntern(),
.tag = .none,
.val = val,
- } }));
+ }));
},
},
.pointer => {
@@ -4481,11 +4481,11 @@ pub fn resolveLazy(
return if (resolved_tag == un.tag and resolved_val == un.val)
val
else
- Value.fromInterned(try pt.intern(.{ .un = .{
+ Value.fromInterned(try pt.internUnion(.{
.ty = un.ty,
.tag = resolved_tag,
.val = resolved_val,
- } }));
+ }));
},
else => return val,
}
diff --git a/src/Zcu.zig b/src/Zcu.zig
@@ -220,7 +220,7 @@ generation: u32 = 0,
pub const PerThread = @import("Zcu/PerThread.zig");
pub const PanicId = enum {
- unreach,
+ reached_unreachable,
unwrap_null,
cast_to_null,
incorrect_alignment,
@@ -232,15 +232,10 @@ pub const PanicId = enum {
shr_overflow,
divide_by_zero,
exact_division_remainder,
- inactive_union_field,
integer_part_out_of_bounds,
corrupt_switch,
shift_rhs_too_big,
invalid_enum_value,
- sentinel_mismatch,
- unwrap_error,
- index_out_of_bounds,
- start_index_greater_than_end,
for_len_mismatch,
memcpy_len_mismatch,
memcpy_alias,
@@ -2923,17 +2918,10 @@ pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u
}
pub const Feature = enum {
- /// When this feature is enabled, Sema will emit calls to `std.builtin.panic`
- /// for things like safety checks and unreachables. Otherwise traps will be emitted.
+ /// When this feature is enabled, Sema will emit calls to
+ /// `std.builtin.Panic` functions for things like safety checks and
+ /// unreachables. Otherwise traps will be emitted.
panic_fn,
- /// When this feature is enabled, Sema will emit calls to `std.builtin.panicUnwrapError`.
- /// This error message requires more advanced formatting, hence it being seperate from `panic_fn`.
- /// Otherwise traps will be emitted.
- panic_unwrap_error,
- /// When this feature is enabled, Sema will emit calls to the more complex panic functions
- /// that use formatting to add detail to error messages. Similar to `panic_unwrap_error`.
- /// Otherwise traps will be emitted.
- safety_check_formatted,
/// When this feature is enabled, Sema will insert tracer functions for gathering a stack
/// trace for error returns.
error_return_trace,
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
@@ -1,6 +1,32 @@
//! This type provides a wrapper around a `*Zcu` for uses which require a thread `Id`.
//! Any operation which mutates `InternPool` state lives here rather than on `Zcu`.
+const Air = @import("../Air.zig");
+const Allocator = std.mem.Allocator;
+const assert = std.debug.assert;
+const Ast = std.zig.Ast;
+const AstGen = std.zig.AstGen;
+const BigIntConst = std.math.big.int.Const;
+const BigIntMutable = std.math.big.int.Mutable;
+const build_options = @import("build_options");
+const builtin = @import("builtin");
+const Cache = std.Build.Cache;
+const dev = @import("../dev.zig");
+const InternPool = @import("../InternPool.zig");
+const AnalUnit = InternPool.AnalUnit;
+const isUpDir = @import("../introspect.zig").isUpDir;
+const Liveness = @import("../Liveness.zig");
+const log = std.log.scoped(.zcu);
+const Module = @import("../Package.zig").Module;
+const Sema = @import("../Sema.zig");
+const std = @import("std");
+const target_util = @import("../target.zig");
+const trace = @import("../tracy.zig").trace;
+const Type = @import("../Type.zig");
+const Value = @import("../Value.zig");
+const Zcu = @import("../Zcu.zig");
+const Zir = std.zig.Zir;
+
zcu: *Zcu,
/// Dense, per-thread unique index.
@@ -2697,11 +2723,16 @@ pub fn reportRetryableFileError(
gop.value_ptr.* = err_msg;
}
-///Shortcut for calling `intern_pool.get`.
+/// Shortcut for calling `intern_pool.get`.
pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {
return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key);
}
+/// Shortcut for calling `intern_pool.getUnion`.
+pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index {
+ return pt.zcu.intern_pool.getUnion(pt.zcu.gpa, pt.tid, un);
+}
+
/// Essentially a shortcut for calling `intern_pool.getCoerced`.
/// However, this function also allows coercing `extern`s. The `InternPool` function can't do
/// this because it requires potentially pushing to the job queue.
@@ -2949,11 +2980,12 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value {
}
pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {
- return Value.fromInterned(try pt.intern(.{ .un = .{
+ const zcu = pt.zcu;
+ return Value.fromInterned(try zcu.intern_pool.getUnion(zcu.gpa, pt.tid, .{
.ty = union_ty.toIntern(),
.tag = tag.toIntern(),
.val = val.toIntern(),
- } }));
+ }));
}
/// This function casts the float representation down to the representation of the type, potentially
@@ -3069,14 +3101,6 @@ pub fn structPackedFieldBitOffset(
unreachable; // index out of bounds
}
-pub fn getBuiltin(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Air.Inst.Ref {
- const zcu = pt.zcu;
- const ip = &zcu.intern_pool;
- const nav = try pt.getBuiltinNav(name);
- pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?) catch @panic("std.builtin is corrupt");
- return Air.internedToRef(ip.getNav(nav).status.resolved.val);
-}
-
pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!InternPool.Nav.Index {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -3094,13 +3118,6 @@ pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Intern
return builtin_namespace.pub_decls.getKeyAdapted(name_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");
}
-pub fn getBuiltinType(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Type {
- const ty_inst = try pt.getBuiltin(name);
- const ty = Type.fromInterned(ty_inst.toInterned() orelse @panic("std.builtin is corrupt"));
- ty.resolveFully(pt) catch @panic("std.builtin is corrupt");
- return ty;
-}
-
pub fn navPtrType(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Allocator.Error!Type {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
@@ -3650,28 +3667,21 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
namespace.generation = zcu.generation;
}
-const Air = @import("../Air.zig");
-const Allocator = std.mem.Allocator;
-const assert = std.debug.assert;
-const Ast = std.zig.Ast;
-const AstGen = std.zig.AstGen;
-const BigIntConst = std.math.big.int.Const;
-const BigIntMutable = std.math.big.int.Mutable;
-const build_options = @import("build_options");
-const builtin = @import("builtin");
-const Cache = std.Build.Cache;
-const dev = @import("../dev.zig");
-const InternPool = @import("../InternPool.zig");
-const AnalUnit = InternPool.AnalUnit;
-const isUpDir = @import("../introspect.zig").isUpDir;
-const Liveness = @import("../Liveness.zig");
-const log = std.log.scoped(.zcu);
-const Module = @import("../Package.zig").Module;
-const Sema = @import("../Sema.zig");
-const std = @import("std");
-const target_util = @import("../target.zig");
-const trace = @import("../tracy.zig").trace;
-const Type = @import("../Type.zig");
-const Value = @import("../Value.zig");
-const Zcu = @import("../Zcu.zig");
-const Zir = std.zig.Zir;
+pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index {
+ const ptr_ty = (try pt.ptrTypeSema(.{
+ .child = pt.zcu.intern_pool.typeOf(val),
+ .flags = .{
+ .alignment = .none,
+ .is_const = true,
+ .address_space = .generic,
+ },
+ })).toIntern();
+ return pt.intern(.{ .ptr = .{
+ .ty = ptr_ty,
+ .base_addr = .{ .uav = .{
+ .val = val,
+ .orig_ty = ptr_ty,
+ } },
+ .byte_offset = 0,
+ } });
+}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
@@ -3848,13 +3848,13 @@ pub const Object = struct {
.undef => unreachable, // handled above
.simple_value => |simple_value| switch (simple_value) {
- .undefined,
- .void,
- .null,
- .empty_struct,
- .@"unreachable",
- .generic_poison,
- => unreachable, // non-runtime values
+ .undefined => unreachable, // non-runtime value
+ .void => unreachable, // non-runtime value
+ .null => unreachable, // non-runtime value
+ .empty_struct => unreachable, // non-runtime value
+ .@"unreachable" => unreachable, // non-runtime value
+ .generic_poison => unreachable, // non-runtime value
+
.false => .false,
.true => .true,
},
diff --git a/src/crash_report.zig b/src/crash_report.zig
@@ -13,11 +13,23 @@ const Sema = @import("Sema.zig");
const InternPool = @import("InternPool.zig");
const Zir = std.zig.Zir;
const Decl = Zcu.Decl;
+const dev = @import("dev.zig");
/// To use these crash report diagnostics, publish this panic in your main file
/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
-pub const panic = if (build_options.enable_debug_extensions) compilerPanic else std.builtin.default_panic;
+pub const Panic = if (build_options.enable_debug_extensions) struct {
+ pub const call = compilerPanic;
+ pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
+ pub const unwrapError = std.debug.FormattedPanic.unwrapError;
+ pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
+ pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
+ pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
+ pub const messages = std.debug.FormattedPanic.messages;
+} else if (dev.env == .bootstrap)
+ std.debug.SimplePanic
+else
+ std.debug.FormattedPanic;
/// Install signal handlers to identify crashes and report diagnostics.
pub fn initialize() void {
@@ -317,9 +329,6 @@ const PanicSwitch = struct {
/// until all panicking threads have dumped their traces.
var panicking = std.atomic.Value(u8).init(0);
- // Locked to avoid interleaving panic messages from multiple threads.
- var panic_mutex = std.Thread.Mutex{};
-
/// Tracks the state of the current panic. If the code within the
/// panic triggers a secondary panic, this allows us to recover.
threadlocal var panic_state_raw: PanicState = .{};
@@ -387,7 +396,7 @@ const PanicSwitch = struct {
state.recover_stage = .release_ref_count;
- panic_mutex.lock();
+ std.debug.lockStdErr();
state.recover_stage = .release_mutex;
@@ -447,7 +456,7 @@ const PanicSwitch = struct {
noinline fn releaseMutex(state: *volatile PanicState) noreturn {
state.recover_stage = .abort;
- panic_mutex.unlock();
+ std.debug.unlockStdErr();
goTo(releaseRefCount, .{state});
}
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
@@ -3230,7 +3230,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
self.zig_text_seg_index = try self.addSegment("__TEXT_ZIG", .{
.fileoff = off,
.filesize = filesize,
- .vmaddr = base_vmaddr + 0x8000000,
+ .vmaddr = base_vmaddr + 0x4000000,
.vmsize = filesize,
.prot = macho.PROT.READ | macho.PROT.EXEC,
});
diff --git a/src/main.zig b/src/main.zig
@@ -44,8 +44,7 @@ pub const std_options = .{
},
};
-// Crash report needs to override the panic handler
-pub const panic = crash_report.panic;
+pub const Panic = crash_report.Panic;
var wasi_preopens: fs.wasi.Preopens = undefined;
pub fn wasi_cwd() std.os.wasi.fd_t {
@@ -826,7 +825,6 @@ fn buildOutputType(
var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };
var have_version = false;
var compatibility_version: ?std.SemanticVersion = null;
- var formatted_panics: ?bool = null;
var function_sections = false;
var data_sections = false;
var no_builtin = false;
@@ -1537,9 +1535,11 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "-gdwarf64")) {
create_module.opts.debug_format = .{ .dwarf = .@"64" };
} else if (mem.eql(u8, arg, "-fformatted-panics")) {
- formatted_panics = true;
+ // Remove this after 0.15.0 is tagged.
+ warn("-fformatted-panics is deprecated and does nothing", .{});
} else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
- formatted_panics = false;
+ // Remove this after 0.15.0 is tagged.
+ warn("-fno-formatted-panics is deprecated and does nothing", .{});
} else if (mem.eql(u8, arg, "-fsingle-threaded")) {
mod_opts.single_threaded = true;
} else if (mem.eql(u8, arg, "-fno-single-threaded")) {
@@ -3405,7 +3405,6 @@ fn buildOutputType(
.force_undefined_symbols = force_undefined_symbols,
.stack_size = stack_size,
.image_base = image_base,
- .formatted_panics = formatted_panics,
.function_sections = function_sections,
.data_sections = data_sections,
.no_builtin = no_builtin,
diff --git a/src/mutable_value.zig b/src/mutable_value.zig
@@ -88,11 +88,11 @@ pub const MutableValue = union(enum) {
.ptr = (try s.ptr.intern(pt, arena)).toIntern(),
.len = (try s.len.intern(pt, arena)).toIntern(),
} }),
- .un => |u| try pt.intern(.{ .un = .{
+ .un => |u| try pt.internUnion(.{
.ty = u.ty,
.tag = u.tag,
.val = (try u.payload.intern(pt, arena)).toIntern(),
- } }),
+ }),
});
}
diff --git a/src/target.zig b/src/target.zig
@@ -586,14 +586,6 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
=> true,
else => false,
},
- .panic_unwrap_error => switch (backend) {
- .stage2_c, .stage2_llvm => true,
- else => false,
- },
- .safety_check_formatted => switch (backend) {
- .stage2_c, .stage2_llvm => true,
- else => false,
- },
.error_return_trace => switch (backend) {
.stage2_llvm => true,
else => false,
diff --git a/test/cases/exit.zig b/test/cases/exit.zig
@@ -1,5 +1,5 @@
pub fn main() void {}
// run
-// target=x86_64-linux,x86_64-macos,x86_64-windows,x86_64-plan9
+// target=x86_64-linux,x86_64-macos,x86_64-windows
//