authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-25 11:11:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-26 12:35:14-07:00
log4f8d244e7ea47a8cdb41496d51961ef4ba3ec2af
treec12d45a7aeadec432e0e40760923ac3c6ea937bc
parent04e694ad116ad2706328c13ce3643347330a861f

remove formatted panics

implements #17969

17 files changed, 634 insertions(+), 744 deletions(-)

lib/compiler_rt/common.zig+2-4
...@@ -77,11 +77,9 @@ pub const want_sparc_abi = builtin.cpu.arch.isSPARC();...@@ -77,11 +77,9 @@ pub const want_sparc_abi = builtin.cpu.arch.isSPARC();
7777
78// Avoid dragging in the runtime safety mechanisms into this .o file,78// Avoid dragging in the runtime safety mechanisms into this .o file,
79// unless we're trying to test compiler-rt.79// unless we're trying to test compiler-rt.
80pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {80pub fn panic(cause: std.builtin.PanicCause, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
81 _ = error_return_trace;
82 if (builtin.is_test) {81 if (builtin.is_test) {
83 @branchHint(.cold);82 std.debug.defaultPanic(cause, error_return_trace, ret_addr orelse @returnAddress());
84 std.debug.panic("{s}", .{msg});
85 } else {83 } else {
86 unreachable;84 unreachable;
87 }85 }
lib/std/builtin.zig+49-164
...@@ -763,181 +763,66 @@ pub const TestFn = struct {...@@ -763,181 +763,66 @@ pub const TestFn = struct {
763763
764/// This function type is used by the Zig language code generation and764/// This function type is used by the Zig language code generation and
765/// therefore must be kept in sync with the compiler implementation.765/// therefore must be kept in sync with the compiler implementation.
766pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn;766pub const PanicFn = fn (PanicCause, ?*StackTrace, ?usize) noreturn;
767767
768/// This function is used by the Zig language code generation and768/// The entry point for auto-generated calls by the compiler.
769/// therefore must be kept in sync with the compiler implementation.
770pub const panic: PanicFn = if (@hasDecl(root, "panic"))769pub const panic: PanicFn = if (@hasDecl(root, "panic"))
771 root.panic770 root.panic
772else if (@hasDecl(root, "os") and @hasDecl(root.os, "panic"))771else if (@hasDecl(root, "os") and @hasDecl(root.os, "panic"))
773 root.os.panic772 root.os.panic
774else773else
775 default_panic;774 std.debug.defaultPanic;
776775
777/// This function is used by the Zig language code generation and776/// This data structure is used by the Zig language code generation and
778/// therefore must be kept in sync with the compiler implementation.777/// therefore must be kept in sync with the compiler implementation.
779pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr: ?usize) noreturn {778pub const PanicCause = union(enum) {
780 @branchHint(.cold);779 reached_unreachable,
781780 unwrap_null,
782 // For backends that cannot handle the language features depended on by the781 cast_to_null,
783 // default panic handler, we have a simpler panic handler:782 incorrect_alignment,
784 if (builtin.zig_backend == .stage2_wasm or783 invalid_error_code,
785 builtin.zig_backend == .stage2_arm or784 cast_truncated_data,
786 builtin.zig_backend == .stage2_aarch64 or785 negative_to_unsigned,
787 builtin.zig_backend == .stage2_x86 or786 integer_overflow,
788 (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or787 shl_overflow,
789 builtin.zig_backend == .stage2_sparc64 or788 shr_overflow,
790 builtin.zig_backend == .stage2_spirv64)789 divide_by_zero,
791 {790 exact_division_remainder,
792 while (true) {791 inactive_union_field: InactiveUnionField,
793 @breakpoint();792 integer_part_out_of_bounds,
794 }793 corrupt_switch,
795 }794 shift_rhs_too_big,
796795 invalid_enum_value,
797 if (builtin.zig_backend == .stage2_riscv64) {796 sentinel_mismatch_usize: SentinelMismatchUsize,
798 std.debug.print("panic: {s}\n", .{msg});797 sentinel_mismatch_other,
799 @breakpoint();798 unwrap_error: anyerror,
800 std.posix.exit(127);799 index_out_of_bounds: IndexOutOfBounds,
801 }800 start_index_greater_than_end: StartIndexGreaterThanEnd,
802801 for_len_mismatch,
803 switch (builtin.os.tag) {802 memcpy_len_mismatch,
804 .freestanding => {803 memcpy_alias,
805 while (true) {804 noreturn_returned,
806 @breakpoint();805 explicit_call: []const u8,
807 }806
808 },807 pub const IndexOutOfBounds = struct {
809 .wasi => {808 index: usize,
810 std.debug.print("{s}", .{msg});809 len: usize,
811 std.posix.abort();810 };
812 },
813 .uefi => {
814 const uefi = std.os.uefi;
815
816 const Formatter = struct {
817 pub fn fmt(exit_msg: []const u8, out: []u16) ![:0]u16 {
818 var u8_buf: [256]u8 = undefined;
819 const slice = try std.fmt.bufPrint(&u8_buf, "err: {s}\r\n", .{exit_msg});
820 // We pass len - 1 because we need to add a null terminator after
821 const len = try std.unicode.utf8ToUtf16Le(out[0 .. out.len - 1], slice);
822
823 out[len] = 0;
824
825 return out[0..len :0];
826 }
827 };
828
829 const ExitData = struct {
830 pub fn create_exit_data(exit_msg: [:0]u16, exit_size: *usize) ![*:0]u16 {
831 // Need boot services for pool allocation
832 if (uefi.system_table.boot_services == null) {
833 return error.BootServicesUnavailable;
834 }
835
836 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
837 const exit_data: []u16 = try uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1);
838
839 @memcpy(exit_data[0 .. exit_msg.len + 1], exit_msg[0 .. exit_msg.len + 1]);
840 exit_size.* = exit_msg.len + 1;
841
842 return @as([*:0]u16, @ptrCast(exit_data.ptr));
843 }
844 };
845
846 var buf: [256]u16 = undefined;
847 const utf16 = Formatter.fmt(msg, &buf) catch null;
848
849 var exit_size: usize = 0;
850 const exit_data = if (utf16) |u|
851 ExitData.create_exit_data(u, &exit_size) catch null
852 else
853 null;
854
855 if (utf16) |str| {
856 // Output to both std_err and con_out, as std_err is easier
857 // to read in stuff like QEMU at times, but, unlike con_out,
858 // isn't visible on actual hardware if directly booted into
859 inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
860 if (o) |out| {
861 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
862 _ = out.outputString(str);
863 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
864 }
865 }
866 }
867
868 if (uefi.system_table.boot_services) |bs| {
869 _ = bs.exit(uefi.handle, .Aborted, exit_size, exit_data);
870 }
871
872 // Didn't have boot_services, just fallback to whatever.
873 std.posix.abort();
874 },
875 .cuda, .amdhsa => std.posix.abort(),
876 .plan9 => {
877 var status: [std.os.plan9.ERRMAX]u8 = undefined;
878 const len = @min(msg.len, status.len - 1);
879 @memcpy(status[0..len], msg[0..len]);
880 status[len] = 0;
881 std.os.plan9.exits(status[0..len :0]);
882 },
883 else => {
884 const first_trace_addr = ret_addr orelse @returnAddress();
885 std.debug.panicImpl(error_return_trace, first_trace_addr, msg);
886 },
887 }
888}
889
890pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {
891 @branchHint(.cold);
892 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual });
893}
894
895pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
896 @branchHint(.cold);
897 std.debug.panicExtra(st, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
898}
899
900pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
901 @branchHint(.cold);
902 std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
903}
904811
905pub fn panicStartGreaterThanEnd(start: usize, end: usize) noreturn {812 pub const StartIndexGreaterThanEnd = struct {
906 @branchHint(.cold);813 start: usize,
907 std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });814 end: usize,
908}815 };
909816
910pub fn panicInactiveUnionField(active: anytype, wanted: @TypeOf(active)) noreturn {817 pub const SentinelMismatchUsize = struct {
911 @branchHint(.cold);818 expected: usize,
912 std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ @tagName(wanted), @tagName(active) });819 found: usize,
913}820 };
914821
915pub const panic_messages = struct {822 pub const InactiveUnionField = struct {
916 pub const unreach = "reached unreachable code";823 active: []const u8,
917 pub const unwrap_null = "attempt to use null value";824 accessed: []const u8,
918 pub const cast_to_null = "cast causes pointer to be null";825 };
919 pub const incorrect_alignment = "incorrect alignment";
920 pub const invalid_error_code = "invalid error code";
921 pub const cast_truncated_data = "integer cast truncated bits";
922 pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
923 pub const integer_overflow = "integer overflow";
924 pub const shl_overflow = "left shift overflowed bits";
925 pub const shr_overflow = "right shift overflowed bits";
926 pub const divide_by_zero = "division by zero";
927 pub const exact_division_remainder = "exact division produced remainder";
928 pub const inactive_union_field = "access of inactive union field";
929 pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
930 pub const corrupt_switch = "switch on corrupt value";
931 pub const shift_rhs_too_big = "shift amount is greater than the type size";
932 pub const invalid_enum_value = "invalid enum value";
933 pub const sentinel_mismatch = "sentinel mismatch";
934 pub const unwrap_error = "attempt to unwrap error";
935 pub const index_out_of_bounds = "index out of bounds";
936 pub const start_index_greater_than_end = "start index is larger than end index";
937 pub const for_len_mismatch = "for loop over objects with non-equal lengths";
938 pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
939 pub const memcpy_alias = "@memcpy arguments alias";
940 pub const noreturn_returned = "'noreturn' function returned";
941};826};
942827
943pub noinline fn returnError(st: *StackTrace) void {828pub noinline fn returnError(st: *StackTrace) void {
lib/std/debug.zig+228-66
...@@ -408,14 +408,15 @@ pub fn assertReadable(slice: []const volatile u8) void {...@@ -408,14 +408,15 @@ pub fn assertReadable(slice: []const volatile u8) void {
408 for (slice) |*byte| _ = byte.*;408 for (slice) |*byte| _ = byte.*;
409}409}
410410
411/// Equivalent to `@panic` but with a formatted message.
411pub fn panic(comptime format: []const u8, args: anytype) noreturn {412pub fn panic(comptime format: []const u8, args: anytype) noreturn {
412 @branchHint(.cold);413 @branchHint(.cold);
413414
414 panicExtra(@errorReturnTrace(), @returnAddress(), format, args);415 panicExtra(@errorReturnTrace(), @returnAddress(), format, args);
415}416}
416417
417/// `panicExtra` is useful when you want to print out an `@errorReturnTrace`418/// Equivalent to `@panic` but with a formatted message, and with an explicitly
418/// and also print out some values.419/// provided `@errorReturnTrace` and return address.
419pub fn panicExtra(420pub fn panicExtra(
420 trace: ?*std.builtin.StackTrace,421 trace: ?*std.builtin.StackTrace,
421 ret_addr: ?usize,422 ret_addr: ?usize,
...@@ -447,11 +448,104 @@ var panicking = std.atomic.Value(u8).init(0);...@@ -447,11 +448,104 @@ var panicking = std.atomic.Value(u8).init(0);
447/// This is used to catch and handle panics triggered by the panic handler.448/// This is used to catch and handle panics triggered by the panic handler.
448threadlocal var panic_stage: usize = 0;449threadlocal var panic_stage: usize = 0;
449450
450// `panicImpl` could be useful in implementing a custom panic handler which451// Dumps a stack trace to standard error, then aborts.
451// calls the default handler (on supported platforms)452//
452pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize, msg: []const u8) noreturn {453// This function avoids a dependency on formatted printing.
454pub fn defaultPanic(
455 cause: std.builtin.PanicCause,
456 trace: ?*const std.builtin.StackTrace,
457 first_trace_addr: ?usize,
458) noreturn {
453 @branchHint(.cold);459 @branchHint(.cold);
454460
461 // For backends that cannot handle the language features depended on by the
462 // default panic handler, we have a simpler panic handler:
463 if (builtin.zig_backend == .stage2_wasm or
464 builtin.zig_backend == .stage2_arm or
465 builtin.zig_backend == .stage2_aarch64 or
466 builtin.zig_backend == .stage2_x86 or
467 (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or
468 builtin.zig_backend == .stage2_sparc64 or
469 builtin.zig_backend == .stage2_spirv64)
470 {
471 @trap();
472 }
473
474 if (builtin.zig_backend == .stage2_riscv64) {
475 var buffer: [1000]u8 = undefined;
476 var i: usize = 0;
477 i += fmtPanicCause(buffer[i..], cause);
478 buffer[i] = '\n';
479 i += 1;
480 const msg = buffer[0..i];
481 lockStdErr();
482 io.getStdErr().writeAll(msg) catch {};
483 @trap();
484 }
485
486 switch (builtin.os.tag) {
487 .freestanding => {
488 @trap();
489 },
490 .wasi => {
491 // TODO: before merging my branch, unify this logic with the main panic logic
492 var buffer: [1000]u8 = undefined;
493 var i: usize = 0;
494 i += fmtPanicCause(buffer[i..], cause);
495 buffer[i] = '\n';
496 i += 1;
497 const msg = buffer[0..i];
498 lockStdErr();
499 io.getStdErr().writeAll(msg) catch {};
500 @trap();
501 },
502 .uefi => {
503 const uefi = std.os.uefi;
504
505 var buffer: [1000]u8 = undefined;
506 var i: usize = 0;
507 i += fmtBuf(buffer[i..], "panic: ");
508 i += fmtPanicCause(buffer[i..], cause);
509 i += fmtBuf(buffer[i..], "\r\n\x00");
510
511 var utf16_buffer: [1000]u16 = undefined;
512 const len = std.unicode.utf8ToUtf16Le(&utf16_buffer, buffer[0..i]) catch 0;
513 const exit_msg = utf16_buffer[0 .. len - 1 :0];
514
515 // Output to both std_err and con_out, as std_err is easier
516 // to read in stuff like QEMU at times, but, unlike con_out,
517 // isn't visible on actual hardware if directly booted into
518 inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
519 if (o) |out| {
520 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
521 _ = out.outputString(exit_msg);
522 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
523 }
524 }
525
526 if (uefi.system_table.boot_services) |bs| {
527 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
528 const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap();
529 @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator.
530 _ = bs.exit(uefi.handle, .Aborted, exit_msg.len + 1, exit_data);
531 }
532 @trap();
533 },
534 .cuda, .amdhsa => std.posix.abort(),
535 .plan9 => {
536 var buffer: [1000]u8 = undefined;
537 comptime assert(buffer.len > std.os.plan9.ERRMAX);
538 var i: usize = 0;
539 i += fmtPanicCause(buffer[i..], cause);
540 buffer[i] = '\n';
541 i += 1;
542 const len = @min(i, std.os.plan9.ERRMAX - 1);
543 buffer[len] = 0;
544 std.os.plan9.exits(buffer[0..len :0]);
545 },
546 else => {},
547 }
548
455 if (enable_segfault_handler) {549 if (enable_segfault_handler) {
456 // If a segfault happens while panicking, we want it to actually segfault, not trigger550 // If a segfault happens while panicking, we want it to actually segfault, not trigger
457 // the handler.551 // the handler.
...@@ -465,23 +559,29 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize...@@ -465,23 +559,29 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
465559
466 _ = panicking.fetchAdd(1, .seq_cst);560 _ = panicking.fetchAdd(1, .seq_cst);
467561
468 // Make sure to release the mutex when done
469 {562 {
470 lockStdErr();563 // This code avoids a dependency on formatted printing, the writer interface,
471 defer unlockStdErr();564 // and limits to only 1 syscall made to print the panic message to stderr.
472565 var buffer: [0x1000]u8 = undefined;
473 const stderr = io.getStdErr().writer();566 var i: usize = 0;
474 if (builtin.single_threaded) {567 if (builtin.single_threaded) {
475 stderr.print("panic: ", .{}) catch posix.abort();568 i += fmtBuf(buffer[i..], "panic: ");
476 } else {569 } else {
477 const current_thread_id = std.Thread.getCurrentId();570 i += fmtBuf(buffer[i..], "thread ");
478 stderr.print("thread {} panic: ", .{current_thread_id}) catch posix.abort();571 i += fmtInt10(buffer[i..], std.Thread.getCurrentId());
479 }572 i += fmtBuf(buffer[i..], " panic: ");
480 stderr.print("{s}\n", .{msg}) catch posix.abort();
481 if (trace) |t| {
482 dumpStackTrace(t.*);
483 }573 }
484 dumpCurrentStackTrace(first_trace_addr);574 i += fmtPanicCause(&buffer, cause);
575 buffer[i] = '\n';
576 i += 1;
577 const msg = buffer[0..i];
578
579 lockStdErr();
580 defer unlockStdErr();
581
582 io.getStdErr().writeAll(msg) catch posix.abort();
583 if (trace) |t| dumpStackTrace(t.*);
584 dumpCurrentStackTrace(first_trace_addr orelse @returnAddress());
485 }585 }
486586
487 waitForOtherThreadToFinishPanicking();587 waitForOtherThreadToFinishPanicking();
...@@ -489,20 +589,99 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize...@@ -489,20 +589,99 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
489 1 => {589 1 => {
490 panic_stage = 2;590 panic_stage = 2;
491591
492 // A panic happened while trying to print a previous panic message,592 // A panic happened while trying to print a previous panic message.
493 // we're still holding the mutex but that's fine as we're going to593 // We're still holding the mutex but that's fine as we're going to
494 // call abort()594 // call abort().
495 const stderr = io.getStdErr().writer();595 io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};
496 stderr.print("Panicked during a panic. Aborting.\n", .{}) catch posix.abort();
497 },
498 else => {
499 // Panicked while printing "Panicked during a panic."
500 },596 },
597 else => {}, // Panicked while printing the recursive panic message.
501 };598 };
502599
503 posix.abort();600 posix.abort();
504}601}
505602
603pub fn fmtPanicCause(buffer: []u8, cause: std.builtin.PanicCause) usize {
604 var i: usize = 0;
605
606 switch (cause) {
607 .reached_unreachable => i += fmtBuf(buffer[i..], "reached unreachable code"),
608 .unwrap_null => i += fmtBuf(buffer[i..], "attempt to use null value"),
609 .cast_to_null => i += fmtBuf(buffer[i..], "cast causes pointer to be null"),
610 .incorrect_alignment => i += fmtBuf(buffer[i..], "incorrect alignment"),
611 .invalid_error_code => i += fmtBuf(buffer[i..], "invalid error code"),
612 .cast_truncated_data => i += fmtBuf(buffer[i..], "integer cast truncated bits"),
613 .negative_to_unsigned => i += fmtBuf(buffer[i..], "attempt to cast negative value to unsigned integer"),
614 .integer_overflow => i += fmtBuf(buffer[i..], "integer overflow"),
615 .shl_overflow => i += fmtBuf(buffer[i..], "left shift overflowed bits"),
616 .shr_overflow => i += fmtBuf(buffer[i..], "right shift overflowed bits"),
617 .divide_by_zero => i += fmtBuf(buffer[i..], "division by zero"),
618 .exact_division_remainder => i += fmtBuf(buffer[i..], "exact division produced remainder"),
619 .inactive_union_field => |info| {
620 i += fmtBuf(buffer[i..], "access of union field '");
621 i += fmtBuf(buffer[i..], info.accessed);
622 i += fmtBuf(buffer[i..], "' while field '");
623 i += fmtBuf(buffer[i..], info.active);
624 i += fmtBuf(buffer[i..], "' is active");
625 },
626 .integer_part_out_of_bounds => i += fmtBuf(buffer[i..], "integer part of floating point value out of bounds"),
627 .corrupt_switch => i += fmtBuf(buffer[i..], "switch on corrupt value"),
628 .shift_rhs_too_big => i += fmtBuf(buffer[i..], "shift amount is greater than the type size"),
629 .invalid_enum_value => i += fmtBuf(buffer[i..], "invalid enum value"),
630 .sentinel_mismatch_usize => |mm| {
631 i += fmtBuf(buffer[i..], "sentinel mismatch: expected ");
632 i += fmtInt10(buffer[i..], mm.expected);
633 i += fmtBuf(buffer[i..], ", found ");
634 i += fmtInt10(buffer[i..], mm.found);
635 },
636 .sentinel_mismatch_other => i += fmtBuf(buffer[i..], "sentinel mismatch"),
637 .unwrap_error => |err| {
638 i += fmtBuf(buffer[i..], "attempt to unwrap error: ");
639 i += fmtBuf(buffer[i..], @errorName(err));
640 },
641 .index_out_of_bounds => |oob| {
642 i += fmtBuf(buffer[i..], "index ");
643 i += fmtInt10(buffer[i..], oob.index);
644 i += fmtBuf(buffer[i..], " exceeds length ");
645 i += fmtInt10(buffer[i..], oob.len);
646 },
647 .start_index_greater_than_end => |oob| {
648 i += fmtBuf(buffer[i..], "start index ");
649 i += fmtInt10(buffer[i..], oob.start);
650 i += fmtBuf(buffer[i..], " exceeds end index ");
651 i += fmtInt10(buffer[i..], oob.end);
652 },
653 .for_len_mismatch => i += fmtBuf(buffer[i..], "for loop over objects with non-equal lengths"),
654 .memcpy_len_mismatch => i += fmtBuf(buffer[i..], "@memcpy arguments have non-equal lengths"),
655 .memcpy_alias => i += fmtBuf(buffer[i..], "@memcpy arguments alias"),
656 .noreturn_returned => i += fmtBuf(buffer[i..], "'noreturn' function returned"),
657 .explicit_call => |msg| i += fmtBuf(buffer[i..], msg),
658 }
659
660 return i;
661}
662
663fn fmtBuf(out_buf: []u8, s: []const u8) usize {
664 @memcpy(out_buf[0..s.len], s);
665 return s.len;
666}
667
668fn fmtInt10(out_buf: []u8, integer_value: usize) usize {
669 var tmp_buf: [50]u8 = undefined;
670 var i: usize = tmp_buf.len;
671 var a: usize = integer_value;
672
673 while (true) {
674 i -= 1;
675 tmp_buf[i] = '0' + (a % 10);
676 a /= 10;
677 if (a == 0) break;
678 }
679
680 const result = tmp_buf[i..];
681 @memcpy(out_buf[0..result.len], result);
682 return result.len;
683}
684
506/// Must be called only after adding 1 to `panicking`. There are three callsites.685/// Must be called only after adding 1 to `panicking`. There are three callsites.
507fn waitForOtherThreadToFinishPanicking() void {686fn waitForOtherThreadToFinishPanicking() void {
508 if (panicking.fetchSub(1, .seq_cst) != 1) {687 if (panicking.fetchSub(1, .seq_cst) != 1) {
...@@ -1157,7 +1336,7 @@ pub const default_enable_segfault_handler = runtime_safety and have_segfault_han...@@ -1157,7 +1336,7 @@ pub const default_enable_segfault_handler = runtime_safety and have_segfault_han
11571336
1158pub fn maybeEnableSegfaultHandler() void {1337pub fn maybeEnableSegfaultHandler() void {
1159 if (enable_segfault_handler) {1338 if (enable_segfault_handler) {
1160 std.debug.attachSegfaultHandler();1339 attachSegfaultHandler();
1161 }1340 }
1162}1341}
11631342
...@@ -1289,46 +1468,29 @@ fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(windows.WIN...@@ -1289,46 +1468,29 @@ fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(windows.WIN
1289 }1468 }
1290}1469}
12911470
1292fn handleSegfaultWindowsExtra(1471fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) noreturn {
1293 info: *windows.EXCEPTION_POINTERS,1472 comptime assert(windows.CONTEXT != void);
1294 msg: u8,1473 nosuspend switch (panic_stage) {
1295 label: ?[]const u8,1474 0 => {
1296) noreturn {1475 panic_stage = 1;
1297 const exception_address = @intFromPtr(info.ExceptionRecord.ExceptionAddress);1476 _ = panicking.fetchAdd(1, .seq_cst);
1298 if (windows.CONTEXT != void) {1477
1299 nosuspend switch (panic_stage) {1478 {
1300 0 => {1479 lockStdErr();
1301 panic_stage = 1;1480 defer unlockStdErr();
1302 _ = panicking.fetchAdd(1, .seq_cst);
1303
1304 {
1305 lockStdErr();
1306 defer unlockStdErr();
1307
1308 dumpSegfaultInfoWindows(info, msg, label);
1309 }
13101481
1311 waitForOtherThreadToFinishPanicking();
1312 },
1313 else => {
1314 // panic mutex already locked
1315 dumpSegfaultInfoWindows(info, msg, label);1482 dumpSegfaultInfoWindows(info, msg, label);
1316 },1483 }
1317 };1484
1318 posix.abort();1485 waitForOtherThreadToFinishPanicking();
1319 } else {1486 },
1320 switch (msg) {1487 1 => {
1321 0 => panicImpl(null, exception_address, "{s}", label.?),1488 panic_stage = 2;
1322 1 => {1489 io.getStdErr().writeAll("aborting due to recursive panic\n") catch {};
1323 const format_item = "Segmentation fault at address 0x{x}";1490 },
1324 var buf: [format_item.len + 64]u8 = undefined; // 64 is arbitrary, but sufficiently large1491 else => {},
1325 const to_print = std.fmt.bufPrint(buf[0..buf.len], format_item, .{info.ExceptionRecord.ExceptionInformation[1]}) catch unreachable;1492 };
1326 panicImpl(null, exception_address, to_print);1493 posix.abort();
1327 },
1328 2 => panicImpl(null, exception_address, "Illegal Instruction"),
1329 else => unreachable,
1330 }
1331 }
1332}1494}
13331495
1334fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {1496fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void {
...@@ -1347,7 +1509,7 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {...@@ -1347,7 +1509,7 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
1347 const sp = asm (""1509 const sp = asm (""
1348 : [argc] "={rsp}" (-> usize),1510 : [argc] "={rsp}" (-> usize),
1349 );1511 );
1350 std.debug.print("{s} sp = 0x{x}\n", .{ prefix, sp });1512 print("{s} sp = 0x{x}\n", .{ prefix, sp });
1351}1513}
13521514
1353test "manage resources correctly" {1515test "manage resources correctly" {
lib/std/fmt.zig+4-8
...@@ -1197,7 +1197,7 @@ pub fn formatInt(...@@ -1197,7 +1197,7 @@ pub fn formatInt(
1197 if (base == 10) {1197 if (base == 10) {
1198 while (a >= 100) : (a = @divTrunc(a, 100)) {1198 while (a >= 100) : (a = @divTrunc(a, 100)) {
1199 index -= 2;1199 index -= 2;
1200 buf[index..][0..2].* = digits2(@as(usize, @intCast(a % 100)));1200 buf[index..][0..2].* = digits2(@intCast(a % 100));
1201 }1201 }
12021202
1203 if (a < 10) {1203 if (a < 10) {
...@@ -1205,13 +1205,13 @@ pub fn formatInt(...@@ -1205,13 +1205,13 @@ pub fn formatInt(
1205 buf[index] = '0' + @as(u8, @intCast(a));1205 buf[index] = '0' + @as(u8, @intCast(a));
1206 } else {1206 } else {
1207 index -= 2;1207 index -= 2;
1208 buf[index..][0..2].* = digits2(@as(usize, @intCast(a)));1208 buf[index..][0..2].* = digits2(@intCast(a));
1209 }1209 }
1210 } else {1210 } else {
1211 while (true) {1211 while (true) {
1212 const digit = a % base;1212 const digit = a % base;
1213 index -= 1;1213 index -= 1;
1214 buf[index] = digitToChar(@as(u8, @intCast(digit)), case);1214 buf[index] = digitToChar(@intCast(digit), case);
1215 a /= base;1215 a /= base;
1216 if (a == 0) break;1216 if (a == 0) break;
1217 }1217 }
...@@ -1242,11 +1242,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options...@@ -1242,11 +1242,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options
12421242
1243// Converts values in the range [0, 100) to a string.1243// Converts values in the range [0, 100) to a string.
1244pub fn digits2(value: usize) [2]u8 {1244pub fn digits2(value: usize) [2]u8 {
1245 return ("0001020304050607080910111213141516171819" ++1245 return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*;
1246 "2021222324252627282930313233343536373839" ++
1247 "4041424344454647484950515253545556575859" ++
1248 "6061626364656667686970717273747576777879" ++
1249 "8081828384858687888990919293949596979899")[value * 2 ..][0..2].*;
1250}1246}
12511247
1252const FormatDurationData = struct {1248const FormatDurationData = struct {
src/Compilation.zig-8
...@@ -195,7 +195,6 @@ job_queued_compiler_rt_obj: bool = false,...@@ -195,7 +195,6 @@ job_queued_compiler_rt_obj: bool = false,
195job_queued_fuzzer_lib: bool = false,195job_queued_fuzzer_lib: bool = false,
196job_queued_update_builtin_zig: bool,196job_queued_update_builtin_zig: bool,
197alloc_failure_occurred: bool = false,197alloc_failure_occurred: bool = false,
198formatted_panics: bool = false,
199last_update_was_cache_hit: bool = false,198last_update_was_cache_hit: bool = false,
200199
201c_source_files: []const CSourceFile,200c_source_files: []const CSourceFile,
...@@ -1088,7 +1087,6 @@ pub const CreateOptions = struct {...@@ -1088,7 +1087,6 @@ pub const CreateOptions = struct {
1088 /// executable this field is ignored.1087 /// executable this field is ignored.
1089 want_compiler_rt: ?bool = null,1088 want_compiler_rt: ?bool = null,
1090 want_lto: ?bool = null,1089 want_lto: ?bool = null,
1091 formatted_panics: ?bool = null,
1092 function_sections: bool = false,1090 function_sections: bool = false,
1093 data_sections: bool = false,1091 data_sections: bool = false,
1094 no_builtin: bool = false,1092 no_builtin: bool = false,
...@@ -1357,9 +1355,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1357,9 +1355,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1357 }1355 }
1358 }1356 }
13591357
1360 // TODO: https://github.com/ziglang/zig/issues/17969
1361 const formatted_panics = options.formatted_panics orelse (options.root_mod.optimize_mode == .Debug);
1362
1363 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);1358 const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
13641359
1365 // We put everything into the cache hash that *cannot be modified1360 // 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...@@ -1520,7 +1515,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1520 .verbose_link = options.verbose_link,1515 .verbose_link = options.verbose_link,
1521 .disable_c_depfile = options.disable_c_depfile,1516 .disable_c_depfile = options.disable_c_depfile,
1522 .reference_trace = options.reference_trace,1517 .reference_trace = options.reference_trace,
1523 .formatted_panics = formatted_panics,
1524 .time_report = options.time_report,1518 .time_report = options.time_report,
1525 .stack_report = options.stack_report,1519 .stack_report = options.stack_report,
1526 .test_filters = options.test_filters,1520 .test_filters = options.test_filters,
...@@ -1638,7 +1632,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1638,7 +1632,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1638 hash.addListOfBytes(options.test_filters);1632 hash.addListOfBytes(options.test_filters);
1639 hash.addOptionalBytes(options.test_name_prefix);1633 hash.addOptionalBytes(options.test_name_prefix);
1640 hash.add(options.skip_linker_dependencies);1634 hash.add(options.skip_linker_dependencies);
1641 hash.add(formatted_panics);
1642 hash.add(options.emit_h != null);1635 hash.add(options.emit_h != null);
1643 hash.add(error_limit);1636 hash.add(error_limit);
16441637
...@@ -2564,7 +2557,6 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2564,7 +2557,6 @@ fn addNonIncrementalStuffToCacheManifest(
2564 man.hash.addListOfBytes(comp.test_filters);2557 man.hash.addListOfBytes(comp.test_filters);
2565 man.hash.addOptionalBytes(comp.test_name_prefix);2558 man.hash.addOptionalBytes(comp.test_name_prefix);
2566 man.hash.add(comp.skip_linker_dependencies);2559 man.hash.add(comp.skip_linker_dependencies);
2567 man.hash.add(comp.formatted_panics);
2568 //man.hash.add(mod.emit_h != null);2560 //man.hash.add(mod.emit_h != null);
2569 man.hash.add(mod.error_limit);2561 man.hash.add(mod.error_limit);
2570 } else {2562 } else {
src/InternPool.zig+25-9
...@@ -7353,6 +7353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7353,6 +7353,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7353 .func_type => unreachable, // use getFuncType() instead7353 .func_type => unreachable, // use getFuncType() instead
7354 .@"extern" => unreachable, // use getExtern() instead7354 .@"extern" => unreachable, // use getExtern() instead
7355 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead7355 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
7356 .un => unreachable, // use getUnion instead
73567357
7357 .variable => |variable| {7358 .variable => |variable| {
7358 const has_init = variable.init != .none;7359 const has_init = variable.init != .none;
...@@ -7968,15 +7969,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7968,15 +7969,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7968 if (sentinel != .none) extra.appendAssumeCapacity(.{@intFromEnum(sentinel)});7969 if (sentinel != .none) extra.appendAssumeCapacity(.{@intFromEnum(sentinel)});
7969 },7970 },
79707971
7971 .un => |un| {
7972 assert(un.ty != .none);
7973 assert(un.val != .none);
7974 items.appendAssumeCapacity(.{
7975 .tag = .union_value,
7976 .data = try addExtra(extra, un),
7977 });
7978 },
7979
7980 .memoized_call => |memoized_call| {7972 .memoized_call => |memoized_call| {
7981 for (memoized_call.arg_values) |arg| assert(arg != .none);7973 for (memoized_call.arg_values) |arg| assert(arg != .none);
7982 try extra.ensureUnusedCapacity(@typeInfo(MemoizedCall).@"struct".fields.len +7974 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...@@ -7996,6 +7988,30 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7996 return gop.put();7988 return gop.put();
7997}7989}
79987990
7991pub fn getUnion(
7992 ip: *InternPool,
7993 gpa: Allocator,
7994 tid: Zcu.PerThread.Id,
7995 un: Key.Union,
7996) Allocator.Error!Index {
7997 var gop = try ip.getOrPutKey(gpa, tid, .{ .un = un });
7998 defer gop.deinit();
7999 if (gop == .existing) return gop.existing;
8000 const local = ip.getLocal(tid);
8001 const items = local.getMutableItems(gpa);
8002 const extra = local.getMutableExtra(gpa);
8003 try items.ensureUnusedCapacity(1);
8004
8005 assert(un.ty != .none);
8006 assert(un.val != .none);
8007 items.appendAssumeCapacity(.{
8008 .tag = .union_value,
8009 .data = try addExtra(extra, un),
8010 });
8011
8012 return gop.put();
8013}
8014
7999pub const UnionTypeInit = struct {8015pub const UnionTypeInit = struct {
8000 flags: packed struct {8016 flags: packed struct {
8001 runtime_tag: LoadedUnionType.RuntimeTag,8017 runtime_tag: LoadedUnionType.RuntimeTag,
src/Sema.zig+267-393
...@@ -4854,11 +4854,11 @@ fn validateUnionInit(...@@ -4854,11 +4854,11 @@ fn validateUnionInit(
4854 }4854 }
4855 block.instructions.shrinkRetainingCapacity(block_index);4855 block.instructions.shrinkRetainingCapacity(block_index);
48564856
4857 const union_val = try pt.intern(.{ .un = .{4857 const union_val = try pt.internUnion(.{
4858 .ty = union_ty.toIntern(),4858 .ty = union_ty.toIntern(),
4859 .tag = tag_val.toIntern(),4859 .tag = tag_val.toIntern(),
4860 .val = val.toIntern(),4860 .val = val.toIntern(),
4861 } });4861 });
4862 const union_init = Air.internedToRef(union_val);4862 const union_init = Air.internedToRef(union_val);
4863 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);4863 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
4864 return;4864 return;
...@@ -5830,8 +5830,6 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -5830,8 +5830,6 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5830 const src = block.nodeOffset(inst_data.src_node);5830 const src = block.nodeOffset(inst_data.src_node);
5831 const msg_inst = try sema.resolveInst(inst_data.operand);5831 const msg_inst = try sema.resolveInst(inst_data.operand);
58325832
5833 // `panicWithMsg` would perform this coercion for us, but we can get a better
5834 // source location if we do it here.
5835 const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));5833 const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
58365834
5837 if (block.is_comptime) {5835 if (block.is_comptime) {
...@@ -5844,7 +5842,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -5844,7 +5842,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5844 sema.branch_hint = .cold;5842 sema.branch_hint = .cold;
5845 }5843 }
58465844
5847 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");5845 try callPanic(sema, block, src, .explicit_call, coerced_msg, .@"@panic");
5848}5846}
58495847
5850fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {5848fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
...@@ -7325,6 +7323,31 @@ fn callBuiltin(...@@ -7325,6 +7323,31 @@ fn callBuiltin(
7325 );7323 );
7326}7324}
73277325
7326const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;
7327
7328fn callPanic(
7329 sema: *Sema,
7330 block: *Block,
7331 call_src: LazySrcLoc,
7332 tag: PanicCauseTag,
7333 payload: Air.Inst.Ref,
7334 call_operation: CallOperation,
7335) !void {
7336 const pt = sema.pt;
7337 if (!pt.zcu.backendSupportsFeature(.panic_fn)) {
7338 _ = try block.addNoOp(.trap);
7339 return;
7340 }
7341 const panic_cause_ty = try pt.getBuiltinType("PanicCause");
7342 const panic_cause = try block.addUnionInit(panic_cause_ty, @intFromEnum(tag), payload);
7343 const panic_fn = try pt.getBuiltin("panic");
7344 const err_return_trace = try sema.getErrorReturnTrace(block);
7345 const opt_usize_ty = try pt.optionalType(.usize_type);
7346 const null_usize = try pt.nullValue(opt_usize_ty);
7347 const args: [3]Air.Inst.Ref = .{ panic_cause, err_return_trace, Air.internedToRef(null_usize) };
7348 try sema.callBuiltin(block, call_src, panic_fn, .auto, &args, call_operation);
7349}
7350
7328const CallOperation = enum {7351const CallOperation = enum {
7329 call,7352 call,
7330 @"@call",7353 @"@call",
...@@ -9327,7 +9350,7 @@ fn analyzeErrUnionPayload(...@@ -9327,7 +9350,7 @@ fn analyzeErrUnionPayload(
9327 if (safety_check and block.wantSafety() and9350 if (safety_check and block.wantSafety() and
9328 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))9351 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))
9329 {9352 {
9330 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);9353 try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
9331 }9354 }
93329355
9333 return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);9356 return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);
...@@ -9411,7 +9434,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -9411,7 +9434,7 @@ fn analyzeErrUnionPayloadPtr(
9411 if (safety_check and block.wantSafety() and9434 if (safety_check and block.wantSafety() and
9412 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))9435 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu))
9413 {9436 {
9414 try sema.panicUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);9437 try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
9415 }9438 }
94169439
9417 if (initializing) {9440 if (initializing) {
...@@ -14190,7 +14213,6 @@ fn maybeErrorUnwrap(...@@ -14190,7 +14213,6 @@ fn maybeErrorUnwrap(
14190) !bool {14213) !bool {
14191 const pt = sema.pt;14214 const pt = sema.pt;
14192 const zcu = pt.zcu;14215 const zcu = pt.zcu;
14193 if (!zcu.backendSupportsFeature(.panic_unwrap_error)) return false;
1419414216
14195 const tags = sema.code.instructions.items(.tag);14217 const tags = sema.code.instructions.items(.tag);
14196 for (body) |inst| {14218 for (body) |inst| {
...@@ -14223,25 +14245,13 @@ fn maybeErrorUnwrap(...@@ -14223,25 +14245,13 @@ fn maybeErrorUnwrap(
14223 .as_node => try sema.zirAsNode(block, inst),14245 .as_node => try sema.zirAsNode(block, inst),
14224 .field_val => try sema.zirFieldVal(block, inst),14246 .field_val => try sema.zirFieldVal(block, inst),
14225 .@"unreachable" => {14247 .@"unreachable" => {
14226 if (!zcu.comp.formatted_panics) {14248 try callPanic(sema, block, operand_src, .unwrap_error, operand, .@"safety check");
14227 try sema.safetyPanic(block, operand_src, .unwrap_error);
14228 return true;
14229 }
14230
14231 const panic_fn = try pt.getBuiltin("panicUnwrapError");
14232 const err_return_trace = try sema.getErrorReturnTrace(block);
14233 const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };
14234 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
14235 return true;14249 return true;
14236 },14250 },
14237 .panic => {14251 .panic => {
14238 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;14252 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
14239 const msg_inst = try sema.resolveInst(inst_data.operand);14253 const msg_inst = try sema.resolveInst(inst_data.operand);
1424014254 try callPanic(sema, block, operand_src, .explicit_call, msg_inst, .@"@panic");
14241 const panic_fn = try pt.getBuiltin("panic");
14242 const err_return_trace = try sema.getErrorReturnTrace(block);
14243 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
14244 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
14245 return true;14255 return true;
14246 },14256 },
14247 else => unreachable,14257 else => unreachable,
...@@ -17388,9 +17398,6 @@ fn analyzeArithmetic(...@@ -17388,9 +17398,6 @@ fn analyzeArithmetic(
1738817398
17389 if (block.wantSafety() and want_safety and scalar_tag == .int) {17399 if (block.wantSafety() and want_safety and scalar_tag == .int) {
17390 if (zcu.backendSupportsFeature(.safety_checked_instructions)) {17400 if (zcu.backendSupportsFeature(.safety_checked_instructions)) {
17391 if (air_tag != air_tag_safe) {
17392 _ = try sema.preparePanicId(block, src, .integer_overflow);
17393 }
17394 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);17401 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
17395 } else {17402 } else {
17396 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {17403 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {
...@@ -18319,29 +18326,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18319,29 +18326,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18319 .undefined,18326 .undefined,
18320 .null,18327 .null,
18321 .enum_literal,18328 .enum_literal,
18322 => |type_info_tag| return Air.internedToRef((try pt.intern(.{ .un = .{18329 => |type_info_tag| return Air.internedToRef((try pt.internUnion(.{
18323 .ty = type_info_ty.toIntern(),18330 .ty = type_info_ty.toIntern(),
18324 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(type_info_tag))).toIntern(),18331 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(type_info_tag))).toIntern(),
18325 .val = .void_value,18332 .val = .void_value,
18326 } }))),18333 }))),
18327 .@"fn" => {18334 .@"fn" => {
18328 const fn_info_nav = try sema.namespaceLookup(18335 const fn_info_ty = try getInnerType(sema, block, src, type_info_ty, "Fn");
18329 block,18336 const param_info_ty = try getInnerType(sema, block, src, fn_info_ty, "Param");
18330 src,
18331 type_info_ty.getNamespaceIndex(zcu),
18332 try ip.getOrPutString(gpa, pt.tid, "Fn", .no_embedded_nulls),
18333 ) orelse @panic("std.builtin.Type is corrupt");
18334 try sema.ensureNavResolved(src, fn_info_nav);
18335 const fn_info_ty = Type.fromInterned(ip.getNav(fn_info_nav).status.resolved.val);
18336
18337 const param_info_nav = try sema.namespaceLookup(
18338 block,
18339 src,
18340 fn_info_ty.getNamespaceIndex(zcu),
18341 try ip.getOrPutString(gpa, pt.tid, "Param", .no_embedded_nulls),
18342 ) orelse @panic("std.builtin.Type is corrupt");
18343 try sema.ensureNavResolved(src, param_info_nav);
18344 const param_info_ty = Type.fromInterned(ip.getNav(param_info_nav).status.resolved.val);
1834518337
18346 const func_ty_info = zcu.typeToFunc(ty).?;18338 const func_ty_info = zcu.typeToFunc(ty).?;
18347 const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);18339 const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
...@@ -18425,25 +18417,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18425,25 +18417,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18425 // args: []const Fn.Param,18417 // args: []const Fn.Param,
18426 args_val,18418 args_val,
18427 };18419 };
18428 return Air.internedToRef((try pt.intern(.{ .un = .{18420 return Air.internedToRef((try pt.internUnion(.{
18429 .ty = type_info_ty.toIntern(),18421 .ty = type_info_ty.toIntern(),
18430 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"fn"))).toIntern(),18422 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"fn"))).toIntern(),
18431 .val = try pt.intern(.{ .aggregate = .{18423 .val = try pt.intern(.{ .aggregate = .{
18432 .ty = fn_info_ty.toIntern(),18424 .ty = fn_info_ty.toIntern(),
18433 .storage = .{ .elems = &field_values },18425 .storage = .{ .elems = &field_values },
18434 } }),18426 } }),
18435 } })));18427 })));
18436 },18428 },
18437 .int => {18429 .int => {
18438 const int_info_nav = try sema.namespaceLookup(18430 const int_info_ty = try getInnerType(sema, block, src, type_info_ty, "Int");
18439 block,
18440 src,
18441 type_info_ty.getNamespaceIndex(zcu),
18442 try ip.getOrPutString(gpa, pt.tid, "Int", .no_embedded_nulls),
18443 ) orelse @panic("std.builtin.Type is corrupt");
18444 try sema.ensureNavResolved(src, int_info_nav);
18445 const int_info_ty = Type.fromInterned(ip.getNav(int_info_nav).status.resolved.val);
18446
18447 const signedness_ty = try pt.getBuiltinType("Signedness");18431 const signedness_ty = try pt.getBuiltinType("Signedness");
18448 const info = ty.intInfo(zcu);18432 const info = ty.intInfo(zcu);
18449 const field_values = .{18433 const field_values = .{
...@@ -18452,37 +18436,30 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18452,37 +18436,30 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18452 // bits: u16,18436 // bits: u16,
18453 (try pt.intValue(Type.u16, info.bits)).toIntern(),18437 (try pt.intValue(Type.u16, info.bits)).toIntern(),
18454 };18438 };
18455 return Air.internedToRef((try pt.intern(.{ .un = .{18439 return Air.internedToRef((try pt.internUnion(.{
18456 .ty = type_info_ty.toIntern(),18440 .ty = type_info_ty.toIntern(),
18457 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.int))).toIntern(),18441 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.int))).toIntern(),
18458 .val = try pt.intern(.{ .aggregate = .{18442 .val = try pt.intern(.{ .aggregate = .{
18459 .ty = int_info_ty.toIntern(),18443 .ty = int_info_ty.toIntern(),
18460 .storage = .{ .elems = &field_values },18444 .storage = .{ .elems = &field_values },
18461 } }),18445 } }),
18462 } })));18446 })));
18463 },18447 },
18464 .float => {18448 .float => {
18465 const float_info_nav = try sema.namespaceLookup(18449 const float_info_ty = try getInnerType(sema, block, src, type_info_ty, "Float");
18466 block,
18467 src,
18468 type_info_ty.getNamespaceIndex(zcu),
18469 try ip.getOrPutString(gpa, pt.tid, "Float", .no_embedded_nulls),
18470 ) orelse @panic("std.builtin.Type is corrupt");
18471 try sema.ensureNavResolved(src, float_info_nav);
18472 const float_info_ty = Type.fromInterned(ip.getNav(float_info_nav).status.resolved.val);
1847318450
18474 const field_vals = .{18451 const field_vals = .{
18475 // bits: u16,18452 // bits: u16,
18476 (try pt.intValue(Type.u16, ty.bitSize(zcu))).toIntern(),18453 (try pt.intValue(Type.u16, ty.bitSize(zcu))).toIntern(),
18477 };18454 };
18478 return Air.internedToRef((try pt.intern(.{ .un = .{18455 return Air.internedToRef((try pt.internUnion(.{
18479 .ty = type_info_ty.toIntern(),18456 .ty = type_info_ty.toIntern(),
18480 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.float))).toIntern(),18457 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.float))).toIntern(),
18481 .val = try pt.intern(.{ .aggregate = .{18458 .val = try pt.intern(.{ .aggregate = .{
18482 .ty = float_info_ty.toIntern(),18459 .ty = float_info_ty.toIntern(),
18483 .storage = .{ .elems = &field_vals },18460 .storage = .{ .elems = &field_vals },
18484 } }),18461 } }),
18485 } })));18462 })));
18486 },18463 },
18487 .pointer => {18464 .pointer => {
18488 const info = ty.ptrInfo(zcu);18465 const info = ty.ptrInfo(zcu);
...@@ -18492,26 +18469,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18492,26 +18469,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18492 try Type.fromInterned(info.child).lazyAbiAlignment(pt);18469 try Type.fromInterned(info.child).lazyAbiAlignment(pt);
1849318470
18494 const addrspace_ty = try pt.getBuiltinType("AddressSpace");18471 const addrspace_ty = try pt.getBuiltinType("AddressSpace");
18495 const pointer_ty = t: {18472 const pointer_ty = try getInnerType(sema, block, src, type_info_ty, "Pointer");
18496 const nav = try sema.namespaceLookup(18473 const ptr_size_ty = try getInnerType(sema, block, src, pointer_ty, "Size");
18497 block,
18498 src,
18499 (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
18500 try ip.getOrPutString(gpa, pt.tid, "Pointer", .no_embedded_nulls),
18501 ) orelse @panic("std.builtin.Type is corrupt");
18502 try sema.ensureNavResolved(src, nav);
18503 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18504 };
18505 const ptr_size_ty = t: {
18506 const nav = try sema.namespaceLookup(
18507 block,
18508 src,
18509 pointer_ty.getNamespaceIndex(zcu),
18510 try ip.getOrPutString(gpa, pt.tid, "Size", .no_embedded_nulls),
18511 ) orelse @panic("std.builtin.Type is corrupt");
18512 try sema.ensureNavResolved(src, nav);
18513 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18514 };
1851518474
18516 const field_values = .{18475 const field_values = .{
18517 // size: Size,18476 // size: Size,
...@@ -18534,26 +18493,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18534,26 +18493,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18534 else => Value.fromInterned(info.sentinel),18493 else => Value.fromInterned(info.sentinel),
18535 })).toIntern(),18494 })).toIntern(),
18536 };18495 };
18537 return Air.internedToRef((try pt.intern(.{ .un = .{18496 return Air.internedToRef((try pt.internUnion(.{
18538 .ty = type_info_ty.toIntern(),18497 .ty = type_info_ty.toIntern(),
18539 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.pointer))).toIntern(),18498 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.pointer))).toIntern(),
18540 .val = try pt.intern(.{ .aggregate = .{18499 .val = try pt.intern(.{ .aggregate = .{
18541 .ty = pointer_ty.toIntern(),18500 .ty = pointer_ty.toIntern(),
18542 .storage = .{ .elems = &field_values },18501 .storage = .{ .elems = &field_values },
18543 } }),18502 } }),
18544 } })));18503 })));
18545 },18504 },
18546 .array => {18505 .array => {
18547 const array_field_ty = t: {18506 const array_field_ty = try getInnerType(sema, block, src, type_info_ty, "Array");
18548 const nav = try sema.namespaceLookup(
18549 block,
18550 src,
18551 type_info_ty.getNamespaceIndex(zcu),
18552 try ip.getOrPutString(gpa, pt.tid, "Array", .no_embedded_nulls),
18553 ) orelse @panic("std.builtin.Type is corrupt");
18554 try sema.ensureNavResolved(src, nav);
18555 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18556 };
1855718507
18558 const info = ty.arrayInfo(zcu);18508 const info = ty.arrayInfo(zcu);
18559 const field_values = .{18509 const field_values = .{
...@@ -18564,26 +18514,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18564,26 +18514,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18564 // sentinel: ?*const anyopaque,18514 // sentinel: ?*const anyopaque,
18565 (try sema.optRefValue(info.sentinel)).toIntern(),18515 (try sema.optRefValue(info.sentinel)).toIntern(),
18566 };18516 };
18567 return Air.internedToRef((try pt.intern(.{ .un = .{18517 return Air.internedToRef((try pt.internUnion(.{
18568 .ty = type_info_ty.toIntern(),18518 .ty = type_info_ty.toIntern(),
18569 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.array))).toIntern(),18519 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.array))).toIntern(),
18570 .val = try pt.intern(.{ .aggregate = .{18520 .val = try pt.intern(.{ .aggregate = .{
18571 .ty = array_field_ty.toIntern(),18521 .ty = array_field_ty.toIntern(),
18572 .storage = .{ .elems = &field_values },18522 .storage = .{ .elems = &field_values },
18573 } }),18523 } }),
18574 } })));18524 })));
18575 },18525 },
18576 .vector => {18526 .vector => {
18577 const vector_field_ty = t: {18527 const vector_field_ty = try getInnerType(sema, block, src, type_info_ty, "Vector");
18578 const nav = try sema.namespaceLookup(
18579 block,
18580 src,
18581 type_info_ty.getNamespaceIndex(zcu),
18582 try ip.getOrPutString(gpa, pt.tid, "Vector", .no_embedded_nulls),
18583 ) orelse @panic("std.builtin.Type is corrupt");
18584 try sema.ensureNavResolved(src, nav);
18585 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18586 };
1858718528
18588 const info = ty.arrayInfo(zcu);18529 const info = ty.arrayInfo(zcu);
18589 const field_values = .{18530 const field_values = .{
...@@ -18592,52 +18533,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18592,52 +18533,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18592 // child: type,18533 // child: type,
18593 info.elem_type.toIntern(),18534 info.elem_type.toIntern(),
18594 };18535 };
18595 return Air.internedToRef((try pt.intern(.{ .un = .{18536 return Air.internedToRef((try pt.internUnion(.{
18596 .ty = type_info_ty.toIntern(),18537 .ty = type_info_ty.toIntern(),
18597 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.vector))).toIntern(),18538 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.vector))).toIntern(),
18598 .val = try pt.intern(.{ .aggregate = .{18539 .val = try pt.intern(.{ .aggregate = .{
18599 .ty = vector_field_ty.toIntern(),18540 .ty = vector_field_ty.toIntern(),
18600 .storage = .{ .elems = &field_values },18541 .storage = .{ .elems = &field_values },
18601 } }),18542 } }),
18602 } })));18543 })));
18603 },18544 },
18604 .optional => {18545 .optional => {
18605 const optional_field_ty = t: {18546 const optional_field_ty = try getInnerType(sema, block, src, type_info_ty, "Optional");
18606 const nav = try sema.namespaceLookup(
18607 block,
18608 src,
18609 type_info_ty.getNamespaceIndex(zcu),
18610 try ip.getOrPutString(gpa, pt.tid, "Optional", .no_embedded_nulls),
18611 ) orelse @panic("std.builtin.Type is corrupt");
18612 try sema.ensureNavResolved(src, nav);
18613 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18614 };
1861518547
18616 const field_values = .{18548 const field_values = .{
18617 // child: type,18549 // child: type,
18618 ty.optionalChild(zcu).toIntern(),18550 ty.optionalChild(zcu).toIntern(),
18619 };18551 };
18620 return Air.internedToRef((try pt.intern(.{ .un = .{18552 return Air.internedToRef((try pt.internUnion(.{
18621 .ty = type_info_ty.toIntern(),18553 .ty = type_info_ty.toIntern(),
18622 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.optional))).toIntern(),18554 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.optional))).toIntern(),
18623 .val = try pt.intern(.{ .aggregate = .{18555 .val = try pt.intern(.{ .aggregate = .{
18624 .ty = optional_field_ty.toIntern(),18556 .ty = optional_field_ty.toIntern(),
18625 .storage = .{ .elems = &field_values },18557 .storage = .{ .elems = &field_values },
18626 } }),18558 } }),
18627 } })));18559 })));
18628 },18560 },
18629 .error_set => {18561 .error_set => {
18630 // Get the Error type18562 // Get the Error type
18631 const error_field_ty = t: {18563 const error_field_ty = try getInnerType(sema, block, src, type_info_ty, "Error");
18632 const nav = try sema.namespaceLookup(
18633 block,
18634 src,
18635 type_info_ty.getNamespaceIndex(zcu),
18636 try ip.getOrPutString(gpa, pt.tid, "Error", .no_embedded_nulls),
18637 ) orelse @panic("std.builtin.Type is corrupt");
18638 try sema.ensureNavResolved(src, nav);
18639 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18640 };
1864118564
18642 // Build our list of Error values18565 // Build our list of Error values
18643 // Optional value is only null if anyerror18566 // Optional value is only null if anyerror
...@@ -18726,23 +18649,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18726,23 +18649,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18726 } });18649 } });
1872718650
18728 // Construct Type{ .error_set = errors_val }18651 // Construct Type{ .error_set = errors_val }
18729 return Air.internedToRef((try pt.intern(.{ .un = .{18652 return Air.internedToRef((try pt.internUnion(.{
18730 .ty = type_info_ty.toIntern(),18653 .ty = type_info_ty.toIntern(),
18731 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_set))).toIntern(),18654 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_set))).toIntern(),
18732 .val = errors_val,18655 .val = errors_val,
18733 } })));18656 })));
18734 },18657 },
18735 .error_union => {18658 .error_union => {
18736 const error_union_field_ty = t: {18659 const error_union_field_ty = try getInnerType(sema, block, src, type_info_ty, "ErrorUnion");
18737 const nav = try sema.namespaceLookup(
18738 block,
18739 src,
18740 type_info_ty.getNamespaceIndex(zcu),
18741 try ip.getOrPutString(gpa, pt.tid, "ErrorUnion", .no_embedded_nulls),
18742 ) orelse @panic("std.builtin.Type is corrupt");
18743 try sema.ensureNavResolved(src, nav);
18744 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18745 };
1874618660
18747 const field_values = .{18661 const field_values = .{
18748 // error_set: type,18662 // error_set: type,
...@@ -18750,28 +18664,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18750,28 +18664,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18750 // payload: type,18664 // payload: type,
18751 ty.errorUnionPayload(zcu).toIntern(),18665 ty.errorUnionPayload(zcu).toIntern(),
18752 };18666 };
18753 return Air.internedToRef((try pt.intern(.{ .un = .{18667 return Air.internedToRef((try pt.internUnion(.{
18754 .ty = type_info_ty.toIntern(),18668 .ty = type_info_ty.toIntern(),
18755 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_union))).toIntern(),18669 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.error_union))).toIntern(),
18756 .val = try pt.intern(.{ .aggregate = .{18670 .val = try pt.intern(.{ .aggregate = .{
18757 .ty = error_union_field_ty.toIntern(),18671 .ty = error_union_field_ty.toIntern(),
18758 .storage = .{ .elems = &field_values },18672 .storage = .{ .elems = &field_values },
18759 } }),18673 } }),
18760 } })));18674 })));
18761 },18675 },
18762 .@"enum" => {18676 .@"enum" => {
18763 const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);18677 const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);
1876418678
18765 const enum_field_ty = t: {18679 const enum_field_ty = try getInnerType(sema, block, src, type_info_ty, "EnumField");
18766 const nav = try sema.namespaceLookup(
18767 block,
18768 src,
18769 type_info_ty.getNamespaceIndex(zcu),
18770 try ip.getOrPutString(gpa, pt.tid, "EnumField", .no_embedded_nulls),
18771 ) orelse @panic("std.builtin.Type is corrupt");
18772 try sema.ensureNavResolved(src, nav);
18773 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18774 };
1877518680
18776 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);18681 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);
18777 for (enum_field_vals, 0..) |*field_val, tag_index| {18682 for (enum_field_vals, 0..) |*field_val, tag_index| {
...@@ -18858,16 +18763,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18858,16 +18763,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1885818763
18859 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace.toOptional());18764 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
1886018765
18861 const type_enum_ty = t: {18766 const type_enum_ty = try getInnerType(sema, block, src, type_info_ty, "Enum");
18862 const nav = try sema.namespaceLookup(
18863 block,
18864 src,
18865 type_info_ty.getNamespaceIndex(zcu),
18866 try ip.getOrPutString(gpa, pt.tid, "Enum", .no_embedded_nulls),
18867 ) orelse @panic("std.builtin.Type is corrupt");
18868 try sema.ensureNavResolved(src, nav);
18869 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18870 };
1887118767
18872 const field_values = .{18768 const field_values = .{
18873 // tag_type: type,18769 // tag_type: type,
...@@ -18879,37 +18775,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18879,37 +18775,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18879 // is_exhaustive: bool,18775 // is_exhaustive: bool,
18880 is_exhaustive.toIntern(),18776 is_exhaustive.toIntern(),
18881 };18777 };
18882 return Air.internedToRef((try pt.intern(.{ .un = .{18778 return Air.internedToRef((try pt.internUnion(.{
18883 .ty = type_info_ty.toIntern(),18779 .ty = type_info_ty.toIntern(),
18884 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"enum"))).toIntern(),18780 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"enum"))).toIntern(),
18885 .val = try pt.intern(.{ .aggregate = .{18781 .val = try pt.intern(.{ .aggregate = .{
18886 .ty = type_enum_ty.toIntern(),18782 .ty = type_enum_ty.toIntern(),
18887 .storage = .{ .elems = &field_values },18783 .storage = .{ .elems = &field_values },
18888 } }),18784 } }),
18889 } })));18785 })));
18890 },18786 },
18891 .@"union" => {18787 .@"union" => {
18892 const type_union_ty = t: {18788 const type_union_ty = try getInnerType(sema, block, src, type_info_ty, "Union");
18893 const nav = try sema.namespaceLookup(18789 const union_field_ty = try getInnerType(sema, block, src, type_info_ty, "UnionField");
18894 block,
18895 src,
18896 type_info_ty.getNamespaceIndex(zcu),
18897 try ip.getOrPutString(gpa, pt.tid, "Union", .no_embedded_nulls),
18898 ) orelse @panic("std.builtin.Type is corrupt");
18899 try sema.ensureNavResolved(src, nav);
18900 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18901 };
18902
18903 const union_field_ty = t: {
18904 const nav = try sema.namespaceLookup(
18905 block,
18906 src,
18907 type_info_ty.getNamespaceIndex(zcu),
18908 try ip.getOrPutString(gpa, pt.tid, "UnionField", .no_embedded_nulls),
18909 ) orelse @panic("std.builtin.Type is corrupt");
18910 try sema.ensureNavResolved(src, nav);
18911 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
18912 };
1891318790
18914 try ty.resolveLayout(pt); // Getting alignment requires type layout18791 try ty.resolveLayout(pt); // Getting alignment requires type layout
18915 const union_obj = zcu.typeToUnion(ty).?;18792 const union_obj = zcu.typeToUnion(ty).?;
...@@ -19004,16 +18881,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19004,16 +18881,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19004 .val = if (ty.unionTagType(zcu)) |tag_ty| tag_ty.toIntern() else .none,18881 .val = if (ty.unionTagType(zcu)) |tag_ty| tag_ty.toIntern() else .none,
19005 } });18882 } });
1900618883
19007 const container_layout_ty = t: {18884 const container_layout_ty = try getBuiltinInnerType(sema, block, src, "Type", "ContainerLayout");
19008 const nav = try sema.namespaceLookup(
19009 block,
19010 src,
19011 (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
19012 try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
19013 ) orelse @panic("std.builtin.Type is corrupt");
19014 try sema.ensureNavResolved(src, nav);
19015 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19016 };
1901718885
19018 const field_values = .{18886 const field_values = .{
19019 // layout: ContainerLayout,18887 // layout: ContainerLayout,
...@@ -19026,37 +18894,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19026,37 +18894,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19026 // decls: []const Declaration,18894 // decls: []const Declaration,
19027 decls_val,18895 decls_val,
19028 };18896 };
19029 return Air.internedToRef((try pt.intern(.{ .un = .{18897 return Air.internedToRef((try pt.internUnion(.{
19030 .ty = type_info_ty.toIntern(),18898 .ty = type_info_ty.toIntern(),
19031 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"union"))).toIntern(),18899 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"union"))).toIntern(),
19032 .val = try pt.intern(.{ .aggregate = .{18900 .val = try pt.intern(.{ .aggregate = .{
19033 .ty = type_union_ty.toIntern(),18901 .ty = type_union_ty.toIntern(),
19034 .storage = .{ .elems = &field_values },18902 .storage = .{ .elems = &field_values },
19035 } }),18903 } }),
19036 } })));18904 })));
19037 },18905 },
19038 .@"struct" => {18906 .@"struct" => {
19039 const type_struct_ty = t: {18907 const type_struct_ty = try getInnerType(sema, block, src, type_info_ty, "Struct");
19040 const nav = try sema.namespaceLookup(18908 const struct_field_ty = try getInnerType(sema, block, src, type_info_ty, "StructField");
19041 block,
19042 src,
19043 type_info_ty.getNamespaceIndex(zcu),
19044 try ip.getOrPutString(gpa, pt.tid, "Struct", .no_embedded_nulls),
19045 ) orelse @panic("std.builtin.Type is corrupt");
19046 try sema.ensureNavResolved(src, nav);
19047 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19048 };
19049
19050 const struct_field_ty = t: {
19051 const nav = try sema.namespaceLookup(
19052 block,
19053 src,
19054 type_info_ty.getNamespaceIndex(zcu),
19055 try ip.getOrPutString(gpa, pt.tid, "StructField", .no_embedded_nulls),
19056 ) orelse @panic("std.builtin.Type is corrupt");
19057 try sema.ensureNavResolved(src, nav);
19058 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19059 };
1906018909
19061 try ty.resolveLayout(pt); // Getting alignment requires type layout18910 try ty.resolveLayout(pt); // Getting alignment requires type layout
1906218911
...@@ -19233,16 +19082,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19233,16 +19082,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19233 } else .none,19082 } else .none,
19234 } });19083 } });
1923519084
19236 const container_layout_ty = t: {19085 const container_layout_ty = try getInnerType(sema, block, src, type_info_ty, "ContainerLayout");
19237 const nav = try sema.namespaceLookup(
19238 block,
19239 src,
19240 (try pt.getBuiltinType("Type")).getNamespaceIndex(zcu),
19241 try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
19242 ) orelse @panic("std.builtin.Type is corrupt");
19243 try sema.ensureNavResolved(src, nav);
19244 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19245 };
1924619086
19247 const layout = ty.containerLayout(zcu);19087 const layout = ty.containerLayout(zcu);
1924819088
...@@ -19258,26 +19098,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19258,26 +19098,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19258 // is_tuple: bool,19098 // is_tuple: bool,
19259 Value.makeBool(ty.isTuple(zcu)).toIntern(),19099 Value.makeBool(ty.isTuple(zcu)).toIntern(),
19260 };19100 };
19261 return Air.internedToRef((try pt.intern(.{ .un = .{19101 return Air.internedToRef((try pt.internUnion(.{
19262 .ty = type_info_ty.toIntern(),19102 .ty = type_info_ty.toIntern(),
19263 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"struct"))).toIntern(),19103 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"struct"))).toIntern(),
19264 .val = try pt.intern(.{ .aggregate = .{19104 .val = try pt.intern(.{ .aggregate = .{
19265 .ty = type_struct_ty.toIntern(),19105 .ty = type_struct_ty.toIntern(),
19266 .storage = .{ .elems = &field_values },19106 .storage = .{ .elems = &field_values },
19267 } }),19107 } }),
19268 } })));19108 })));
19269 },19109 },
19270 .@"opaque" => {19110 .@"opaque" => {
19271 const type_opaque_ty = t: {19111 const type_opaque_ty = try getInnerType(sema, block, src, type_info_ty, "Opaque");
19272 const nav = try sema.namespaceLookup(
19273 block,
19274 src,
19275 type_info_ty.getNamespaceIndex(zcu),
19276 try ip.getOrPutString(gpa, pt.tid, "Opaque", .no_embedded_nulls),
19277 ) orelse @panic("std.builtin.Type is corrupt");
19278 try sema.ensureNavResolved(src, nav);
19279 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19280 };
1928119112
19282 try ty.resolveFields(pt);19113 try ty.resolveFields(pt);
19283 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(zcu));19114 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(zcu));
...@@ -19286,14 +19117,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19286,14 +19117,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19286 // decls: []const Declaration,19117 // decls: []const Declaration,
19287 decls_val,19118 decls_val,
19288 };19119 };
19289 return Air.internedToRef((try pt.intern(.{ .un = .{19120 return Air.internedToRef((try pt.internUnion(.{
19290 .ty = type_info_ty.toIntern(),19121 .ty = type_info_ty.toIntern(),
19291 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"opaque"))).toIntern(),19122 .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.builtin.TypeId.@"opaque"))).toIntern(),
19292 .val = try pt.intern(.{ .aggregate = .{19123 .val = try pt.intern(.{ .aggregate = .{
19293 .ty = type_opaque_ty.toIntern(),19124 .ty = type_opaque_ty.toIntern(),
19294 .storage = .{ .elems = &field_values },19125 .storage = .{ .elems = &field_values },
19295 } }),19126 } }),
19296 } })));19127 })));
19297 },19128 },
19298 .frame => return sema.failWithUseOfAsync(block, src),19129 .frame => return sema.failWithUseOfAsync(block, src),
19299 .@"anyframe" => return sema.failWithUseOfAsync(block, src),19130 .@"anyframe" => return sema.failWithUseOfAsync(block, src),
...@@ -19309,19 +19140,9 @@ fn typeInfoDecls(...@@ -19309,19 +19140,9 @@ fn typeInfoDecls(
19309) CompileError!InternPool.Index {19140) CompileError!InternPool.Index {
19310 const pt = sema.pt;19141 const pt = sema.pt;
19311 const zcu = pt.zcu;19142 const zcu = pt.zcu;
19312 const ip = &zcu.intern_pool;
19313 const gpa = sema.gpa;19143 const gpa = sema.gpa;
1931419144
19315 const declaration_ty = t: {19145 const declaration_ty = try getInnerType(sema, block, src, type_info_ty, "Declaration");
19316 const nav = try sema.namespaceLookup(
19317 block,
19318 src,
19319 type_info_ty.getNamespaceIndex(zcu),
19320 try ip.getOrPutString(gpa, pt.tid, "Declaration", .no_embedded_nulls),
19321 ) orelse @panic("std.builtin.Type is corrupt");
19322 try sema.ensureNavResolved(src, nav);
19323 break :t Type.fromInterned(ip.getNav(nav).status.resolved.val);
19324 };
1932519146
19326 var decl_vals = std.ArrayList(InternPool.Index).init(gpa);19147 var decl_vals = std.ArrayList(InternPool.Index).init(gpa);
19327 defer decl_vals.deinit();19148 defer decl_vals.deinit();
...@@ -20809,11 +20630,11 @@ fn unionInit(...@@ -20809,11 +20630,11 @@ fn unionInit(
20809 if (try sema.resolveValue(init)) |init_val| {20630 if (try sema.resolveValue(init)) |init_val| {
20810 const tag_ty = union_ty.unionTagTypeHypothetical(zcu);20631 const tag_ty = union_ty.unionTagTypeHypothetical(zcu);
20811 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);20632 const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index);
20812 return Air.internedToRef((try pt.intern(.{ .un = .{20633 return Air.internedToRef((try pt.internUnion(.{
20813 .ty = union_ty.toIntern(),20634 .ty = union_ty.toIntern(),
20814 .tag = tag_val.toIntern(),20635 .tag = tag_val.toIntern(),
20815 .val = init_val.toIntern(),20636 .val = init_val.toIntern(),
20816 } })));20637 })));
20817 }20638 }
2081820639
20819 try sema.requireRuntimeBlock(block, init_src, null);20640 try sema.requireRuntimeBlock(block, init_src, null);
...@@ -20949,11 +20770,11 @@ fn zirStructInit(...@@ -20949,11 +20770,11 @@ fn zirStructInit(
20949 const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src);20770 const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src);
2095020771
20951 if (try sema.resolveValue(init_inst)) |val| {20772 if (try sema.resolveValue(init_inst)) |val| {
20952 const struct_val = Value.fromInterned(try pt.intern(.{ .un = .{20773 const struct_val = Value.fromInterned(try pt.internUnion(.{
20953 .ty = resolved_ty.toIntern(),20774 .ty = resolved_ty.toIntern(),
20954 .tag = tag_val.toIntern(),20775 .tag = tag_val.toIntern(),
20955 .val = val.toIntern(),20776 .val = val.toIntern(),
20956 } }));20777 }));
20957 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);20778 const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src);
20958 const final_val = (try sema.resolveValue(final_val_inst)).?;20779 const final_val = (try sema.resolveValue(final_val_inst)).?;
20959 return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);20780 return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
...@@ -21869,11 +21690,20 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -21869,11 +21690,20 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
21869 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);21690 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
21870 const src = block.nodeOffset(inst_data.src_node);21691 const src = block.nodeOffset(inst_data.src_node);
21871 const operand = try sema.resolveInst(inst_data.operand);21692 const operand = try sema.resolveInst(inst_data.operand);
21693 return analyzeTagName(sema, block, src, operand_src, operand);
21694}
21695
21696fn analyzeTagName(
21697 sema: *Sema,
21698 block: *Block,
21699 src: LazySrcLoc,
21700 operand_src: LazySrcLoc,
21701 operand: Air.Inst.Ref,
21702) CompileError!Air.Inst.Ref {
21872 const operand_ty = sema.typeOf(operand);21703 const operand_ty = sema.typeOf(operand);
21873 const pt = sema.pt;21704 const pt = sema.pt;
21874 const zcu = pt.zcu;21705 const zcu = pt.zcu;
21875 const ip = &zcu.intern_pool;21706 const ip = &zcu.intern_pool;
21876
21877 try operand_ty.resolveLayout(pt);21707 try operand_ty.resolveLayout(pt);
21878 const enum_ty = switch (operand_ty.zigTypeTag(zcu)) {21708 const enum_ty = switch (operand_ty.zigTypeTag(zcu)) {
21879 .enum_literal => {21709 .enum_literal => {
...@@ -27840,7 +27670,7 @@ fn explainWhyTypeIsNotPacked(...@@ -27840,7 +27670,7 @@ fn explainWhyTypeIsNotPacked(
27840 }27670 }
27841}27671}
2784227672
27843fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {27673fn preparePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
27844 const pt = sema.pt;27674 const pt = sema.pt;
27845 const zcu = pt.zcu;27675 const zcu = pt.zcu;
2784627676
...@@ -27871,33 +27701,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {...@@ -27871,33 +27701,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
27871 .val = .none,27701 .val = .none,
27872 } });27702 } });
27873 }27703 }
27874}
27875
27876/// Backends depend on panic decls being available when lowering safety-checked
27877/// instructions. This function ensures the panic function will be available to
27878/// be called during that time.
27879fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Nav.Index {
27880 const pt = sema.pt;
27881 const zcu = pt.zcu;
27882 const gpa = sema.gpa;
27883 if (zcu.panic_messages[@intFromEnum(panic_id)].unwrap()) |x| return x;
27884
27885 try sema.prepareSimplePanic(block, src);
2788627704
27887 const panic_messages_ty = try pt.getBuiltinType("panic_messages");27705 if (zcu.panic_cause_type == .none) {
27888 const msg_nav_index = (sema.namespaceLookup(27706 const panic_cause_ty = try pt.getBuiltinType("PanicCause");
27889 block,27707 try panic_cause_ty.resolveFields(pt);
27890 LazySrcLoc.unneeded,27708 zcu.panic_cause_type = panic_cause_ty.toIntern();
27891 panic_messages_ty.getNamespaceIndex(zcu),27709 }
27892 try zcu.intern_pool.getOrPutString(gpa, pt.tid, @tagName(panic_id), .no_embedded_nulls),
27893 ) catch |err| switch (err) {
27894 error.AnalysisFail => @panic("std.builtin.panic_messages is corrupt"),
27895 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
27896 error.OutOfMemory => |e| return e,
27897 }).?;
27898 try sema.ensureNavResolved(src, msg_nav_index);
27899 zcu.panic_messages[@intFromEnum(panic_id)] = msg_nav_index.toOptional();
27900 return msg_nav_index;
27901}27710}
2790227711
27903fn addSafetyCheck(27712fn addSafetyCheck(
...@@ -27905,7 +27714,7 @@ fn addSafetyCheck(...@@ -27905,7 +27714,7 @@ fn addSafetyCheck(
27905 parent_block: *Block,27714 parent_block: *Block,
27906 src: LazySrcLoc,27715 src: LazySrcLoc,
27907 ok: Air.Inst.Ref,27716 ok: Air.Inst.Ref,
27908 panic_id: Zcu.PanicId,27717 panic_cause_tag: PanicCauseTag,
27909) !void {27718) !void {
27910 const gpa = sema.gpa;27719 const gpa = sema.gpa;
27911 assert(!parent_block.is_comptime);27720 assert(!parent_block.is_comptime);
...@@ -27923,7 +27732,7 @@ fn addSafetyCheck(...@@ -27923,7 +27732,7 @@ fn addSafetyCheck(
2792327732
27924 defer fail_block.instructions.deinit(gpa);27733 defer fail_block.instructions.deinit(gpa);
2792527734
27926 try sema.safetyPanic(&fail_block, src, panic_id);27735 try sema.safetyPanic(&fail_block, src, panic_cause_tag);
27927 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);27736 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
27928}27737}
2792927738
...@@ -27992,30 +27801,7 @@ fn addSafetyCheckExtra(...@@ -27992,30 +27801,7 @@ fn addSafetyCheckExtra(
27992 parent_block.instructions.appendAssumeCapacity(block_inst);27801 parent_block.instructions.appendAssumeCapacity(block_inst);
27993}27802}
2799427803
27995fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void {27804fn addSafetyCheckUnwrapError(
27996 const pt = sema.pt;
27997 const zcu = pt.zcu;
27998
27999 if (!zcu.backendSupportsFeature(.panic_fn)) {
28000 _ = try block.addNoOp(.trap);
28001 return;
28002 }
28003
28004 try sema.prepareSimplePanic(block, src);
28005
28006 const panic_func = zcu.funcInfo(zcu.panic_func_index);
28007 const panic_fn = try sema.analyzeNavVal(block, src, panic_func.owner_nav);
28008 const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
28009
28010 const opt_usize_ty = try pt.optionalType(.usize_type);
28011 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
28012 .ty = opt_usize_ty.toIntern(),
28013 .val = .none,
28014 } })));
28015 try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation);
28016}
28017
28018fn panicUnwrapError(
28019 sema: *Sema,27805 sema: *Sema,
28020 parent_block: *Block,27806 parent_block: *Block,
28021 src: LazySrcLoc,27807 src: LazySrcLoc,
...@@ -28023,12 +27809,8 @@ fn panicUnwrapError(...@@ -28023,12 +27809,8 @@ fn panicUnwrapError(
28023 unwrap_err_tag: Air.Inst.Tag,27809 unwrap_err_tag: Air.Inst.Tag,
28024 is_non_err_tag: Air.Inst.Tag,27810 is_non_err_tag: Air.Inst.Tag,
28025) !void {27811) !void {
28026 const pt = sema.pt;
28027 assert(!parent_block.is_comptime);27812 assert(!parent_block.is_comptime);
28028 const ok = try parent_block.addUnOp(is_non_err_tag, operand);27813 const ok = try parent_block.addUnOp(is_non_err_tag, operand);
28029 if (!pt.zcu.comp.formatted_panics) {
28030 return sema.addSafetyCheck(parent_block, src, ok, .unwrap_error);
28031 }
28032 const gpa = sema.gpa;27814 const gpa = sema.gpa;
2803327815
28034 var fail_block: Block = .{27816 var fail_block: Block = .{
...@@ -28044,21 +27826,13 @@ fn panicUnwrapError(...@@ -28044,21 +27826,13 @@ fn panicUnwrapError(
2804427826
28045 defer fail_block.instructions.deinit(gpa);27827 defer fail_block.instructions.deinit(gpa);
2804627828
28047 {27829 const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
28048 if (!pt.zcu.backendSupportsFeature(.panic_unwrap_error)) {27830 try callPanic(sema, &fail_block, src, .unwrap_error, err, .@"safety check");
28049 _ = try fail_block.addNoOp(.trap);27831
28050 } else {
28051 const panic_fn = try sema.pt.getBuiltin("panicUnwrapError");
28052 const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
28053 const err_return_trace = try sema.getErrorReturnTrace(&fail_block);
28054 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
28055 try sema.callBuiltin(&fail_block, src, panic_fn, .auto, &args, .@"safety check");
28056 }
28057 }
28058 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);27832 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
28059}27833}
2806027834
28061fn panicIndexOutOfBounds(27835fn addSafetyCheckIndexOob(
28062 sema: *Sema,27836 sema: *Sema,
28063 parent_block: *Block,27837 parent_block: *Block,
28064 src: LazySrcLoc,27838 src: LazySrcLoc,
...@@ -28067,14 +27841,71 @@ fn panicIndexOutOfBounds(...@@ -28067,14 +27841,71 @@ fn panicIndexOutOfBounds(
28067 cmp_op: Air.Inst.Tag,27841 cmp_op: Air.Inst.Tag,
28068) !void {27842) !void {
28069 assert(!parent_block.is_comptime);27843 assert(!parent_block.is_comptime);
27844 const gpa = sema.gpa;
28070 const ok = try parent_block.addBinOp(cmp_op, index, len);27845 const ok = try parent_block.addBinOp(cmp_op, index, len);
28071 if (!sema.pt.zcu.comp.formatted_panics) {27846
28072 return sema.addSafetyCheck(parent_block, src, ok, .index_out_of_bounds);27847 var fail_block: Block = .{
27848 .parent = parent_block,
27849 .sema = sema,
27850 .namespace = parent_block.namespace,
27851 .instructions = .{},
27852 .inlining = parent_block.inlining,
27853 .is_comptime = false,
27854 .src_base_inst = parent_block.src_base_inst,
27855 .type_name_ctx = parent_block.type_name_ctx,
27856 };
27857
27858 defer fail_block.instructions.deinit(gpa);
27859
27860 const oob_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "IndexOutOfBounds");
27861 comptime {
27862 const fields = @typeInfo(std.builtin.PanicCause.IndexOutOfBounds).@"struct".fields;
27863 assert(std.mem.eql(u8, fields[0].name, "index"));
27864 assert(std.mem.eql(u8, fields[1].name, "len"));
27865 assert(fields.len == 2);
28073 }27866 }
28074 try sema.safetyCheckFormatted(parent_block, src, ok, "panicOutOfBounds", &.{ index, len });27867 const panic_cause_payload = try fail_block.addAggregateInit(oob_ty, &.{ index, len });
27868 try callPanic(sema, &fail_block, src, .index_out_of_bounds, panic_cause_payload, .@"safety check");
27869 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
28075}27870}
2807627871
28077fn panicInactiveUnionField(27872fn addSafetyCheckStartGreaterThanEnd(
27873 sema: *Sema,
27874 parent_block: *Block,
27875 src: LazySrcLoc,
27876 start: Air.Inst.Ref,
27877 end: Air.Inst.Ref,
27878) !void {
27879 assert(!parent_block.is_comptime);
27880 const gpa = sema.gpa;
27881 const ok = try parent_block.addBinOp(.cmp_lte, start, end);
27882
27883 var fail_block: Block = .{
27884 .parent = parent_block,
27885 .sema = sema,
27886 .namespace = parent_block.namespace,
27887 .instructions = .{},
27888 .inlining = parent_block.inlining,
27889 .is_comptime = false,
27890 .src_base_inst = parent_block.src_base_inst,
27891 .type_name_ctx = parent_block.type_name_ctx,
27892 };
27893
27894 defer fail_block.instructions.deinit(gpa);
27895
27896 const oob_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "StartIndexGreaterThanEnd");
27897 comptime {
27898 const fields = @typeInfo(std.builtin.PanicCause.StartIndexGreaterThanEnd).@"struct".fields;
27899 assert(std.mem.eql(u8, fields[0].name, "start"));
27900 assert(std.mem.eql(u8, fields[1].name, "end"));
27901 assert(fields.len == 2);
27902 }
27903 const panic_cause_payload = try fail_block.addAggregateInit(oob_ty, &.{ start, end });
27904 try callPanic(sema, &fail_block, src, .start_index_greater_than_end, panic_cause_payload, .@"safety check");
27905 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
27906}
27907
27908fn addSafetyCheckInactiveUnionField(
28078 sema: *Sema,27909 sema: *Sema,
28079 parent_block: *Block,27910 parent_block: *Block,
28080 src: LazySrcLoc,27911 src: LazySrcLoc,
...@@ -28082,14 +27913,39 @@ fn panicInactiveUnionField(...@@ -28082,14 +27913,39 @@ fn panicInactiveUnionField(
28082 wanted_tag: Air.Inst.Ref,27913 wanted_tag: Air.Inst.Ref,
28083) !void {27914) !void {
28084 assert(!parent_block.is_comptime);27915 assert(!parent_block.is_comptime);
27916 const gpa = sema.gpa;
28085 const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);27917 const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
28086 if (!sema.pt.zcu.comp.formatted_panics) {27918
28087 return sema.addSafetyCheck(parent_block, src, ok, .inactive_union_field);27919 var fail_block: Block = .{
28088 }27920 .parent = parent_block,
28089 try sema.safetyCheckFormatted(parent_block, src, ok, "panicInactiveUnionField", &.{ active_tag, wanted_tag });27921 .sema = sema,
27922 .namespace = parent_block.namespace,
27923 .instructions = .{},
27924 .inlining = parent_block.inlining,
27925 .is_comptime = false,
27926 .src_base_inst = parent_block.src_base_inst,
27927 .type_name_ctx = parent_block.type_name_ctx,
27928 };
27929
27930 defer fail_block.instructions.deinit(gpa);
27931
27932 const payload_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "InactiveUnionField");
27933 comptime {
27934 const fields = @typeInfo(std.builtin.PanicCause.InactiveUnionField).@"struct".fields;
27935 assert(std.mem.eql(u8, fields[0].name, "active"));
27936 assert(std.mem.eql(u8, fields[1].name, "accessed"));
27937 assert(fields.len == 2);
27938 }
27939 // TODO: before merging the branch, check how many safety checks end up being emitted
27940 // for union field accesses and avoid extraneous ones.
27941 const active_str = try analyzeTagName(sema, &fail_block, src, src, active_tag);
27942 const accessed_str = try analyzeTagName(sema, &fail_block, src, src, wanted_tag);
27943 const panic_cause_payload = try fail_block.addAggregateInit(payload_ty, &.{ active_str, accessed_str });
27944 try callPanic(sema, &fail_block, src, .inactive_union_field, panic_cause_payload, .@"safety check");
27945 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
28090}27946}
2809127947
28092fn panicSentinelMismatch(27948fn addSafetyCheckSentinelMismatch(
28093 sema: *Sema,27949 sema: *Sema,
28094 parent_block: *Block,27950 parent_block: *Block,
28095 src: LazySrcLoc,27951 src: LazySrcLoc,
...@@ -28099,6 +27955,7 @@ fn panicSentinelMismatch(...@@ -28099,6 +27955,7 @@ fn panicSentinelMismatch(
28099 sentinel_index: Air.Inst.Ref,27955 sentinel_index: Air.Inst.Ref,
28100) !void {27956) !void {
28101 assert(!parent_block.is_comptime);27957 assert(!parent_block.is_comptime);
27958 const gpa = sema.gpa;
28102 const pt = sema.pt;27959 const pt = sema.pt;
28103 const zcu = pt.zcu;27960 const zcu = pt.zcu;
28104 const expected_sentinel_val = maybe_sentinel orelse return;27961 const expected_sentinel_val = maybe_sentinel orelse return;
...@@ -28114,8 +27971,7 @@ fn panicSentinelMismatch(...@@ -28114,8 +27971,7 @@ fn panicSentinelMismatch(
28114 };27971 };
2811527972
28116 const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {27973 const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {
28117 const eql =27974 const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
28118 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
28119 break :ok try parent_block.addInst(.{27975 break :ok try parent_block.addInst(.{
28120 .tag = .reduce,27976 .tag = .reduce,
28121 .data = .{ .reduce = .{27977 .data = .{ .reduce = .{
...@@ -28128,25 +27984,6 @@ fn panicSentinelMismatch(...@@ -28128,25 +27984,6 @@ fn panicSentinelMismatch(
28128 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);27984 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
28129 };27985 };
2813027986
28131 if (!pt.zcu.comp.formatted_panics) {
28132 return sema.addSafetyCheck(parent_block, src, ok, .sentinel_mismatch);
28133 }
28134 try sema.safetyCheckFormatted(parent_block, src, ok, "panicSentinelMismatch", &.{ expected_sentinel, actual_sentinel });
28135}
28136
28137fn safetyCheckFormatted(
28138 sema: *Sema,
28139 parent_block: *Block,
28140 src: LazySrcLoc,
28141 ok: Air.Inst.Ref,
28142 func: []const u8,
28143 args: []const Air.Inst.Ref,
28144) CompileError!void {
28145 const pt = sema.pt;
28146 const zcu = pt.zcu;
28147 assert(zcu.comp.formatted_panics);
28148 const gpa = sema.gpa;
28149
28150 var fail_block: Block = .{27987 var fail_block: Block = .{
28151 .parent = parent_block,27988 .parent = parent_block,
28152 .sema = sema,27989 .sema = sema,
...@@ -28160,20 +27997,29 @@ fn safetyCheckFormatted(...@@ -28160,20 +27997,29 @@ fn safetyCheckFormatted(
2816027997
28161 defer fail_block.instructions.deinit(gpa);27998 defer fail_block.instructions.deinit(gpa);
2816227999
28163 if (!zcu.backendSupportsFeature(.safety_check_formatted)) {28000 // A different PanicCause tag must be used depending on what payload type it can be fit into.
28164 _ = try fail_block.addNoOp(.trap);28001 // If it cannot fit into any, the "other" tag can be used, which does not try to carry the
28002 // sentinel value data.
28003
28004 if (sentinel_ty.isUnsignedInt(zcu) and sentinel_ty.intInfo(zcu).bits <= Type.usize.intInfo(zcu).bits) {
28005 const mm_ty = try getBuiltinInnerType(sema, &fail_block, src, "PanicCause", "SentinelMismatchUsize");
28006 comptime {
28007 const fields = @typeInfo(std.builtin.PanicCause.SentinelMismatchUsize).@"struct".fields;
28008 assert(std.mem.eql(u8, fields[0].name, "expected"));
28009 assert(std.mem.eql(u8, fields[1].name, "found"));
28010 assert(fields.len == 2);
28011 }
28012 const panic_cause_payload = &fail_block.addAggregateInit(mm_ty, &.{ expected_sentinel, actual_sentinel });
28013 try callPanic(sema, &fail_block, src, .sentinel_mismatch_usize, panic_cause_payload, .@"safety check");
28165 } else {28014 } else {
28166 const panic_fn = try pt.getBuiltin(func);28015 try callPanic(sema, &fail_block, src, .sentinel_mismatch_other, .void_value, .@"safety check");
28167 try sema.callBuiltin(&fail_block, src, panic_fn, .auto, args, .@"safety check");
28168 }28016 }
28169 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);28017 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
28170}28018}
2817128019
28172/// This does not set `sema.branch_hint`.28020/// This does not set `sema.branch_hint`.
28173fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void {28021fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_cause_tag: PanicCauseTag) CompileError!void {
28174 const msg_nav_index = try sema.preparePanicId(block, src, panic_id);28022 try callPanic(sema, block, src, panic_cause_tag, .void_value, .@"safety check");
28175 const msg_inst = try sema.analyzeNavVal(block, src, msg_nav_index);
28176 try sema.panicWithMsg(block, src, msg_inst, .@"safety check");
28177}28023}
2817828024
28179fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {28025fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
...@@ -29229,7 +29075,7 @@ fn unionFieldPtr(...@@ -29229,7 +29075,7 @@ fn unionFieldPtr(
29229 // TODO would it be better if get_union_tag supported pointers to unions?29075 // TODO would it be better if get_union_tag supported pointers to unions?
29230 const union_val = try block.addTyOp(.load, union_ty, union_ptr);29076 const union_val = try block.addTyOp(.load, union_ty, union_ptr);
29231 const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_val);29077 const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_val);
29232 try sema.panicInactiveUnionField(block, src, active_tag, wanted_tag);29078 try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
29233 }29079 }
29234 if (field_ty.zigTypeTag(zcu) == .noreturn) {29080 if (field_ty.zigTypeTag(zcu) == .noreturn) {
29235 _ = try block.addNoOp(.unreach);29081 _ = try block.addNoOp(.unreach);
...@@ -29304,7 +29150,7 @@ fn unionFieldVal(...@@ -29304,7 +29150,7 @@ fn unionFieldVal(
29304 const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);29150 const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index);
29305 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());29151 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
29306 const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_byval);29152 const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_byval);
29307 try sema.panicInactiveUnionField(block, src, active_tag, wanted_tag);29153 try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
29308 }29154 }
29309 if (field_ty.zigTypeTag(zcu) == .noreturn) {29155 if (field_ty.zigTypeTag(zcu) == .noreturn) {
29310 _ = try block.addNoOp(.unreach);29156 _ = try block.addNoOp(.unreach);
...@@ -29668,11 +29514,11 @@ fn elemValArray(...@@ -29668,11 +29514,11 @@ fn elemValArray(
2966829514
29669 const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;29515 const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;
29670 if (oob_safety and block.wantSafety()) {29516 if (oob_safety and block.wantSafety()) {
29671 // Runtime check is only needed if unable to comptime check29517 // Runtime check is only needed if unable to comptime check.
29672 if (maybe_index_val == null) {29518 if (maybe_index_val == null) {
29673 const len_inst = try pt.intRef(Type.usize, array_len);29519 const len_inst = try pt.intRef(Type.usize, array_len);
29674 const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt;29520 const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt;
29675 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);29521 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
29676 }29522 }
29677 }29523 }
2967829524
...@@ -29740,7 +29586,7 @@ fn elemPtrArray(...@@ -29740,7 +29586,7 @@ fn elemPtrArray(
29740 if (oob_safety and block.wantSafety() and offset == null) {29586 if (oob_safety and block.wantSafety() and offset == null) {
29741 const len_inst = try pt.intRef(Type.usize, array_len);29587 const len_inst = try pt.intRef(Type.usize, array_len);
29742 const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt;29588 const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt;
29743 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);29589 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
29744 }29590 }
2974529591
29746 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);29592 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
...@@ -29799,7 +29645,7 @@ fn elemValSlice(...@@ -29799,7 +29645,7 @@ fn elemValSlice(
29799 else29645 else
29800 try block.addTyOp(.slice_len, Type.usize, slice);29646 try block.addTyOp(.slice_len, Type.usize, slice);
29801 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;29647 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
29802 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);29648 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
29803 }29649 }
29804 return block.addBinOp(.slice_elem_val, slice, elem_index);29650 return block.addBinOp(.slice_elem_val, slice, elem_index);
29805}29651}
...@@ -29859,7 +29705,7 @@ fn elemPtrSlice(...@@ -29859,7 +29705,7 @@ fn elemPtrSlice(
29859 break :len try block.addTyOp(.slice_len, Type.usize, slice);29705 break :len try block.addTyOp(.slice_len, Type.usize, slice);
29860 };29706 };
29861 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;29707 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
29862 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);29708 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
29863 }29709 }
29864 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);29710 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
29865}29711}
...@@ -33666,12 +33512,7 @@ fn analyzeSlice(...@@ -33666,12 +33512,7 @@ fn analyzeSlice(
33666 // requirement: start <= end33512 // requirement: start <= end
33667 assert(!block.is_comptime);33513 assert(!block.is_comptime);
33668 try sema.requireRuntimeBlock(block, src, runtime_src.?);33514 try sema.requireRuntimeBlock(block, src, runtime_src.?);
33669 const ok = try block.addBinOp(.cmp_lte, start, end);33515 try sema.addSafetyCheckStartGreaterThanEnd(block, src, start, end);
33670 if (!pt.zcu.comp.formatted_panics) {
33671 try sema.addSafetyCheck(block, src, ok, .start_index_greater_than_end);
33672 } else {
33673 try sema.safetyCheckFormatted(block, src, ok, "panicStartGreaterThanEnd", &.{ start, end });
33674 }
33675 }33516 }
33676 const new_len = if (by_length)33517 const new_len = if (by_length)
33677 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)33518 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
...@@ -33726,11 +33567,11 @@ fn analyzeSlice(...@@ -33726,11 +33567,11 @@ fn analyzeSlice(
33726 else33567 else
33727 end;33568 end;
3372833569
33729 try sema.panicIndexOutOfBounds(block, src, actual_end, actual_len, .cmp_lte);33570 try sema.addSafetyCheckIndexOob(block, src, actual_end, actual_len, .cmp_lte);
33730 }33571 }
3373133572
33732 // requirement: result[new_len] == slice_sentinel33573 // requirement: result[new_len] == slice_sentinel
33733 try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);33574 try sema.addSafetyCheckSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
33734 }33575 }
33735 return result;33576 return result;
33736 };33577 };
...@@ -33789,11 +33630,11 @@ fn analyzeSlice(...@@ -33789,11 +33630,11 @@ fn analyzeSlice(
33789 try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)33630 try sema.analyzeArithmetic(block, .add, end, .one, src, end_src, end_src, true)
33790 else33631 else
33791 end;33632 end;
33792 try sema.panicIndexOutOfBounds(block, src, actual_end, len_inst, .cmp_lte);33633 try sema.addSafetyCheckIndexOob(block, src, actual_end, len_inst, .cmp_lte);
33793 }33634 }
3379433635
33795 // requirement: start <= end33636 // requirement: start <= end
33796 try sema.panicIndexOutOfBounds(block, src, start, end, .cmp_lte);33637 try sema.addSafetyCheckIndexOob(block, src, start, end, .cmp_lte);
33797 }33638 }
33798 const result = try block.addInst(.{33639 const result = try block.addInst(.{
33799 .tag = .slice,33640 .tag = .slice,
...@@ -33807,7 +33648,7 @@ fn analyzeSlice(...@@ -33807,7 +33648,7 @@ fn analyzeSlice(
33807 });33648 });
33808 if (block.wantSafety()) {33649 if (block.wantSafety()) {
33809 // requirement: result[new_len] == slice_sentinel33650 // requirement: result[new_len] == slice_sentinel
33810 try sema.panicSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);33651 try sema.addSafetyCheckSentinelMismatch(block, src, slice_sentinel, elem_ty, result, new_len);
33811 }33652 }
33812 return result;33653 return result;
33813}33654}
...@@ -37688,11 +37529,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37688,11 +37529,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37688 const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);37529 const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
37689 const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse37530 const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse
37690 return null;37531 return null;
37691 const only = try pt.intern(.{ .un = .{37532 const only = try pt.internUnion(.{
37692 .ty = ty.toIntern(),37533 .ty = ty.toIntern(),
37693 .tag = tag_val.toIntern(),37534 .tag = tag_val.toIntern(),
37694 .val = val_val.toIntern(),37535 .val = val_val.toIntern(),
37695 } });37536 });
37696 return Value.fromInterned(only);37537 return Value.fromInterned(only);
37697 },37538 },
3769837539
...@@ -38849,7 +38690,7 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check:...@@ -38849,7 +38690,7 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check:
38849 sema.branch_hint = .cold;38690 sema.branch_hint = .cold;
38850 }38691 }
3885138692
38852 try sema.safetyPanic(block, src, .unreach);38693 try sema.safetyPanic(block, src, .reached_unreachable);
38853 } else {38694 } else {
38854 _ = try block.addNoOp(.unreach);38695 _ = try block.addNoOp(.unreach);
38855 }38696 }
...@@ -39123,3 +38964,36 @@ const loadComptimePtr = @import("Sema/comptime_ptr_access.zig").loadComptimePtr;...@@ -39123,3 +38964,36 @@ const loadComptimePtr = @import("Sema/comptime_ptr_access.zig").loadComptimePtr;
39123const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadResult;38964const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadResult;
39124const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr;38965const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr;
39125const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult;38966const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult;
38967
38968/// Convenience function that looks 2 levels deep into `std.builtin`.
38969fn getBuiltinInnerType(
38970 sema: *Sema,
38971 block: *Block,
38972 src: LazySrcLoc,
38973 outer_name: []const u8,
38974 inner_name: []const u8,
38975) !Type {
38976 const outer_ty = try sema.pt.getBuiltinType(outer_name);
38977 return getInnerType(sema, block, src, outer_ty, inner_name);
38978}
38979
38980fn getInnerType(
38981 sema: *Sema,
38982 block: *Block,
38983 src: LazySrcLoc,
38984 outer_ty: Type,
38985 inner_name: []const u8,
38986) !Type {
38987 const pt = sema.pt;
38988 const zcu = pt.zcu;
38989 const ip = &zcu.intern_pool;
38990 const gpa = sema.gpa;
38991 const nav = try sema.namespaceLookup(
38992 block,
38993 src,
38994 outer_ty.getNamespaceIndex(zcu),
38995 try ip.getOrPutString(gpa, pt.tid, inner_name, .no_embedded_nulls),
38996 ) orelse return sema.fail(block, src, "std.builtin missing {s}", .{inner_name});
38997 try sema.ensureNavResolved(src, nav);
38998 return Type.fromInterned(ip.getNav(nav).status.resolved.val);
38999}
src/Sema/bitcast.zig+6-6
...@@ -613,11 +613,11 @@ const PackValueBits = struct {...@@ -613,11 +613,11 @@ const PackValueBits = struct {
613 pack.bit_offset = prev_bit_offset;613 pack.bit_offset = prev_bit_offset;
614 break :backing;614 break :backing;
615 }615 }
616 return Value.fromInterned(try pt.intern(.{ .un = .{616 return Value.fromInterned(try pt.internUnion(.{
617 .ty = ty.toIntern(),617 .ty = ty.toIntern(),
618 .tag = .none,618 .tag = .none,
619 .val = backing_val.toIntern(),619 .val = backing_val.toIntern(),
620 } }));620 }));
621 }621 }
622622
623 const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu));623 const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu));
...@@ -658,21 +658,21 @@ const PackValueBits = struct {...@@ -658,21 +658,21 @@ const PackValueBits = struct {
658 continue;658 continue;
659 }659 }
660 const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx);660 const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx);
661 return Value.fromInterned(try pt.intern(.{ .un = .{661 return Value.fromInterned(try pt.internUnion(.{
662 .ty = ty.toIntern(),662 .ty = ty.toIntern(),
663 .tag = tag_val.toIntern(),663 .tag = tag_val.toIntern(),
664 .val = field_val.toIntern(),664 .val = field_val.toIntern(),
665 } }));665 }));
666 }666 }
667667
668 // No field could represent the value. Just do whatever happens when we try to read668 // No field could represent the value. Just do whatever happens when we try to read
669 // the backing type - either `undefined` or `error.ReinterpretDeclRef`.669 // the backing type - either `undefined` or `error.ReinterpretDeclRef`.
670 const backing_val = try pack.get(backing_ty);670 const backing_val = try pack.get(backing_ty);
671 return Value.fromInterned(try pt.intern(.{ .un = .{671 return Value.fromInterned(try pt.internUnion(.{
672 .ty = ty.toIntern(),672 .ty = ty.toIntern(),
673 .tag = .none,673 .tag = .none,
674 .val = backing_val.toIntern(),674 .val = backing_val.toIntern(),
675 } }));675 }));
676 },676 },
677 else => return pack.primitive(ty),677 else => return pack.primitive(ty),
678 }678 }
src/Type.zig+2-2
...@@ -2677,11 +2677,11 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2677,11 +2677,11 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2677 const only_field_ty = union_obj.field_types.get(ip)[0];2677 const only_field_ty = union_obj.field_types.get(ip)[0];
2678 const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse2678 const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse
2679 return null;2679 return null;
2680 const only = try pt.intern(.{ .un = .{2680 const only = try pt.internUnion(.{
2681 .ty = ty.toIntern(),2681 .ty = ty.toIntern(),
2682 .tag = tag_val.toIntern(),2682 .tag = tag_val.toIntern(),
2683 .val = val_val.toIntern(),2683 .val = val_val.toIntern(),
2684 } });2684 });
2685 return Value.fromInterned(only);2685 return Value.fromInterned(only);
2686 },2686 },
2687 .opaque_type => return null,2687 .opaque_type => return null,
src/Value.zig+6-6
...@@ -713,11 +713,11 @@ pub fn readFromMemory(...@@ -713,11 +713,11 @@ pub fn readFromMemory(
713 const union_size = ty.abiSize(zcu);713 const union_size = ty.abiSize(zcu);
714 const array_ty = try zcu.arrayType(.{ .len = union_size, .child = .u8_type });714 const array_ty = try zcu.arrayType(.{ .len = union_size, .child = .u8_type });
715 const val = (try readFromMemory(array_ty, zcu, buffer, arena)).toIntern();715 const val = (try readFromMemory(array_ty, zcu, buffer, arena)).toIntern();
716 return Value.fromInterned(try pt.intern(.{ .un = .{716 return Value.fromInterned(try pt.internUnion(.{
717 .ty = ty.toIntern(),717 .ty = ty.toIntern(),
718 .tag = .none,718 .tag = .none,
719 .val = val,719 .val = val,
720 } }));720 }));
721 },721 },
722 .@"packed" => {722 .@"packed" => {
723 const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8;723 const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8;
...@@ -860,11 +860,11 @@ pub fn readFromPackedMemory(...@@ -860,11 +860,11 @@ pub fn readFromPackedMemory(
860 .@"packed" => {860 .@"packed" => {
861 const backing_ty = try ty.unionBackingType(pt);861 const backing_ty = try ty.unionBackingType(pt);
862 const val = (try readFromPackedMemory(backing_ty, pt, buffer, bit_offset, arena)).toIntern();862 const val = (try readFromPackedMemory(backing_ty, pt, buffer, bit_offset, arena)).toIntern();
863 return Value.fromInterned(try pt.intern(.{ .un = .{863 return Value.fromInterned(try pt.internUnion(.{
864 .ty = ty.toIntern(),864 .ty = ty.toIntern(),
865 .tag = .none,865 .tag = .none,
866 .val = val,866 .val = val,
867 } }));867 }));
868 },868 },
869 },869 },
870 .pointer => {870 .pointer => {
...@@ -4481,11 +4481,11 @@ pub fn resolveLazy(...@@ -4481,11 +4481,11 @@ pub fn resolveLazy(
4481 return if (resolved_tag == un.tag and resolved_val == un.val)4481 return if (resolved_tag == un.tag and resolved_val == un.val)
4482 val4482 val
4483 else4483 else
4484 Value.fromInterned(try pt.intern(.{ .un = .{4484 Value.fromInterned(try pt.internUnion(.{
4485 .ty = un.ty,4485 .ty = un.ty,
4486 .tag = resolved_tag,4486 .tag = resolved_tag,
4487 .val = resolved_val,4487 .val = resolved_val,
4488 } }));4488 }));
4489 },4489 },
4490 else => return val,4490 else => return val,
4491 }4491 }
src/Zcu.zig+1-39
...@@ -210,45 +210,15 @@ all_type_references: std.ArrayListUnmanaged(TypeReference) = .empty,...@@ -210,45 +210,15 @@ all_type_references: std.ArrayListUnmanaged(TypeReference) = .empty,
210/// Freelist of indices in `all_type_references`.210/// Freelist of indices in `all_type_references`.
211free_type_references: std.ArrayListUnmanaged(u32) = .empty,211free_type_references: std.ArrayListUnmanaged(u32) = .empty,
212212
213panic_messages: [PanicId.len]InternPool.Nav.Index.Optional = .{.none} ** PanicId.len,
214/// The panic function body.213/// The panic function body.
215panic_func_index: InternPool.Index = .none,214panic_func_index: InternPool.Index = .none,
216null_stack_trace: InternPool.Index = .none,215null_stack_trace: InternPool.Index = .none,
216panic_cause_type: InternPool.Index = .none,
217217
218generation: u32 = 0,218generation: u32 = 0,
219219
220pub const PerThread = @import("Zcu/PerThread.zig");220pub const PerThread = @import("Zcu/PerThread.zig");
221221
222pub const PanicId = enum {
223 unreach,
224 unwrap_null,
225 cast_to_null,
226 incorrect_alignment,
227 invalid_error_code,
228 cast_truncated_data,
229 negative_to_unsigned,
230 integer_overflow,
231 shl_overflow,
232 shr_overflow,
233 divide_by_zero,
234 exact_division_remainder,
235 inactive_union_field,
236 integer_part_out_of_bounds,
237 corrupt_switch,
238 shift_rhs_too_big,
239 invalid_enum_value,
240 sentinel_mismatch,
241 unwrap_error,
242 index_out_of_bounds,
243 start_index_greater_than_end,
244 for_len_mismatch,
245 memcpy_len_mismatch,
246 memcpy_alias,
247 noreturn_returned,
248
249 pub const len = @typeInfo(PanicId).@"enum".fields.len;
250};
251
252pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);222pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
253223
254pub const CImportError = struct {224pub const CImportError = struct {
...@@ -2926,14 +2896,6 @@ pub const Feature = enum {...@@ -2926,14 +2896,6 @@ pub const Feature = enum {
2926 /// When this feature is enabled, Sema will emit calls to `std.builtin.panic`2896 /// When this feature is enabled, Sema will emit calls to `std.builtin.panic`
2927 /// for things like safety checks and unreachables. Otherwise traps will be emitted.2897 /// for things like safety checks and unreachables. Otherwise traps will be emitted.
2928 panic_fn,2898 panic_fn,
2929 /// When this feature is enabled, Sema will emit calls to `std.builtin.panicUnwrapError`.
2930 /// This error message requires more advanced formatting, hence it being seperate from `panic_fn`.
2931 /// Otherwise traps will be emitted.
2932 panic_unwrap_error,
2933 /// When this feature is enabled, Sema will emit calls to the more complex panic functions
2934 /// that use formatting to add detail to error messages. Similar to `panic_unwrap_error`.
2935 /// Otherwise traps will be emitted.
2936 safety_check_formatted,
2937 /// When this feature is enabled, Sema will insert tracer functions for gathering a stack2899 /// When this feature is enabled, Sema will insert tracer functions for gathering a stack
2938 /// trace for error returns.2900 /// trace for error returns.
2939 error_return_trace,2901 error_return_trace,
src/Zcu/PerThread.zig+9-3
...@@ -2697,11 +2697,16 @@ pub fn reportRetryableFileError(...@@ -2697,11 +2697,16 @@ pub fn reportRetryableFileError(
2697 gop.value_ptr.* = err_msg;2697 gop.value_ptr.* = err_msg;
2698}2698}
26992699
2700///Shortcut for calling `intern_pool.get`.2700/// Shortcut for calling `intern_pool.get`.
2701pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {2701pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {
2702 return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key);2702 return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key);
2703}2703}
27042704
2705/// Shortcut for calling `intern_pool.getUnion`.
2706pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index {
2707 return pt.zcu.intern_pool.getUnion(pt.zcu.gpa, pt.tid, un);
2708}
2709
2705/// Essentially a shortcut for calling `intern_pool.getCoerced`.2710/// Essentially a shortcut for calling `intern_pool.getCoerced`.
2706/// However, this function also allows coercing `extern`s. The `InternPool` function can't do2711/// However, this function also allows coercing `extern`s. The `InternPool` function can't do
2707/// this because it requires potentially pushing to the job queue.2712/// this because it requires potentially pushing to the job queue.
...@@ -2949,11 +2954,12 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value {...@@ -2949,11 +2954,12 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value {
2949}2954}
29502955
2951pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {2956pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {
2952 return Value.fromInterned(try pt.intern(.{ .un = .{2957 const zcu = pt.zcu;
2958 return Value.fromInterned(try zcu.intern_pool.getUnion(zcu.gpa, pt.tid, .{
2953 .ty = union_ty.toIntern(),2959 .ty = union_ty.toIntern(),
2954 .tag = tag.toIntern(),2960 .tag = tag.toIntern(),
2955 .val = val.toIntern(),2961 .val = val.toIntern(),
2956 } }));2962 }));
2957}2963}
29582964
2959/// This function casts the float representation down to the representation of the type, potentially2965/// This function casts the float representation down to the representation of the type, potentially
src/crash_report.zig+27-21
...@@ -17,7 +17,7 @@ const Decl = Zcu.Decl;...@@ -17,7 +17,7 @@ const Decl = Zcu.Decl;
17/// To use these crash report diagnostics, publish this panic in your main file17/// To use these crash report diagnostics, publish this panic in your main file
18/// and add `pub const enable_segfault_handler = false;` to your `std_options`.18/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
19/// You will also need to call initialize() on startup, preferably as the very first operation in your program.19/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
20pub const panic = if (build_options.enable_debug_extensions) compilerPanic else std.builtin.default_panic;20pub const panic = if (build_options.enable_debug_extensions) compilerPanic else std.debug.defaultPanic;
2121
22/// Install signal handlers to identify crashes and report diagnostics.22/// Install signal handlers to identify crashes and report diagnostics.
23pub fn initialize() void {23pub fn initialize() void {
...@@ -152,12 +152,16 @@ fn writeFilePath(file: *Zcu.File, writer: anytype) !void {...@@ -152,12 +152,16 @@ fn writeFilePath(file: *Zcu.File, writer: anytype) !void {
152 try writer.writeAll(file.sub_file_path);152 try writer.writeAll(file.sub_file_path);
153}153}
154154
155pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, maybe_ret_addr: ?usize) noreturn {155pub fn compilerPanic(
156 cause: std.builtin.PanicCause,
157 error_return_trace: ?*std.builtin.StackTrace,
158 maybe_ret_addr: ?usize,
159) noreturn {
156 @branchHint(.cold);160 @branchHint(.cold);
157 PanicSwitch.preDispatch();161 PanicSwitch.preDispatch();
158 const ret_addr = maybe_ret_addr orelse @returnAddress();162 const ret_addr = maybe_ret_addr orelse @returnAddress();
159 const stack_ctx: StackContext = .{ .current = .{ .ret_addr = ret_addr } };163 const stack_ctx: StackContext = .{ .current = .{ .ret_addr = ret_addr } };
160 PanicSwitch.dispatch(error_return_trace, stack_ctx, msg);164 PanicSwitch.dispatch(error_return_trace, stack_ctx, cause);
161}165}
162166
163/// Attaches a global SIGSEGV handler167/// Attaches a global SIGSEGV handler
...@@ -354,17 +358,17 @@ const PanicSwitch = struct {...@@ -354,17 +358,17 @@ const PanicSwitch = struct {
354 pub fn dispatch(358 pub fn dispatch(
355 trace: ?*const std.builtin.StackTrace,359 trace: ?*const std.builtin.StackTrace,
356 stack_ctx: StackContext,360 stack_ctx: StackContext,
357 msg: []const u8,361 panic_cause: std.builtin.PanicCause,
358 ) noreturn {362 ) noreturn {
359 var panic_state: *volatile PanicState = &panic_state_raw;363 var panic_state: *volatile PanicState = &panic_state_raw;
360 debug.assert(panic_state.awaiting_dispatch);364 debug.assert(panic_state.awaiting_dispatch);
361 panic_state.awaiting_dispatch = false;365 panic_state.awaiting_dispatch = false;
362 nosuspend switch (panic_state.recover_stage) {366 nosuspend switch (panic_state.recover_stage) {
363 .initialize => goTo(initPanic, .{ panic_state, trace, stack_ctx, msg }),367 .initialize => goTo(initPanic, .{ panic_state, trace, stack_ctx, panic_cause }),
364 .report_stack => goTo(recoverReportStack, .{ panic_state, trace, stack_ctx, msg }),368 .report_stack => goTo(recoverReportStack, .{ panic_state, trace, stack_ctx, panic_cause }),
365 .release_mutex => goTo(recoverReleaseMutex, .{ panic_state, trace, stack_ctx, msg }),369 .release_mutex => goTo(recoverReleaseMutex, .{ panic_state, trace, stack_ctx, panic_cause }),
366 .release_ref_count => goTo(recoverReleaseRefCount, .{ panic_state, trace, stack_ctx, msg }),370 .release_ref_count => goTo(recoverReleaseRefCount, .{ panic_state, trace, stack_ctx, panic_cause }),
367 .abort => goTo(recoverAbort, .{ panic_state, trace, stack_ctx, msg }),371 .abort => goTo(recoverAbort, .{ panic_state, trace, stack_ctx, panic_cause }),
368 .silent_abort => goTo(abort, .{}),372 .silent_abort => goTo(abort, .{}),
369 };373 };
370 }374 }
...@@ -373,7 +377,7 @@ const PanicSwitch = struct {...@@ -373,7 +377,7 @@ const PanicSwitch = struct {
373 state: *volatile PanicState,377 state: *volatile PanicState,
374 trace: ?*const std.builtin.StackTrace,378 trace: ?*const std.builtin.StackTrace,
375 stack: StackContext,379 stack: StackContext,
376 msg: []const u8,380 panic_cause: std.builtin.PanicCause,
377 ) noreturn {381 ) noreturn {
378 // use a temporary so there's only one volatile store382 // use a temporary so there's only one volatile store
379 const new_state = PanicState{383 const new_state = PanicState{
...@@ -398,6 +402,8 @@ const PanicSwitch = struct {...@@ -398,6 +402,8 @@ const PanicSwitch = struct {
398 const current_thread_id = std.Thread.getCurrentId();402 const current_thread_id = std.Thread.getCurrentId();
399 stderr.print("thread {} panic: ", .{current_thread_id}) catch goTo(releaseMutex, .{state});403 stderr.print("thread {} panic: ", .{current_thread_id}) catch goTo(releaseMutex, .{state});
400 }404 }
405 var buffer: [1000]u8 = undefined;
406 const msg = buffer[0..std.debug.fmtPanicCause(&buffer, panic_cause)];
401 stderr.print("{s}\n", .{msg}) catch goTo(releaseMutex, .{state});407 stderr.print("{s}\n", .{msg}) catch goTo(releaseMutex, .{state});
402408
403 state.recover_stage = .report_stack;409 state.recover_stage = .report_stack;
...@@ -413,9 +419,9 @@ const PanicSwitch = struct {...@@ -413,9 +419,9 @@ const PanicSwitch = struct {
413 state: *volatile PanicState,419 state: *volatile PanicState,
414 trace: ?*const std.builtin.StackTrace,420 trace: ?*const std.builtin.StackTrace,
415 stack: StackContext,421 stack: StackContext,
416 msg: []const u8,422 panic_cause: std.builtin.PanicCause,
417 ) noreturn {423 ) noreturn {
418 recover(state, trace, stack, msg);424 recover(state, trace, stack, panic_cause);
419425
420 state.recover_stage = .release_mutex;426 state.recover_stage = .release_mutex;
421 const stderr = io.getStdErr().writer();427 const stderr = io.getStdErr().writer();
...@@ -438,9 +444,9 @@ const PanicSwitch = struct {...@@ -438,9 +444,9 @@ const PanicSwitch = struct {
438 state: *volatile PanicState,444 state: *volatile PanicState,
439 trace: ?*const std.builtin.StackTrace,445 trace: ?*const std.builtin.StackTrace,
440 stack: StackContext,446 stack: StackContext,
441 msg: []const u8,447 panic_cause: std.builtin.PanicCause,
442 ) noreturn {448 ) noreturn {
443 recover(state, trace, stack, msg);449 recover(state, trace, stack, panic_cause);
444 goTo(releaseMutex, .{state});450 goTo(releaseMutex, .{state});
445 }451 }
446452
...@@ -456,9 +462,9 @@ const PanicSwitch = struct {...@@ -456,9 +462,9 @@ const PanicSwitch = struct {
456 state: *volatile PanicState,462 state: *volatile PanicState,
457 trace: ?*const std.builtin.StackTrace,463 trace: ?*const std.builtin.StackTrace,
458 stack: StackContext,464 stack: StackContext,
459 msg: []const u8,465 panic_cause: std.builtin.PanicCause,
460 ) noreturn {466 ) noreturn {
461 recover(state, trace, stack, msg);467 recover(state, trace, stack, panic_cause);
462 goTo(releaseRefCount, .{state});468 goTo(releaseRefCount, .{state});
463 }469 }
464470
...@@ -484,9 +490,9 @@ const PanicSwitch = struct {...@@ -484,9 +490,9 @@ const PanicSwitch = struct {
484 state: *volatile PanicState,490 state: *volatile PanicState,
485 trace: ?*const std.builtin.StackTrace,491 trace: ?*const std.builtin.StackTrace,
486 stack: StackContext,492 stack: StackContext,
487 msg: []const u8,493 panic_cause: std.builtin.PanicCause,
488 ) noreturn {494 ) noreturn {
489 recover(state, trace, stack, msg);495 recover(state, trace, stack, panic_cause);
490496
491 state.recover_stage = .silent_abort;497 state.recover_stage = .silent_abort;
492 const stderr = io.getStdErr().writer();498 const stderr = io.getStdErr().writer();
...@@ -510,7 +516,7 @@ const PanicSwitch = struct {...@@ -510,7 +516,7 @@ const PanicSwitch = struct {
510 state: *volatile PanicState,516 state: *volatile PanicState,
511 trace: ?*const std.builtin.StackTrace,517 trace: ?*const std.builtin.StackTrace,
512 stack: StackContext,518 stack: StackContext,
513 msg: []const u8,519 panic_cause: std.builtin.PanicCause,
514 ) void {520 ) void {
515 switch (state.recover_verbosity) {521 switch (state.recover_verbosity) {
516 .message_and_stack => {522 .message_and_stack => {
...@@ -519,7 +525,7 @@ const PanicSwitch = struct {...@@ -519,7 +525,7 @@ const PanicSwitch = struct {
519525
520 const stderr = io.getStdErr().writer();526 const stderr = io.getStdErr().writer();
521 stderr.writeAll("\nPanicked during a panic: ") catch {};527 stderr.writeAll("\nPanicked during a panic: ") catch {};
522 stderr.writeAll(msg) catch {};528 stderr.writeAll(panic_cause) catch {};
523 stderr.writeAll("\nInner panic stack:\n") catch {};529 stderr.writeAll("\nInner panic stack:\n") catch {};
524 if (trace) |t| {530 if (trace) |t| {
525 debug.dumpStackTrace(t.*);531 debug.dumpStackTrace(t.*);
...@@ -533,7 +539,7 @@ const PanicSwitch = struct {...@@ -533,7 +539,7 @@ const PanicSwitch = struct {
533539
534 const stderr = io.getStdErr().writer();540 const stderr = io.getStdErr().writer();
535 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};541 stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
536 stderr.writeAll(msg) catch {};542 stderr.writeAll(panic_cause) catch {};
537 stderr.writeAll("\n") catch {};543 stderr.writeAll("\n") catch {};
538544
539 // If we succeed, restore all the way to dumping the stack.545 // If we succeed, restore all the way to dumping the stack.
src/main.zig+4-4
...@@ -826,7 +826,6 @@ fn buildOutputType(...@@ -826,7 +826,6 @@ fn buildOutputType(
826 var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };826 var version: std.SemanticVersion = .{ .major = 0, .minor = 0, .patch = 0 };
827 var have_version = false;827 var have_version = false;
828 var compatibility_version: ?std.SemanticVersion = null;828 var compatibility_version: ?std.SemanticVersion = null;
829 var formatted_panics: ?bool = null;
830 var function_sections = false;829 var function_sections = false;
831 var data_sections = false;830 var data_sections = false;
832 var no_builtin = false;831 var no_builtin = false;
...@@ -1537,9 +1536,11 @@ fn buildOutputType(...@@ -1537,9 +1536,11 @@ fn buildOutputType(
1537 } else if (mem.eql(u8, arg, "-gdwarf64")) {1536 } else if (mem.eql(u8, arg, "-gdwarf64")) {
1538 create_module.opts.debug_format = .{ .dwarf = .@"64" };1537 create_module.opts.debug_format = .{ .dwarf = .@"64" };
1539 } else if (mem.eql(u8, arg, "-fformatted-panics")) {1538 } else if (mem.eql(u8, arg, "-fformatted-panics")) {
1540 formatted_panics = true;1539 // Remove this after 0.15.0 is tagged.
1540 warn("-fformatted-panics is deprecated and does nothing", .{});
1541 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {1541 } else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
1542 formatted_panics = false;1542 // Remove this after 0.15.0 is tagged.
1543 warn("-fno-formatted-panics is deprecated and does nothing", .{});
1543 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {1544 } else if (mem.eql(u8, arg, "-fsingle-threaded")) {
1544 mod_opts.single_threaded = true;1545 mod_opts.single_threaded = true;
1545 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {1546 } else if (mem.eql(u8, arg, "-fno-single-threaded")) {
...@@ -3405,7 +3406,6 @@ fn buildOutputType(...@@ -3405,7 +3406,6 @@ fn buildOutputType(
3405 .force_undefined_symbols = force_undefined_symbols,3406 .force_undefined_symbols = force_undefined_symbols,
3406 .stack_size = stack_size,3407 .stack_size = stack_size,
3407 .image_base = image_base,3408 .image_base = image_base,
3408 .formatted_panics = formatted_panics,
3409 .function_sections = function_sections,3409 .function_sections = function_sections,
3410 .data_sections = data_sections,3410 .data_sections = data_sections,
3411 .no_builtin = no_builtin,3411 .no_builtin = no_builtin,
src/mutable_value.zig+2-2
...@@ -88,11 +88,11 @@ pub const MutableValue = union(enum) {...@@ -88,11 +88,11 @@ pub const MutableValue = union(enum) {
88 .ptr = (try s.ptr.intern(pt, arena)).toIntern(),88 .ptr = (try s.ptr.intern(pt, arena)).toIntern(),
89 .len = (try s.len.intern(pt, arena)).toIntern(),89 .len = (try s.len.intern(pt, arena)).toIntern(),
90 } }),90 } }),
91 .un => |u| try pt.intern(.{ .un = .{91 .un => |u| try pt.internUnion(.{
92 .ty = u.ty,92 .ty = u.ty,
93 .tag = u.tag,93 .tag = u.tag,
94 .val = (try u.payload.intern(pt, arena)).toIntern(),94 .val = (try u.payload.intern(pt, arena)).toIntern(),
95 } }),95 }),
96 });96 });
97 }97 }
9898
src/target.zig-8
...@@ -586,14 +586,6 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt...@@ -586,14 +586,6 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
586 => true,586 => true,
587 else => false,587 else => false,
588 },588 },
589 .panic_unwrap_error => switch (backend) {
590 .stage2_c, .stage2_llvm => true,
591 else => false,
592 },
593 .safety_check_formatted => switch (backend) {
594 .stage2_c, .stage2_llvm => true,
595 else => false,
596 },
597 .error_return_trace => switch (backend) {589 .error_return_trace => switch (backend) {
598 .stage2_llvm => true,590 .stage2_llvm => true,
599 else => false,591 else => false,
test/cases/safety/unreachable.zig+2-1
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
4 _ = stack_trace;4 _ = stack_trace;
5 _ = ret_addr;
5 if (std.mem.eql(u8, message, "reached unreachable code")) {6 if (std.mem.eql(u8, message, "reached unreachable code")) {
6 std.process.exit(0);7 std.process.exit(0);
7 }8 }