| author | |
| committer | |
| log | 8ba3812eeedec643dd045e0fecb8a6697f6253db |
| tree | 00c47f03ccef1a0398163b5af7063501860d18fe |
| parent | 921725427efeae591793f49291807a41112ccbf9 |
| parent | b6726913d31f9273317ab56c4d33096aee0a588f |
| signature |
compiler: yet more panic handler changes23 files changed, 828 insertions(+), 543 deletions(-)
lib/compiler_rt/common.zig+1-10| ... | ... | @@ -78,16 +78,7 @@ pub const want_sparc_abi = builtin.cpu.arch.isSPARC(); |
| 78 | 78 | |
| 79 | 79 | // Avoid dragging in the runtime safety mechanisms into this .o file, unless |
| 80 | 80 | // we're trying to test compiler-rt. |
| 81 | pub const Panic = if (builtin.is_test) std.debug.FormattedPanic else struct {}; | |
| 82 | ||
| 83 | /// To be deleted after zig1.wasm is updated. | |
| 84 | pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn { | |
| 85 | if (builtin.is_test) { | |
| 86 | std.debug.defaultPanic(msg, error_return_trace, ret_addr orelse @returnAddress()); | |
| 87 | } else { | |
| 88 | unreachable; | |
| 89 | } | |
| 90 | } | |
| 81 | pub const panic = if (builtin.is_test) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.no_panic; | |
| 91 | 82 | |
| 92 | 83 | /// AArch64 is the only ABI (at the moment) to support f16 arguments without the |
| 93 | 84 | /// need for extending them to wider fp types. |
lib/std/Target.zig+1-1| ... | ... | @@ -370,7 +370,7 @@ pub const Os = struct { |
| 370 | 370 | range: std.SemanticVersion.Range, |
| 371 | 371 | glibc: std.SemanticVersion, |
| 372 | 372 | /// Android API level. |
| 373 | android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated. | |
| 373 | android: u32, | |
| 374 | 374 | |
| 375 | 375 | pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool { |
| 376 | 376 | return range.range.includesVersion(ver); |
lib/std/builtin.zig+20-35| ... | ... | @@ -1110,46 +1110,31 @@ pub const TestFn = struct { |
| 1110 | 1110 | /// Deprecated, use the `Panic` namespace instead. |
| 1111 | 1111 | /// To be deleted after 0.14.0 is released. |
| 1112 | 1112 | pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn; |
| 1113 | /// Deprecated, use the `Panic` namespace instead. | |
| 1114 | /// To be deleted after 0.14.0 is released. | |
| 1115 | pub const panic: PanicFn = Panic.call; | |
| 1116 | 1113 | |
| 1117 | 1114 | /// This namespace is used by the Zig compiler to emit various kinds of safety |
| 1118 | /// panics. These can be overridden by making a public `Panic` namespace in the | |
| 1115 | /// panics. These can be overridden by making a public `panic` namespace in the | |
| 1119 | 1116 | /// root source file. |
| 1120 | pub const Panic: type = if (@hasDecl(root, "Panic")) | |
| 1121 | root.Panic | |
| 1122 | else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead. | |
| 1123 | DeprecatedPanic | |
| 1124 | else if (builtin.zig_backend == .stage2_riscv64) | |
| 1125 | std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519 | |
| 1126 | else | |
| 1127 | std.debug.FormattedPanic; | |
| 1128 | ||
| 1129 | /// To be deleted after 0.14.0 is released. | |
| 1130 | const DeprecatedPanic = struct { | |
| 1131 | pub const call = root.panic; | |
| 1132 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 1133 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 1134 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 1135 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 1136 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 1137 | pub const messages = std.debug.FormattedPanic.messages; | |
| 1117 | pub const panic: type = p: { | |
| 1118 | if (@hasDecl(root, "panic")) { | |
| 1119 | if (@TypeOf(root.panic) != type) { | |
| 1120 | // Deprecated; make `panic` a namespace instead. | |
| 1121 | break :p std.debug.FullPanic(struct { | |
| 1122 | fn panic(msg: []const u8, ra: ?usize) noreturn { | |
| 1123 | root.panic(msg, @errorReturnTrace(), ra); | |
| 1124 | } | |
| 1125 | }.panic); | |
| 1126 | } | |
| 1127 | break :p root.panic; | |
| 1128 | } | |
| 1129 | if (@hasDecl(root, "Panic")) { | |
| 1130 | break :p root.Panic; // Deprecated; use `panic` instead. | |
| 1131 | } | |
| 1132 | if (builtin.zig_backend == .stage2_riscv64) { | |
| 1133 | break :p std.debug.simple_panic; | |
| 1134 | } | |
| 1135 | break :p std.debug.FullPanic(std.debug.defaultPanic); | |
| 1138 | 1136 | }; |
| 1139 | 1137 | |
| 1140 | /// To be deleted after zig1.wasm is updated. | |
| 1141 | pub const panicSentinelMismatch = Panic.sentinelMismatch; | |
| 1142 | /// To be deleted after zig1.wasm is updated. | |
| 1143 | pub const panicUnwrapError = Panic.unwrapError; | |
| 1144 | /// To be deleted after zig1.wasm is updated. | |
| 1145 | pub const panicOutOfBounds = Panic.outOfBounds; | |
| 1146 | /// To be deleted after zig1.wasm is updated. | |
| 1147 | pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd; | |
| 1148 | /// To be deleted after zig1.wasm is updated. | |
| 1149 | pub const panicInactiveUnionField = Panic.inactiveUnionField; | |
| 1150 | /// To be deleted after zig1.wasm is updated. | |
| 1151 | pub const panic_messages = Panic.messages; | |
| 1152 | ||
| 1153 | 1138 | pub noinline fn returnError() void { |
| 1154 | 1139 | @branchHint(.unlikely); |
| 1155 | 1140 | @setRuntimeSafety(false); |
lib/std/debug.zig+119-9| ... | ... | @@ -21,9 +21,121 @@ pub const SelfInfo = @import("debug/SelfInfo.zig"); |
| 21 | 21 | pub const Info = @import("debug/Info.zig"); |
| 22 | 22 | pub const Coverage = @import("debug/Coverage.zig"); |
| 23 | 23 | |
| 24 | pub const FormattedPanic = @import("debug/FormattedPanic.zig"); | |
| 25 | pub const SimplePanic = @import("debug/SimplePanic.zig"); | |
| 26 | pub const NoPanic = @import("debug/NoPanic.zig"); | |
| 24 | pub const simple_panic = @import("debug/simple_panic.zig"); | |
| 25 | pub const no_panic = @import("debug/no_panic.zig"); | |
| 26 | ||
| 27 | /// A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`. | |
| 28 | /// Safety panics will use formatted printing to provide a meaningful error message. | |
| 29 | /// The signature of `panicFn` should match that of `defaultPanic`. | |
| 30 | pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { | |
| 31 | return struct { | |
| 32 | pub const call = panicFn; | |
| 33 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | |
| 34 | @branchHint(.cold); | |
| 35 | std.debug.panicExtra(@returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ | |
| 36 | expected, found, | |
| 37 | }); | |
| 38 | } | |
| 39 | pub fn unwrapError(err: anyerror) noreturn { | |
| 40 | @branchHint(.cold); | |
| 41 | std.debug.panicExtra(@returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); | |
| 42 | } | |
| 43 | pub fn outOfBounds(index: usize, len: usize) noreturn { | |
| 44 | @branchHint(.cold); | |
| 45 | std.debug.panicExtra(@returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); | |
| 46 | } | |
| 47 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | |
| 48 | @branchHint(.cold); | |
| 49 | std.debug.panicExtra(@returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); | |
| 50 | } | |
| 51 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | |
| 52 | @branchHint(.cold); | |
| 53 | std.debug.panicExtra(@returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ | |
| 54 | @tagName(accessed), @tagName(active), | |
| 55 | }); | |
| 56 | } | |
| 57 | pub fn reachedUnreachable() noreturn { | |
| 58 | @branchHint(.cold); | |
| 59 | call("reached unreachable code", @returnAddress()); | |
| 60 | } | |
| 61 | pub fn unwrapNull() noreturn { | |
| 62 | @branchHint(.cold); | |
| 63 | call("attempt to use null value", @returnAddress()); | |
| 64 | } | |
| 65 | pub fn castToNull() noreturn { | |
| 66 | @branchHint(.cold); | |
| 67 | call("cast causes pointer to be null", @returnAddress()); | |
| 68 | } | |
| 69 | pub fn incorrectAlignment() noreturn { | |
| 70 | @branchHint(.cold); | |
| 71 | call("incorrect alignment", @returnAddress()); | |
| 72 | } | |
| 73 | pub fn invalidErrorCode() noreturn { | |
| 74 | @branchHint(.cold); | |
| 75 | call("invalid error code", @returnAddress()); | |
| 76 | } | |
| 77 | pub fn castTruncatedData() noreturn { | |
| 78 | @branchHint(.cold); | |
| 79 | call("integer cast truncated bits", @returnAddress()); | |
| 80 | } | |
| 81 | pub fn negativeToUnsigned() noreturn { | |
| 82 | @branchHint(.cold); | |
| 83 | call("attempt to cast negative value to unsigned integer", @returnAddress()); | |
| 84 | } | |
| 85 | pub fn integerOverflow() noreturn { | |
| 86 | @branchHint(.cold); | |
| 87 | call("integer overflow", @returnAddress()); | |
| 88 | } | |
| 89 | pub fn shlOverflow() noreturn { | |
| 90 | @branchHint(.cold); | |
| 91 | call("left shift overflowed bits", @returnAddress()); | |
| 92 | } | |
| 93 | pub fn shrOverflow() noreturn { | |
| 94 | @branchHint(.cold); | |
| 95 | call("right shift overflowed bits", @returnAddress()); | |
| 96 | } | |
| 97 | pub fn divideByZero() noreturn { | |
| 98 | @branchHint(.cold); | |
| 99 | call("division by zero", @returnAddress()); | |
| 100 | } | |
| 101 | pub fn exactDivisionRemainder() noreturn { | |
| 102 | @branchHint(.cold); | |
| 103 | call("exact division produced remainder", @returnAddress()); | |
| 104 | } | |
| 105 | pub fn integerPartOutOfBounds() noreturn { | |
| 106 | @branchHint(.cold); | |
| 107 | call("integer part of floating point value out of bounds", @returnAddress()); | |
| 108 | } | |
| 109 | pub fn corruptSwitch() noreturn { | |
| 110 | @branchHint(.cold); | |
| 111 | call("switch on corrupt value", @returnAddress()); | |
| 112 | } | |
| 113 | pub fn shiftRhsTooBig() noreturn { | |
| 114 | @branchHint(.cold); | |
| 115 | call("shift amount is greater than the type size", @returnAddress()); | |
| 116 | } | |
| 117 | pub fn invalidEnumValue() noreturn { | |
| 118 | @branchHint(.cold); | |
| 119 | call("invalid enum value", @returnAddress()); | |
| 120 | } | |
| 121 | pub fn forLenMismatch() noreturn { | |
| 122 | @branchHint(.cold); | |
| 123 | call("for loop over objects with non-equal lengths", @returnAddress()); | |
| 124 | } | |
| 125 | pub fn memcpyLenMismatch() noreturn { | |
| 126 | @branchHint(.cold); | |
| 127 | call("@memcpy arguments have non-equal lengths", @returnAddress()); | |
| 128 | } | |
| 129 | pub fn memcpyAlias() noreturn { | |
| 130 | @branchHint(.cold); | |
| 131 | call("@memcpy arguments alias", @returnAddress()); | |
| 132 | } | |
| 133 | pub fn noreturnReturned() noreturn { | |
| 134 | @branchHint(.cold); | |
| 135 | call("'noreturn' function returned", @returnAddress()); | |
| 136 | } | |
| 137 | }; | |
| 138 | } | |
| 27 | 139 | |
| 28 | 140 | /// Unresolved source locations can be represented with a single `usize` that |
| 29 | 141 | /// corresponds to a virtual memory address of the program counter. Combined |
| ... | ... | @@ -416,13 +528,12 @@ pub fn assertReadable(slice: []const volatile u8) void { |
| 416 | 528 | /// Equivalent to `@panic` but with a formatted message. |
| 417 | 529 | pub fn panic(comptime format: []const u8, args: anytype) noreturn { |
| 418 | 530 | @branchHint(.cold); |
| 419 | panicExtra(@errorReturnTrace(), @returnAddress(), format, args); | |
| 531 | panicExtra(@returnAddress(), format, args); | |
| 420 | 532 | } |
| 421 | 533 | |
| 422 | 534 | /// Equivalent to `@panic` but with a formatted message, and with an explicitly |
| 423 | /// provided `@errorReturnTrace` and return address. | |
| 535 | /// provided return address. | |
| 424 | 536 | pub fn panicExtra( |
| 425 | trace: ?*std.builtin.StackTrace, | |
| 426 | 537 | ret_addr: ?usize, |
| 427 | 538 | comptime format: []const u8, |
| 428 | 539 | args: anytype, |
| ... | ... | @@ -441,7 +552,7 @@ pub fn panicExtra( |
| 441 | 552 | break :blk &buf; |
| 442 | 553 | }, |
| 443 | 554 | }; |
| 444 | std.builtin.Panic.call(msg, trace, ret_addr); | |
| 555 | std.builtin.panic.call(msg, ret_addr); | |
| 445 | 556 | } |
| 446 | 557 | |
| 447 | 558 | /// Non-zero whenever the program triggered a panic. |
| ... | ... | @@ -455,7 +566,6 @@ threadlocal var panic_stage: usize = 0; |
| 455 | 566 | /// Dumps a stack trace to standard error, then aborts. |
| 456 | 567 | pub fn defaultPanic( |
| 457 | 568 | msg: []const u8, |
| 458 | error_return_trace: ?*const std.builtin.StackTrace, | |
| 459 | 569 | first_trace_addr: ?usize, |
| 460 | 570 | ) noreturn { |
| 461 | 571 | @branchHint(.cold); |
| ... | ... | @@ -542,7 +652,7 @@ pub fn defaultPanic( |
| 542 | 652 | } |
| 543 | 653 | stderr.print("{s}\n", .{msg}) catch posix.abort(); |
| 544 | 654 | |
| 545 | if (error_return_trace) |t| dumpStackTrace(t.*); | |
| 655 | if (@errorReturnTrace()) |t| dumpStackTrace(t.*); | |
| 546 | 656 | dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); |
| 547 | 657 | } |
| 548 | 658 |
lib/std/debug/FormattedPanic.zig deleted-45| ... | ... | @@ -1,45 +0,0 @@ |
| 1 | //! This namespace is the default one used by the Zig compiler to emit various | |
| 2 | //! kinds of safety panics, due to the logic in `std.builtin.Panic`. | |
| 3 | //! | |
| 4 | //! Since Zig does not have interfaces, this file serves as an example template | |
| 5 | //! for users to provide their own alternative panic handling. | |
| 6 | //! | |
| 7 | //! As an alternative, see `std.debug.SimplePanic`. | |
| 8 | ||
| 9 | const std = @import("../std.zig"); | |
| 10 | ||
| 11 | /// Dumps a stack trace to standard error, then aborts. | |
| 12 | /// | |
| 13 | /// Explicit calls to `@panic` lower to calling this function. | |
| 14 | pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic; | |
| 15 | ||
| 16 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | |
| 17 | @branchHint(.cold); | |
| 18 | std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ | |
| 19 | expected, found, | |
| 20 | }); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { | |
| 24 | @branchHint(.cold); | |
| 25 | std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn outOfBounds(index: usize, len: usize) noreturn { | |
| 29 | @branchHint(.cold); | |
| 30 | std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); | |
| 31 | } | |
| 32 | ||
| 33 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | |
| 34 | @branchHint(.cold); | |
| 35 | std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); | |
| 36 | } | |
| 37 | ||
| 38 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | |
| 39 | @branchHint(.cold); | |
| 40 | std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ | |
| 41 | @tagName(accessed), @tagName(active), | |
| 42 | }); | |
| 43 | } | |
| 44 | ||
| 45 | pub const messages = std.debug.SimplePanic.messages; |
lib/std/debug/NoPanic.zig deleted-59| ... | ... | @@ -1,59 +0,0 @@ |
| 1 | //! This namespace can be used with `pub const Panic = std.debug.NoPanic;` in the root file. | |
| 2 | //! It emits as little code as possible, for testing purposes. | |
| 3 | //! | |
| 4 | //! For a functional alternative, see `std.debug.FormattedPanic`. | |
| 5 | ||
| 6 | const std = @import("../std.zig"); | |
| 7 | ||
| 8 | pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 9 | @branchHint(.cold); | |
| 10 | @trap(); | |
| 11 | } | |
| 12 | ||
| 13 | pub fn sentinelMismatch(_: anytype, _: anytype) noreturn { | |
| 14 | @branchHint(.cold); | |
| 15 | @trap(); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn { | |
| 19 | @branchHint(.cold); | |
| 20 | @trap(); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn outOfBounds(_: usize, _: usize) noreturn { | |
| 24 | @branchHint(.cold); | |
| 25 | @trap(); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn startGreaterThanEnd(_: usize, _: usize) noreturn { | |
| 29 | @branchHint(.cold); | |
| 30 | @trap(); | |
| 31 | } | |
| 32 | ||
| 33 | pub fn inactiveUnionField(_: anytype, _: anytype) noreturn { | |
| 34 | @branchHint(.cold); | |
| 35 | @trap(); | |
| 36 | } | |
| 37 | ||
| 38 | pub const messages = struct { | |
| 39 | pub const reached_unreachable = ""; | |
| 40 | pub const unwrap_null = ""; | |
| 41 | pub const cast_to_null = ""; | |
| 42 | pub const incorrect_alignment = ""; | |
| 43 | pub const invalid_error_code = ""; | |
| 44 | pub const cast_truncated_data = ""; | |
| 45 | pub const negative_to_unsigned = ""; | |
| 46 | pub const integer_overflow = ""; | |
| 47 | pub const shl_overflow = ""; | |
| 48 | pub const shr_overflow = ""; | |
| 49 | pub const divide_by_zero = ""; | |
| 50 | pub const exact_division_remainder = ""; | |
| 51 | pub const integer_part_out_of_bounds = ""; | |
| 52 | pub const corrupt_switch = ""; | |
| 53 | pub const shift_rhs_too_big = ""; | |
| 54 | pub const invalid_enum_value = ""; | |
| 55 | pub const for_len_mismatch = ""; | |
| 56 | pub const memcpy_len_mismatch = ""; | |
| 57 | pub const memcpy_alias = ""; | |
| 58 | pub const noreturn_returned = ""; | |
| 59 | }; |
lib/std/debug/SimplePanic.zig deleted-86| ... | ... | @@ -1,86 +0,0 @@ |
| 1 | //! This namespace is the default one used by the Zig compiler to emit various | |
| 2 | //! kinds of safety panics, due to the logic in `std.builtin.Panic`. | |
| 3 | //! | |
| 4 | //! Since Zig does not have interfaces, this file serves as an example template | |
| 5 | //! for users to provide their own alternative panic handling. | |
| 6 | //! | |
| 7 | //! As an alternative, see `std.debug.FormattedPanic`. | |
| 8 | ||
| 9 | const std = @import("../std.zig"); | |
| 10 | ||
| 11 | /// Prints the message to stderr without a newline and then traps. | |
| 12 | /// | |
| 13 | /// Explicit calls to `@panic` lower to calling this function. | |
| 14 | pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn { | |
| 15 | @branchHint(.cold); | |
| 16 | _ = ert; | |
| 17 | _ = ra; | |
| 18 | std.debug.lockStdErr(); | |
| 19 | const stderr = std.io.getStdErr(); | |
| 20 | stderr.writeAll(msg) catch {}; | |
| 21 | @trap(); | |
| 22 | } | |
| 23 | ||
| 24 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | |
| 25 | _ = found; | |
| 26 | call("sentinel mismatch", null, null); | |
| 27 | } | |
| 28 | ||
| 29 | pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { | |
| 30 | _ = ert; | |
| 31 | _ = &err; | |
| 32 | call("attempt to unwrap error", null, null); | |
| 33 | } | |
| 34 | ||
| 35 | pub fn outOfBounds(index: usize, len: usize) noreturn { | |
| 36 | _ = index; | |
| 37 | _ = len; | |
| 38 | call("index out of bounds", null, null); | |
| 39 | } | |
| 40 | ||
| 41 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | |
| 42 | _ = start; | |
| 43 | _ = end; | |
| 44 | call("start index is larger than end index", null, null); | |
| 45 | } | |
| 46 | ||
| 47 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | |
| 48 | _ = accessed; | |
| 49 | call("access of inactive union field", null, null); | |
| 50 | } | |
| 51 | ||
| 52 | pub const messages = struct { | |
| 53 | pub const reached_unreachable = "reached unreachable code"; | |
| 54 | pub const unwrap_null = "attempt to use null value"; | |
| 55 | pub const cast_to_null = "cast causes pointer to be null"; | |
| 56 | pub const incorrect_alignment = "incorrect alignment"; | |
| 57 | pub const invalid_error_code = "invalid error code"; | |
| 58 | pub const cast_truncated_data = "integer cast truncated bits"; | |
| 59 | pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer"; | |
| 60 | pub const integer_overflow = "integer overflow"; | |
| 61 | pub const shl_overflow = "left shift overflowed bits"; | |
| 62 | pub const shr_overflow = "right shift overflowed bits"; | |
| 63 | pub const divide_by_zero = "division by zero"; | |
| 64 | pub const exact_division_remainder = "exact division produced remainder"; | |
| 65 | pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds"; | |
| 66 | pub const corrupt_switch = "switch on corrupt value"; | |
| 67 | pub const shift_rhs_too_big = "shift amount is greater than the type size"; | |
| 68 | pub const invalid_enum_value = "invalid enum value"; | |
| 69 | pub const for_len_mismatch = "for loop over objects with non-equal lengths"; | |
| 70 | pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths"; | |
| 71 | pub const memcpy_alias = "@memcpy arguments alias"; | |
| 72 | pub const noreturn_returned = "'noreturn' function returned"; | |
| 73 | ||
| 74 | /// To be deleted after zig1.wasm is updated. | |
| 75 | pub const inactive_union_field = "access of inactive union field"; | |
| 76 | /// To be deleted after zig1.wasm is updated. | |
| 77 | pub const sentinel_mismatch = "sentinel mismatch"; | |
| 78 | /// To be deleted after zig1.wasm is updated. | |
| 79 | pub const unwrap_error = "attempt to unwrap error"; | |
| 80 | /// To be deleted after zig1.wasm is updated. | |
| 81 | pub const index_out_of_bounds = "index out of bounds"; | |
| 82 | /// To be deleted after zig1.wasm is updated. | |
| 83 | pub const start_index_greater_than_end = "start index is larger than end index"; | |
| 84 | /// To be deleted after zig1.wasm is updated. | |
| 85 | pub const unreach = reached_unreachable; | |
| 86 | }; |
lib/std/debug/no_panic.zig created+136| ... | ... | @@ -0,0 +1,136 @@ |
| 1 | //! This namespace can be used with `pub const panic = std.debug.no_panic;` in the root file. | |
| 2 | //! It emits as little code as possible, for testing purposes. | |
| 3 | //! | |
| 4 | //! For a functional alternative, see `std.debug.FullPanic`. | |
| 5 | ||
| 6 | const std = @import("../std.zig"); | |
| 7 | ||
| 8 | pub fn call(_: []const u8, _: ?usize) noreturn { | |
| 9 | @branchHint(.cold); | |
| 10 | @trap(); | |
| 11 | } | |
| 12 | ||
| 13 | pub fn sentinelMismatch(_: anytype, _: anytype) noreturn { | |
| 14 | @branchHint(.cold); | |
| 15 | @trap(); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn unwrapError(_: anyerror) noreturn { | |
| 19 | @branchHint(.cold); | |
| 20 | @trap(); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn outOfBounds(_: usize, _: usize) noreturn { | |
| 24 | @branchHint(.cold); | |
| 25 | @trap(); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn startGreaterThanEnd(_: usize, _: usize) noreturn { | |
| 29 | @branchHint(.cold); | |
| 30 | @trap(); | |
| 31 | } | |
| 32 | ||
| 33 | pub fn inactiveUnionField(_: anytype, _: anytype) noreturn { | |
| 34 | @branchHint(.cold); | |
| 35 | @trap(); | |
| 36 | } | |
| 37 | ||
| 38 | pub fn reachedUnreachable() noreturn { | |
| 39 | @branchHint(.cold); | |
| 40 | @trap(); | |
| 41 | } | |
| 42 | ||
| 43 | pub fn unwrapNull() noreturn { | |
| 44 | @branchHint(.cold); | |
| 45 | @trap(); | |
| 46 | } | |
| 47 | ||
| 48 | pub fn castToNull() noreturn { | |
| 49 | @branchHint(.cold); | |
| 50 | @trap(); | |
| 51 | } | |
| 52 | ||
| 53 | pub fn incorrectAlignment() noreturn { | |
| 54 | @branchHint(.cold); | |
| 55 | @trap(); | |
| 56 | } | |
| 57 | ||
| 58 | pub fn invalidErrorCode() noreturn { | |
| 59 | @branchHint(.cold); | |
| 60 | @trap(); | |
| 61 | } | |
| 62 | ||
| 63 | pub fn castTruncatedData() noreturn { | |
| 64 | @branchHint(.cold); | |
| 65 | @trap(); | |
| 66 | } | |
| 67 | ||
| 68 | pub fn negativeToUnsigned() noreturn { | |
| 69 | @branchHint(.cold); | |
| 70 | @trap(); | |
| 71 | } | |
| 72 | ||
| 73 | pub fn integerOverflow() noreturn { | |
| 74 | @branchHint(.cold); | |
| 75 | @trap(); | |
| 76 | } | |
| 77 | ||
| 78 | pub fn shlOverflow() noreturn { | |
| 79 | @branchHint(.cold); | |
| 80 | @trap(); | |
| 81 | } | |
| 82 | ||
| 83 | pub fn shrOverflow() noreturn { | |
| 84 | @branchHint(.cold); | |
| 85 | @trap(); | |
| 86 | } | |
| 87 | ||
| 88 | pub fn divideByZero() noreturn { | |
| 89 | @branchHint(.cold); | |
| 90 | @trap(); | |
| 91 | } | |
| 92 | ||
| 93 | pub fn exactDivisionRemainder() noreturn { | |
| 94 | @branchHint(.cold); | |
| 95 | @trap(); | |
| 96 | } | |
| 97 | ||
| 98 | pub fn integerPartOutOfBounds() noreturn { | |
| 99 | @branchHint(.cold); | |
| 100 | @trap(); | |
| 101 | } | |
| 102 | ||
| 103 | pub fn corruptSwitch() noreturn { | |
| 104 | @branchHint(.cold); | |
| 105 | @trap(); | |
| 106 | } | |
| 107 | ||
| 108 | pub fn shiftRhsTooBig() noreturn { | |
| 109 | @branchHint(.cold); | |
| 110 | @trap(); | |
| 111 | } | |
| 112 | ||
| 113 | pub fn invalidEnumValue() noreturn { | |
| 114 | @branchHint(.cold); | |
| 115 | @trap(); | |
| 116 | } | |
| 117 | ||
| 118 | pub fn forLenMismatch() noreturn { | |
| 119 | @branchHint(.cold); | |
| 120 | @trap(); | |
| 121 | } | |
| 122 | ||
| 123 | pub fn memcpyLenMismatch() noreturn { | |
| 124 | @branchHint(.cold); | |
| 125 | @trap(); | |
| 126 | } | |
| 127 | ||
| 128 | pub fn memcpyAlias() noreturn { | |
| 129 | @branchHint(.cold); | |
| 130 | @trap(); | |
| 131 | } | |
| 132 | ||
| 133 | pub fn noreturnReturned() noreturn { | |
| 134 | @branchHint(.cold); | |
| 135 | @trap(); | |
| 136 | } |
lib/std/debug/simple_panic.zig created+128| ... | ... | @@ -0,0 +1,128 @@ |
| 1 | //! This namespace is the default one used by the Zig compiler to emit various | |
| 2 | //! kinds of safety panics, due to the logic in `std.builtin.panic`. | |
| 3 | //! | |
| 4 | //! Since Zig does not have interfaces, this file serves as an example template | |
| 5 | //! for users to provide their own alternative panic handling. | |
| 6 | //! | |
| 7 | //! As an alternative, see `std.debug.FullPanic`. | |
| 8 | ||
| 9 | const std = @import("../std.zig"); | |
| 10 | ||
| 11 | /// Prints the message to stderr without a newline and then traps. | |
| 12 | /// | |
| 13 | /// Explicit calls to `@panic` lower to calling this function. | |
| 14 | pub fn call(msg: []const u8, ra: ?usize) noreturn { | |
| 15 | @branchHint(.cold); | |
| 16 | _ = ra; | |
| 17 | std.debug.lockStdErr(); | |
| 18 | const stderr = std.io.getStdErr(); | |
| 19 | stderr.writeAll(msg) catch {}; | |
| 20 | @trap(); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | |
| 24 | _ = found; | |
| 25 | call("sentinel mismatch", null); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn unwrapError(err: anyerror) noreturn { | |
| 29 | _ = &err; | |
| 30 | call("attempt to unwrap error", null); | |
| 31 | } | |
| 32 | ||
| 33 | pub fn outOfBounds(index: usize, len: usize) noreturn { | |
| 34 | _ = index; | |
| 35 | _ = len; | |
| 36 | call("index out of bounds", null); | |
| 37 | } | |
| 38 | ||
| 39 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | |
| 40 | _ = start; | |
| 41 | _ = end; | |
| 42 | call("start index is larger than end index", null); | |
| 43 | } | |
| 44 | ||
| 45 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | |
| 46 | _ = accessed; | |
| 47 | call("access of inactive union field", null); | |
| 48 | } | |
| 49 | ||
| 50 | pub fn reachedUnreachable() noreturn { | |
| 51 | call("reached unreachable code", null); | |
| 52 | } | |
| 53 | ||
| 54 | pub fn unwrapNull() noreturn { | |
| 55 | call("attempt to use null value", null); | |
| 56 | } | |
| 57 | ||
| 58 | pub fn castToNull() noreturn { | |
| 59 | call("cast causes pointer to be null", null); | |
| 60 | } | |
| 61 | ||
| 62 | pub fn incorrectAlignment() noreturn { | |
| 63 | call("incorrect alignment", null); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn invalidErrorCode() noreturn { | |
| 67 | call("invalid error code", null); | |
| 68 | } | |
| 69 | ||
| 70 | pub fn castTruncatedData() noreturn { | |
| 71 | call("integer cast truncated bits", null); | |
| 72 | } | |
| 73 | ||
| 74 | pub fn negativeToUnsigned() noreturn { | |
| 75 | call("attempt to cast negative value to unsigned integer", null); | |
| 76 | } | |
| 77 | ||
| 78 | pub fn integerOverflow() noreturn { | |
| 79 | call("integer overflow", null); | |
| 80 | } | |
| 81 | ||
| 82 | pub fn shlOverflow() noreturn { | |
| 83 | call("left shift overflowed bits", null); | |
| 84 | } | |
| 85 | ||
| 86 | pub fn shrOverflow() noreturn { | |
| 87 | call("right shift overflowed bits", null); | |
| 88 | } | |
| 89 | ||
| 90 | pub fn divideByZero() noreturn { | |
| 91 | call("division by zero", null); | |
| 92 | } | |
| 93 | ||
| 94 | pub fn exactDivisionRemainder() noreturn { | |
| 95 | call("exact division produced remainder", null); | |
| 96 | } | |
| 97 | ||
| 98 | pub fn integerPartOutOfBounds() noreturn { | |
| 99 | call("integer part of floating point value out of bounds", null); | |
| 100 | } | |
| 101 | ||
| 102 | pub fn corruptSwitch() noreturn { | |
| 103 | call("switch on corrupt value", null); | |
| 104 | } | |
| 105 | ||
| 106 | pub fn shiftRhsTooBig() noreturn { | |
| 107 | call("shift amount is greater than the type size", null); | |
| 108 | } | |
| 109 | ||
| 110 | pub fn invalidEnumValue() noreturn { | |
| 111 | call("invalid enum value", null); | |
| 112 | } | |
| 113 | ||
| 114 | pub fn forLenMismatch() noreturn { | |
| 115 | call("for loop over objects with non-equal lengths", null); | |
| 116 | } | |
| 117 | ||
| 118 | pub fn memcpyLenMismatch() noreturn { | |
| 119 | call("@memcpy arguments have non-equal lengths", null); | |
| 120 | } | |
| 121 | ||
| 122 | pub fn memcpyAlias() noreturn { | |
| 123 | call("@memcpy arguments alias", null); | |
| 124 | } | |
| 125 | ||
| 126 | pub fn noreturnReturned() noreturn { | |
| 127 | call("'noreturn' function returned", null); | |
| 128 | } |
lib/std/meta.zig+1-2| ... | ... | @@ -448,8 +448,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 { |
| 448 | 448 | return comptime blk: { |
| 449 | 449 | const fieldInfos = fields(T); |
| 450 | 450 | var names: [fieldInfos.len][:0]const u8 = undefined; |
| 451 | // This concat can be removed with the next zig1 update. | |
| 452 | for (&names, fieldInfos) |*name, field| name.* = field.name ++ ""; | |
| 451 | for (&names, fieldInfos) |*name, field| name.* = field.name; | |
| 453 | 452 | const final = names; |
| 454 | 453 | break :blk &final; |
| 455 | 454 | }; |
src/Sema.zig+94-102| ... | ... | @@ -2584,7 +2584,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg |
| 2584 | 2584 | std.debug.print("compile error during Sema:\n", .{}); |
| 2585 | 2585 | var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); |
| 2586 | 2586 | error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); |
| 2587 | crash_report.compilerPanic("unexpected compile error occurred", null, null); | |
| 2587 | crash_report.compilerPanic("unexpected compile error occurred", null); | |
| 2588 | 2588 | } |
| 2589 | 2589 | |
| 2590 | 2590 | if (block) |start_block| { |
| ... | ... | @@ -5918,13 +5918,14 @@ fn zirCompileLog( |
| 5918 | 5918 | } |
| 5919 | 5919 | |
| 5920 | 5920 | fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 5921 | const pt = sema.pt; | |
| 5922 | const zcu = pt.zcu; | |
| 5923 | ||
| 5921 | 5924 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 5922 | 5925 | const src = block.nodeOffset(inst_data.src_node); |
| 5923 | 5926 | const msg_inst = try sema.resolveInst(inst_data.operand); |
| 5924 | 5927 | |
| 5925 | // `panicWithMsg` would perform this coercion for us, but we can get a better | |
| 5926 | // source location if we do it here. | |
| 5927 | const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); | |
| 5928 | const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); | |
| 5928 | 5929 | |
| 5929 | 5930 | if (block.isComptime()) { |
| 5930 | 5931 | return sema.fail(block, src, "encountered @panic at comptime", .{}); |
| ... | ... | @@ -5936,7 +5937,22 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 5936 | 5937 | sema.branch_hint = .cold; |
| 5937 | 5938 | } |
| 5938 | 5939 | |
| 5939 | try sema.panicWithMsg(block, src, coerced_msg, .@"@panic"); | |
| 5940 | if (!zcu.backendSupportsFeature(.panic_fn)) { | |
| 5941 | _ = try block.addNoOp(.trap); | |
| 5942 | return; | |
| 5943 | } | |
| 5944 | ||
| 5945 | try sema.ensureMemoizedStateResolved(src, .panic); | |
| 5946 | try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call")); | |
| 5947 | ||
| 5948 | const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call")); | |
| 5949 | ||
| 5950 | const opt_usize_ty = try pt.optionalType(.usize_type); | |
| 5951 | const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ | |
| 5952 | .ty = opt_usize_ty.toIntern(), | |
| 5953 | .val = .none, | |
| 5954 | } }))); | |
| 5955 | try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_ret_addr }, .@"@panic"); | |
| 5940 | 5956 | } |
| 5941 | 5957 | |
| 5942 | 5958 | fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -13787,9 +13803,8 @@ fn maybeErrorUnwrap( |
| 13787 | 13803 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 13788 | 13804 | const msg_inst = try sema.resolveInst(inst_data.operand); |
| 13789 | 13805 | |
| 13790 | const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call"); | |
| 13791 | const err_return_trace = try sema.getErrorReturnTrace(block); | |
| 13792 | const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value }; | |
| 13806 | const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); | |
| 13807 | const args: [2]Air.Inst.Ref = .{ msg_inst, .null_value }; | |
| 13793 | 13808 | try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); |
| 13794 | 13809 | return true; |
| 13795 | 13810 | }, |
| ... | ... | @@ -27083,15 +27098,16 @@ fn explainWhyTypeIsNotPacked( |
| 27083 | 27098 | /// Backends depend on panic decls being available when lowering safety-checked |
| 27084 | 27099 | /// instructions. This function ensures the panic function will be available to |
| 27085 | 27100 | /// be called during that time. |
| 27086 | fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index { | |
| 27101 | fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index { | |
| 27087 | 27102 | const zcu = sema.pt.zcu; |
| 27088 | 27103 | try sema.ensureMemoizedStateResolved(src, .panic); |
| 27089 | try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call")); | |
| 27104 | const panic_func = zcu.builtin_decl_values.get(panic_id.toBuiltin()); | |
| 27105 | try zcu.ensureFuncBodyAnalysisQueued(panic_func); | |
| 27090 | 27106 | switch (sema.owner.unwrap()) { |
| 27091 | 27107 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, |
| 27092 | 27108 | .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true), |
| 27093 | 27109 | } |
| 27094 | return zcu.builtin_decl_values.get(panic_id.toBuiltin()); | |
| 27110 | return panic_func; | |
| 27095 | 27111 | } |
| 27096 | 27112 | |
| 27097 | 27113 | fn addSafetyCheck( |
| ... | ... | @@ -27099,7 +27115,7 @@ fn addSafetyCheck( |
| 27099 | 27115 | parent_block: *Block, |
| 27100 | 27116 | src: LazySrcLoc, |
| 27101 | 27117 | ok: Air.Inst.Ref, |
| 27102 | panic_id: Zcu.PanicId, | |
| 27118 | panic_id: Zcu.SimplePanicId, | |
| 27103 | 27119 | ) !void { |
| 27104 | 27120 | const gpa = sema.gpa; |
| 27105 | 27121 | assert(!parent_block.isComptime()); |
| ... | ... | @@ -27186,29 +27202,6 @@ fn addSafetyCheckExtra( |
| 27186 | 27202 | parent_block.instructions.appendAssumeCapacity(block_inst); |
| 27187 | 27203 | } |
| 27188 | 27204 | |
| 27189 | fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void { | |
| 27190 | const pt = sema.pt; | |
| 27191 | const zcu = pt.zcu; | |
| 27192 | ||
| 27193 | if (!zcu.backendSupportsFeature(.panic_fn)) { | |
| 27194 | _ = try block.addNoOp(.trap); | |
| 27195 | return; | |
| 27196 | } | |
| 27197 | ||
| 27198 | try sema.ensureMemoizedStateResolved(src, .panic); | |
| 27199 | try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call")); | |
| 27200 | ||
| 27201 | const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"Panic.call")); | |
| 27202 | const null_stack_trace = Air.internedToRef(zcu.null_stack_trace); | |
| 27203 | ||
| 27204 | const opt_usize_ty = try pt.optionalType(.usize_type); | |
| 27205 | const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ | |
| 27206 | .ty = opt_usize_ty.toIntern(), | |
| 27207 | .val = .none, | |
| 27208 | } }))); | |
| 27209 | try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation); | |
| 27210 | } | |
| 27211 | ||
| 27212 | 27205 | fn addSafetyCheckUnwrapError( |
| 27213 | 27206 | sema: *Sema, |
| 27214 | 27207 | parent_block: *Block, |
| ... | ... | @@ -27246,10 +27239,8 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air. |
| 27246 | 27239 | if (!zcu.backendSupportsFeature(.panic_fn)) { |
| 27247 | 27240 | _ = try block.addNoOp(.trap); |
| 27248 | 27241 | } else { |
| 27249 | const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError"); | |
| 27250 | const err_return_trace = try sema.getErrorReturnTrace(block); | |
| 27251 | const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; | |
| 27252 | try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); | |
| 27242 | const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError"); | |
| 27243 | try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{err}, .@"safety check"); | |
| 27253 | 27244 | } |
| 27254 | 27245 | } |
| 27255 | 27246 | |
| ... | ... | @@ -27263,7 +27254,7 @@ fn addSafetyCheckIndexOob( |
| 27263 | 27254 | ) !void { |
| 27264 | 27255 | assert(!parent_block.isComptime()); |
| 27265 | 27256 | const ok = try parent_block.addBinOp(cmp_op, index, len); |
| 27266 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len }); | |
| 27257 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.outOfBounds", &.{ index, len }); | |
| 27267 | 27258 | } |
| 27268 | 27259 | |
| 27269 | 27260 | fn addSafetyCheckInactiveUnionField( |
| ... | ... | @@ -27275,7 +27266,7 @@ fn addSafetyCheckInactiveUnionField( |
| 27275 | 27266 | ) !void { |
| 27276 | 27267 | assert(!parent_block.isComptime()); |
| 27277 | 27268 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 27278 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag }); | |
| 27269 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.inactiveUnionField", &.{ active_tag, wanted_tag }); | |
| 27279 | 27270 | } |
| 27280 | 27271 | |
| 27281 | 27272 | fn addSafetyCheckSentinelMismatch( |
| ... | ... | @@ -27316,7 +27307,7 @@ fn addSafetyCheckSentinelMismatch( |
| 27316 | 27307 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); |
| 27317 | 27308 | }; |
| 27318 | 27309 | |
| 27319 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{ | |
| 27310 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ | |
| 27320 | 27311 | expected_sentinel, actual_sentinel, |
| 27321 | 27312 | }); |
| 27322 | 27313 | } |
| ... | ... | @@ -27358,9 +27349,13 @@ fn addSafetyCheckCall( |
| 27358 | 27349 | } |
| 27359 | 27350 | |
| 27360 | 27351 | /// This does not set `sema.branch_hint`. |
| 27361 | fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void { | |
| 27362 | const msg_val = try sema.preparePanicId(src, panic_id); | |
| 27363 | try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check"); | |
| 27352 | fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void { | |
| 27353 | if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) { | |
| 27354 | _ = try block.addNoOp(.trap); | |
| 27355 | } else { | |
| 27356 | const panic_fn = try sema.preparePanicId(src, panic_id); | |
| 27357 | try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{}, .@"safety check"); | |
| 27358 | } | |
| 27364 | 27359 | } |
| 27365 | 27360 | |
| 27366 | 27361 | fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| ... | ... | @@ -32818,7 +32813,7 @@ fn analyzeSlice( |
| 32818 | 32813 | assert(!block.isComptime()); |
| 32819 | 32814 | try sema.requireRuntimeBlock(block, src, runtime_src.?); |
| 32820 | 32815 | const ok = try block.addBinOp(.cmp_lte, start, end); |
| 32821 | try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end }); | |
| 32816 | try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end }); | |
| 32822 | 32817 | } |
| 32823 | 32818 | const new_len = if (by_length) |
| 32824 | 32819 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) |
| ... | ... | @@ -38525,14 +38520,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38525 | 38520 | break :val uncoerced_val; |
| 38526 | 38521 | }, |
| 38527 | 38522 | .func => val: { |
| 38528 | if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| { | |
| 38529 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); | |
| 38530 | break :val .fromInterned(coerced.toInterned().?); | |
| 38531 | } | |
| 38532 | if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") { | |
| 38533 | return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name }); | |
| 38534 | } | |
| 38535 | break :val uncoerced_val; | |
| 38523 | const func_ty = try sema.getExpectedBuiltinFnType(builtin_decl); | |
| 38524 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); | |
| 38525 | break :val .fromInterned(coerced.toInterned().?); | |
| 38536 | 38526 | }, |
| 38537 | 38527 | .string => val: { |
| 38538 | 38528 | const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); |
| ... | ... | @@ -38549,75 +38539,77 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38549 | 38539 | } |
| 38550 | 38540 | } |
| 38551 | 38541 | |
| 38552 | if (stage == .panic) { | |
| 38553 | // We use `getBuiltinType` because this is from an earlier stage. | |
| 38554 | const stack_trace_ty = try sema.getBuiltinType(simple_src, .StackTrace); | |
| 38555 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); | |
| 38556 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); | |
| 38557 | const null_stack_trace = try pt.intern(.{ .opt = .{ | |
| 38558 | .ty = opt_ptr_stack_trace_ty.toIntern(), | |
| 38559 | .val = .none, | |
| 38560 | } }); | |
| 38561 | if (null_stack_trace != zcu.null_stack_trace) { | |
| 38562 | zcu.null_stack_trace = null_stack_trace; | |
| 38563 | any_changed = true; | |
| 38564 | } | |
| 38565 | } | |
| 38566 | ||
| 38567 | 38542 | return any_changed; |
| 38568 | 38543 | } |
| 38569 | 38544 | |
| 38570 | /// Given that `decl.kind() == .func`, get the type expected of the function if necessary. | |
| 38571 | /// If this will be type checked by `Sema` anyway, this function may return `null`. In | |
| 38572 | /// particular, generic functions should return `null`, as `Sema` will necessarily check | |
| 38573 | /// them at instantiation time. Returning non-null is necessary only when backends can emit | |
| 38574 | /// calls to the function, as is the case with the panic handler. | |
| 38575 | fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type { | |
| 38545 | /// Given that `decl.kind() == .func`, get the type expected of the function. | |
| 38546 | fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Type { | |
| 38576 | 38547 | const pt = sema.pt; |
| 38577 | 38548 | return switch (decl) { |
| 38578 | // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` | |
| 38579 | .@"Panic.call" => try pt.funcType(.{ | |
| 38549 | // `noinline fn () void` | |
| 38550 | .returnError => try pt.funcType(.{ | |
| 38551 | .param_types = &.{}, | |
| 38552 | .return_type = .void_type, | |
| 38553 | .is_noinline = true, | |
| 38554 | }), | |
| 38555 | ||
| 38556 | // `fn ([]const u8, ?usize) noreturn` | |
| 38557 | .@"panic.call" => try pt.funcType(.{ | |
| 38580 | 38558 | .param_types = &.{ |
| 38581 | 38559 | .slice_const_u8_type, |
| 38582 | (try pt.optionalType( | |
| 38583 | (try pt.singleMutPtrType( | |
| 38584 | try sema.getBuiltinType(src, .StackTrace), | |
| 38585 | )).toIntern(), | |
| 38586 | )).toIntern(), | |
| 38587 | 38560 | (try pt.optionalType(.usize_type)).toIntern(), |
| 38588 | 38561 | }, |
| 38589 | 38562 | .return_type = .noreturn_type, |
| 38590 | 38563 | }), |
| 38591 | 38564 | |
| 38592 | // `fn (?*StackTrace, anyerror) noreturn` | |
| 38593 | .@"Panic.unwrapError" => try pt.funcType(.{ | |
| 38594 | .param_types = &.{ | |
| 38595 | (try pt.optionalType( | |
| 38596 | (try pt.singleMutPtrType( | |
| 38597 | try sema.getBuiltinType(src, .StackTrace), | |
| 38598 | )).toIntern(), | |
| 38599 | )).toIntern(), | |
| 38600 | .anyerror_type, | |
| 38601 | }, | |
| 38565 | // `fn (anytype, anytype) noreturn` | |
| 38566 | .@"panic.sentinelMismatch", | |
| 38567 | .@"panic.inactiveUnionField", | |
| 38568 | => try pt.funcType(.{ | |
| 38569 | .param_types = &.{ .generic_poison_type, .generic_poison_type }, | |
| 38570 | .return_type = .noreturn_type, | |
| 38571 | .is_generic = true, | |
| 38572 | }), | |
| 38573 | ||
| 38574 | // `fn (anyerror) noreturn` | |
| 38575 | .@"panic.unwrapError" => try pt.funcType(.{ | |
| 38576 | .param_types = &.{.anyerror_type}, | |
| 38602 | 38577 | .return_type = .noreturn_type, |
| 38603 | 38578 | }), |
| 38604 | 38579 | |
| 38605 | 38580 | // `fn (usize, usize) noreturn` |
| 38606 | .@"Panic.outOfBounds", | |
| 38607 | .@"Panic.startGreaterThanEnd", | |
| 38581 | .@"panic.outOfBounds", | |
| 38582 | .@"panic.startGreaterThanEnd", | |
| 38608 | 38583 | => try pt.funcType(.{ |
| 38609 | 38584 | .param_types = &.{ .usize_type, .usize_type }, |
| 38610 | 38585 | .return_type = .noreturn_type, |
| 38611 | 38586 | }), |
| 38612 | 38587 | |
| 38613 | // Generic functions, so calls are necessarily validated by Sema | |
| 38614 | .@"Panic.sentinelMismatch", | |
| 38615 | .@"Panic.inactiveUnionField", | |
| 38616 | => null, | |
| 38617 | ||
| 38618 | // Other functions called exclusively by Sema | |
| 38619 | .returnError, | |
| 38620 | => null, | |
| 38588 | // `fn () noreturn` | |
| 38589 | .@"panic.reachedUnreachable", | |
| 38590 | .@"panic.unwrapNull", | |
| 38591 | .@"panic.castToNull", | |
| 38592 | .@"panic.incorrectAlignment", | |
| 38593 | .@"panic.invalidErrorCode", | |
| 38594 | .@"panic.castTruncatedData", | |
| 38595 | .@"panic.negativeToUnsigned", | |
| 38596 | .@"panic.integerOverflow", | |
| 38597 | .@"panic.shlOverflow", | |
| 38598 | .@"panic.shrOverflow", | |
| 38599 | .@"panic.divideByZero", | |
| 38600 | .@"panic.exactDivisionRemainder", | |
| 38601 | .@"panic.integerPartOutOfBounds", | |
| 38602 | .@"panic.corruptSwitch", | |
| 38603 | .@"panic.shiftRhsTooBig", | |
| 38604 | .@"panic.invalidEnumValue", | |
| 38605 | .@"panic.forLenMismatch", | |
| 38606 | .@"panic.memcpyLenMismatch", | |
| 38607 | .@"panic.memcpyAlias", | |
| 38608 | .@"panic.noreturnReturned", | |
| 38609 | => try pt.funcType(.{ | |
| 38610 | .param_types = &.{}, | |
| 38611 | .return_type = .noreturn_type, | |
| 38612 | }), | |
| 38621 | 38613 | |
| 38622 | 38614 | else => unreachable, |
| 38623 | 38615 | }; |
src/Zcu.zig+81-76| ... | ... | @@ -219,8 +219,6 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty, |
| 219 | 219 | |
| 220 | 220 | /// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = s })`, where `s` depends on the element. |
| 221 | 221 | builtin_decl_values: BuiltinDecl.Memoized = .initFill(.none), |
| 222 | /// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = .panic })`. | |
| 223 | null_stack_trace: InternPool.Index = .none, | |
| 224 | 222 | |
| 225 | 223 | generation: u32 = 0, |
| 226 | 224 | |
| ... | ... | @@ -269,34 +267,33 @@ pub const BuiltinDecl = enum { |
| 269 | 267 | @"Type.Opaque", |
| 270 | 268 | @"Type.Declaration", |
| 271 | 269 | |
| 272 | Panic, | |
| 273 | @"Panic.call", | |
| 274 | @"Panic.sentinelMismatch", | |
| 275 | @"Panic.unwrapError", | |
| 276 | @"Panic.outOfBounds", | |
| 277 | @"Panic.startGreaterThanEnd", | |
| 278 | @"Panic.inactiveUnionField", | |
| 279 | @"Panic.messages", | |
| 280 | @"Panic.messages.reached_unreachable", | |
| 281 | @"Panic.messages.unwrap_null", | |
| 282 | @"Panic.messages.cast_to_null", | |
| 283 | @"Panic.messages.incorrect_alignment", | |
| 284 | @"Panic.messages.invalid_error_code", | |
| 285 | @"Panic.messages.cast_truncated_data", | |
| 286 | @"Panic.messages.negative_to_unsigned", | |
| 287 | @"Panic.messages.integer_overflow", | |
| 288 | @"Panic.messages.shl_overflow", | |
| 289 | @"Panic.messages.shr_overflow", | |
| 290 | @"Panic.messages.divide_by_zero", | |
| 291 | @"Panic.messages.exact_division_remainder", | |
| 292 | @"Panic.messages.integer_part_out_of_bounds", | |
| 293 | @"Panic.messages.corrupt_switch", | |
| 294 | @"Panic.messages.shift_rhs_too_big", | |
| 295 | @"Panic.messages.invalid_enum_value", | |
| 296 | @"Panic.messages.for_len_mismatch", | |
| 297 | @"Panic.messages.memcpy_len_mismatch", | |
| 298 | @"Panic.messages.memcpy_alias", | |
| 299 | @"Panic.messages.noreturn_returned", | |
| 270 | panic, | |
| 271 | @"panic.call", | |
| 272 | @"panic.sentinelMismatch", | |
| 273 | @"panic.unwrapError", | |
| 274 | @"panic.outOfBounds", | |
| 275 | @"panic.startGreaterThanEnd", | |
| 276 | @"panic.inactiveUnionField", | |
| 277 | @"panic.reachedUnreachable", | |
| 278 | @"panic.unwrapNull", | |
| 279 | @"panic.castToNull", | |
| 280 | @"panic.incorrectAlignment", | |
| 281 | @"panic.invalidErrorCode", | |
| 282 | @"panic.castTruncatedData", | |
| 283 | @"panic.negativeToUnsigned", | |
| 284 | @"panic.integerOverflow", | |
| 285 | @"panic.shlOverflow", | |
| 286 | @"panic.shrOverflow", | |
| 287 | @"panic.divideByZero", | |
| 288 | @"panic.exactDivisionRemainder", | |
| 289 | @"panic.integerPartOutOfBounds", | |
| 290 | @"panic.corruptSwitch", | |
| 291 | @"panic.shiftRhsTooBig", | |
| 292 | @"panic.invalidEnumValue", | |
| 293 | @"panic.forLenMismatch", | |
| 294 | @"panic.memcpyLenMismatch", | |
| 295 | @"panic.memcpyAlias", | |
| 296 | @"panic.noreturnReturned", | |
| 300 | 297 | |
| 301 | 298 | VaList, |
| 302 | 299 | |
| ... | ... | @@ -345,39 +342,35 @@ pub const BuiltinDecl = enum { |
| 345 | 342 | .@"Type.Declaration", |
| 346 | 343 | => .type, |
| 347 | 344 | |
| 348 | .Panic => .type, | |
| 349 | ||
| 350 | .@"Panic.call", | |
| 351 | .@"Panic.sentinelMismatch", | |
| 352 | .@"Panic.unwrapError", | |
| 353 | .@"Panic.outOfBounds", | |
| 354 | .@"Panic.startGreaterThanEnd", | |
| 355 | .@"Panic.inactiveUnionField", | |
| 345 | .panic => .type, | |
| 346 | ||
| 347 | .@"panic.call", | |
| 348 | .@"panic.sentinelMismatch", | |
| 349 | .@"panic.unwrapError", | |
| 350 | .@"panic.outOfBounds", | |
| 351 | .@"panic.startGreaterThanEnd", | |
| 352 | .@"panic.inactiveUnionField", | |
| 353 | .@"panic.reachedUnreachable", | |
| 354 | .@"panic.unwrapNull", | |
| 355 | .@"panic.castToNull", | |
| 356 | .@"panic.incorrectAlignment", | |
| 357 | .@"panic.invalidErrorCode", | |
| 358 | .@"panic.castTruncatedData", | |
| 359 | .@"panic.negativeToUnsigned", | |
| 360 | .@"panic.integerOverflow", | |
| 361 | .@"panic.shlOverflow", | |
| 362 | .@"panic.shrOverflow", | |
| 363 | .@"panic.divideByZero", | |
| 364 | .@"panic.exactDivisionRemainder", | |
| 365 | .@"panic.integerPartOutOfBounds", | |
| 366 | .@"panic.corruptSwitch", | |
| 367 | .@"panic.shiftRhsTooBig", | |
| 368 | .@"panic.invalidEnumValue", | |
| 369 | .@"panic.forLenMismatch", | |
| 370 | .@"panic.memcpyLenMismatch", | |
| 371 | .@"panic.memcpyAlias", | |
| 372 | .@"panic.noreturnReturned", | |
| 356 | 373 | => .func, |
| 357 | ||
| 358 | .@"Panic.messages" => .type, | |
| 359 | ||
| 360 | .@"Panic.messages.reached_unreachable", | |
| 361 | .@"Panic.messages.unwrap_null", | |
| 362 | .@"Panic.messages.cast_to_null", | |
| 363 | .@"Panic.messages.incorrect_alignment", | |
| 364 | .@"Panic.messages.invalid_error_code", | |
| 365 | .@"Panic.messages.cast_truncated_data", | |
| 366 | .@"Panic.messages.negative_to_unsigned", | |
| 367 | .@"Panic.messages.integer_overflow", | |
| 368 | .@"Panic.messages.shl_overflow", | |
| 369 | .@"Panic.messages.shr_overflow", | |
| 370 | .@"Panic.messages.divide_by_zero", | |
| 371 | .@"Panic.messages.exact_division_remainder", | |
| 372 | .@"Panic.messages.integer_part_out_of_bounds", | |
| 373 | .@"Panic.messages.corrupt_switch", | |
| 374 | .@"Panic.messages.shift_rhs_too_big", | |
| 375 | .@"Panic.messages.invalid_enum_value", | |
| 376 | .@"Panic.messages.for_len_mismatch", | |
| 377 | .@"Panic.messages.memcpy_len_mismatch", | |
| 378 | .@"Panic.messages.memcpy_alias", | |
| 379 | .@"Panic.messages.noreturn_returned", | |
| 380 | => .string, | |
| 381 | 374 | }; |
| 382 | 375 | } |
| 383 | 376 | |
| ... | ... | @@ -423,7 +416,7 @@ pub const BuiltinDecl = enum { |
| 423 | 416 | const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index); |
| 424 | 417 | }; |
| 425 | 418 | |
| 426 | pub const PanicId = enum { | |
| 419 | pub const SimplePanicId = enum { | |
| 427 | 420 | reached_unreachable, |
| 428 | 421 | unwrap_null, |
| 429 | 422 | cast_to_null, |
| ... | ... | @@ -445,19 +438,31 @@ pub const PanicId = enum { |
| 445 | 438 | memcpy_alias, |
| 446 | 439 | noreturn_returned, |
| 447 | 440 | |
| 448 | pub fn toBuiltin(id: PanicId) BuiltinDecl { | |
| 449 | const first_msg: PanicId = @enumFromInt(0); | |
| 450 | const first_decl = @field(BuiltinDecl, "Panic.messages." ++ @tagName(first_msg)); | |
| 451 | comptime { | |
| 452 | // Ensure that the messages are ordered the same in `BuiltinDecl` as they are here. | |
| 453 | for (@typeInfo(PanicId).@"enum".fields) |panic_field| { | |
| 454 | const expect_name = "Panic.messages." ++ panic_field.name; | |
| 455 | const expect_idx = @intFromEnum(first_decl) + panic_field.value; | |
| 456 | const actual_idx = @intFromEnum(@field(BuiltinDecl, expect_name)); | |
| 457 | assert(expect_idx == actual_idx); | |
| 458 | } | |
| 459 | } | |
| 460 | return @enumFromInt(@intFromEnum(first_decl) + @intFromEnum(id)); | |
| 441 | pub fn toBuiltin(id: SimplePanicId) BuiltinDecl { | |
| 442 | return switch (id) { | |
| 443 | // zig fmt: off | |
| 444 | .reached_unreachable => .@"panic.reachedUnreachable", | |
| 445 | .unwrap_null => .@"panic.unwrapNull", | |
| 446 | .cast_to_null => .@"panic.castToNull", | |
| 447 | .incorrect_alignment => .@"panic.incorrectAlignment", | |
| 448 | .invalid_error_code => .@"panic.invalidErrorCode", | |
| 449 | .cast_truncated_data => .@"panic.castTruncatedData", | |
| 450 | .negative_to_unsigned => .@"panic.negativeToUnsigned", | |
| 451 | .integer_overflow => .@"panic.integerOverflow", | |
| 452 | .shl_overflow => .@"panic.shlOverflow", | |
| 453 | .shr_overflow => .@"panic.shrOverflow", | |
| 454 | .divide_by_zero => .@"panic.divideByZero", | |
| 455 | .exact_division_remainder => .@"panic.exactDivisionRemainder", | |
| 456 | .integer_part_out_of_bounds => .@"panic.integerPartOutOfBounds", | |
| 457 | .corrupt_switch => .@"panic.corruptSwitch", | |
| 458 | .shift_rhs_too_big => .@"panic.shiftRhsTooBig", | |
| 459 | .invalid_enum_value => .@"panic.invalidEnumValue", | |
| 460 | .for_len_mismatch => .@"panic.forLenMismatch", | |
| 461 | .memcpy_len_mismatch => .@"panic.memcpyLenMismatch", | |
| 462 | .memcpy_alias => .@"panic.memcpyAlias", | |
| 463 | .noreturn_returned => .@"panic.noreturnReturned", | |
| 464 | // zig fmt: on | |
| 465 | }; | |
| 461 | 466 | } |
| 462 | 467 | }; |
| 463 | 468 |
src/Zcu/PerThread.zig+1-1| ... | ... | @@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 605 | 605 | // We use an arbitrary element to check if the state has been resolved yet. |
| 606 | 606 | const to_check: Zcu.BuiltinDecl = switch (stage) { |
| 607 | 607 | .main => .Type, |
| 608 | .panic => .Panic, | |
| 608 | .panic => .panic, | |
| 609 | 609 | .va_list => .VaList, |
| 610 | 610 | }; |
| 611 | 611 | if (zcu.builtin_decl_values.get(to_check) != .none) return; |
src/codegen/llvm.zig+5-44| ... | ... | @@ -5019,18 +5019,6 @@ pub const FuncGen = struct { |
| 5019 | 5019 | ); |
| 5020 | 5020 | } |
| 5021 | 5021 | |
| 5022 | fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant { | |
| 5023 | const o = self.ng.object; | |
| 5024 | const pt = o.pt; | |
| 5025 | if (o.null_opt_usize == .no_init) { | |
| 5026 | o.null_opt_usize = try self.resolveValue(Value.fromInterned(try pt.intern(.{ .opt = .{ | |
| 5027 | .ty = try pt.intern(.{ .opt_type = .usize_type }), | |
| 5028 | .val = .none, | |
| 5029 | } }))); | |
| 5030 | } | |
| 5031 | return o.null_opt_usize; | |
| 5032 | } | |
| 5033 | ||
| 5034 | 5022 | fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void { |
| 5035 | 5023 | const o = self.ng.object; |
| 5036 | 5024 | const zcu = o.pt.zcu; |
| ... | ... | @@ -5732,30 +5720,14 @@ pub const FuncGen = struct { |
| 5732 | 5720 | } |
| 5733 | 5721 | } |
| 5734 | 5722 | |
| 5735 | fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void { | |
| 5723 | fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void { | |
| 5736 | 5724 | const o = fg.ng.object; |
| 5737 | 5725 | const zcu = o.pt.zcu; |
| 5738 | const ip = &zcu.intern_pool; | |
| 5739 | const msg_len: u64, const msg_ptr: Builder.Constant = msg: { | |
| 5740 | const str_val = zcu.builtin_decl_values.get(panic_id.toBuiltin()); | |
| 5741 | assert(str_val != .none); | |
| 5742 | const slice = ip.indexToKey(str_val).slice; | |
| 5743 | break :msg .{ Value.fromInterned(slice.len).toUnsignedInt(zcu), try o.lowerValue(slice.ptr) }; | |
| 5744 | }; | |
| 5745 | const null_opt_addr_global = try fg.resolveNullOptUsize(); | |
| 5746 | 5726 | const target = zcu.getTarget(); |
| 5747 | const llvm_usize = try o.lowerType(Type.usize); | |
| 5748 | // example: | |
| 5749 | // call fastcc void @test2.panic( | |
| 5750 | // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr | |
| 5751 | // i64 16, ; msg.len | |
| 5752 | // ptr null, ; stack trace | |
| 5753 | // ptr @2, ; addr (null ?usize) | |
| 5754 | // ) | |
| 5755 | const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(.@"Panic.call")); | |
| 5756 | const panic_nav = ip.getNav(panic_func.owner_nav); | |
| 5757 | const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?; | |
| 5727 | const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin())); | |
| 5728 | const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?; | |
| 5758 | 5729 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav); |
| 5730 | ||
| 5759 | 5731 | const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto; |
| 5760 | 5732 | if (has_err_trace) assert(fg.err_ret_trace != .none); |
| 5761 | 5733 | _ = try fg.wip.callIntrinsicAssumeCold(); |
| ... | ... | @@ -5765,18 +5737,7 @@ pub const FuncGen = struct { |
| 5765 | 5737 | .none, |
| 5766 | 5738 | panic_global.typeOf(&o.builder), |
| 5767 | 5739 | panic_global.toValue(&o.builder), |
| 5768 | if (has_err_trace) &.{ | |
| 5769 | fg.err_ret_trace, | |
| 5770 | msg_ptr.toValue(), | |
| 5771 | try o.builder.intValue(llvm_usize, msg_len), | |
| 5772 | try o.builder.nullValue(.ptr), | |
| 5773 | null_opt_addr_global.toValue(), | |
| 5774 | } else &.{ | |
| 5775 | msg_ptr.toValue(), | |
| 5776 | try o.builder.intValue(llvm_usize, msg_len), | |
| 5777 | try o.builder.nullValue(.ptr), | |
| 5778 | null_opt_addr_global.toValue(), | |
| 5779 | }, | |
| 5740 | if (has_err_trace) &.{fg.err_ret_trace} else &.{}, | |
| 5780 | 5741 | "", |
| 5781 | 5742 | ); |
| 5782 | 5743 | _ = try fg.wip.@"unreachable"(); |
src/crash_report.zig+7-13| ... | ... | @@ -18,18 +18,12 @@ const dev = @import("dev.zig"); |
| 18 | 18 | /// To use these crash report diagnostics, publish this panic in your main file |
| 19 | 19 | /// and add `pub const enable_segfault_handler = false;` to your `std_options`. |
| 20 | 20 | /// You will also need to call initialize() on startup, preferably as the very first operation in your program. |
| 21 | pub const Panic = if (build_options.enable_debug_extensions) struct { | |
| 22 | pub const call = compilerPanic; | |
| 23 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 24 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 25 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 26 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 27 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 28 | pub const messages = std.debug.FormattedPanic.messages; | |
| 29 | } else if (dev.env == .bootstrap) | |
| 30 | std.debug.SimplePanic | |
| 21 | pub const panic = if (build_options.enable_debug_extensions) | |
| 22 | std.debug.FullPanic(compilerPanic) | |
| 23 | else if (dev.env == .bootstrap) | |
| 24 | std.debug.simple_panic | |
| 31 | 25 | else |
| 32 | std.debug.FormattedPanic; | |
| 26 | std.debug.FullPanic(std.debug.defaultPanic); | |
| 33 | 27 | |
| 34 | 28 | /// Install signal handlers to identify crashes and report diagnostics. |
| 35 | 29 | pub fn initialize() void { |
| ... | ... | @@ -164,12 +158,12 @@ fn writeFilePath(file: *Zcu.File, writer: anytype) !void { |
| 164 | 158 | try writer.writeAll(file.sub_file_path); |
| 165 | 159 | } |
| 166 | 160 | |
| 167 | pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, maybe_ret_addr: ?usize) noreturn { | |
| 161 | pub fn compilerPanic(msg: []const u8, maybe_ret_addr: ?usize) noreturn { | |
| 168 | 162 | @branchHint(.cold); |
| 169 | 163 | PanicSwitch.preDispatch(); |
| 170 | 164 | const ret_addr = maybe_ret_addr orelse @returnAddress(); |
| 171 | 165 | const stack_ctx: StackContext = .{ .current = .{ .ret_addr = ret_addr } }; |
| 172 | PanicSwitch.dispatch(error_return_trace, stack_ctx, msg); | |
| 166 | PanicSwitch.dispatch(@errorReturnTrace(), stack_ctx, msg); | |
| 173 | 167 | } |
| 174 | 168 | |
| 175 | 169 | /// Attaches a global SIGSEGV handler |
src/main.zig+1-1| ... | ... | @@ -56,7 +56,7 @@ pub const std_options: std.Options = .{ |
| 56 | 56 | }, |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | pub const Panic = crash_report.Panic; | |
| 59 | pub const panic = crash_report.panic; | |
| 60 | 60 | |
| 61 | 61 | var wasi_preopens: fs.wasi.Preopens = undefined; |
| 62 | 62 | pub fn wasi_cwd() std.os.wasi.fd_t { |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ |
test/cases/compile_errors/bad_panic_call_signature.zig created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | const simple_panic = std.debug.simple_panic; | |
| 2 | pub const panic = struct { | |
| 3 | pub fn call(msg: []const u8, bad: usize) noreturn { | |
| 4 | _ = msg; | |
| 5 | _ = bad; | |
| 6 | @trap(); | |
| 7 | } | |
| 8 | pub const sentinelMismatch = simple_panic.sentinelMismatch; | |
| 9 | pub const unwrapError = simple_panic.unwrapError; | |
| 10 | pub const outOfBounds = simple_panic.outOfBounds; | |
| 11 | pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd; | |
| 12 | pub const inactiveUnionField = simple_panic.inactiveUnionField; | |
| 13 | pub const reachedUnreachable = simple_panic.reachedUnreachable; | |
| 14 | pub const unwrapNull = simple_panic.unwrapNull; | |
| 15 | pub const castToNull = simple_panic.castToNull; | |
| 16 | pub const incorrectAlignment = simple_panic.incorrectAlignment; | |
| 17 | pub const invalidErrorCode = simple_panic.invalidErrorCode; | |
| 18 | pub const castTruncatedData = simple_panic.castTruncatedData; | |
| 19 | pub const negativeToUnsigned = simple_panic.negativeToUnsigned; | |
| 20 | pub const integerOverflow = simple_panic.integerOverflow; | |
| 21 | pub const shlOverflow = simple_panic.shlOverflow; | |
| 22 | pub const shrOverflow = simple_panic.shrOverflow; | |
| 23 | pub const divideByZero = simple_panic.divideByZero; | |
| 24 | pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder; | |
| 25 | pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds; | |
| 26 | pub const corruptSwitch = simple_panic.corruptSwitch; | |
| 27 | pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig; | |
| 28 | pub const invalidEnumValue = simple_panic.invalidEnumValue; | |
| 29 | pub const forLenMismatch = simple_panic.forLenMismatch; | |
| 30 | pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch; | |
| 31 | pub const memcpyAlias = simple_panic.memcpyAlias; | |
| 32 | pub const noreturnReturned = simple_panic.noreturnReturned; | |
| 33 | }; | |
| 34 | ||
| 35 | export fn foo(a: u8) void { | |
| 36 | @setRuntimeSafety(true); | |
| 37 | _ = a + 1; // safety check to reference the panic handler | |
| 38 | } | |
| 39 | ||
| 40 | const std = @import("std"); | |
| 41 | ||
| 42 | // error | |
| 43 | // | |
| 44 | // :3:9: error: expected type 'fn ([]const u8, ?usize) noreturn', found 'fn ([]const u8, usize) noreturn' | |
| 45 | // :3:9: note: parameter 1 'usize' cannot cast into '?usize' |
test/cases/compile_errors/bad_panic_generic_signature.zig created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | const simple_panic = std.debug.simple_panic; | |
| 2 | pub const panic = struct { | |
| 3 | pub fn sentinelMismatch() void {} // invalid | |
| 4 | pub const call = simple_panic.call; | |
| 5 | pub const unwrapError = simple_panic.unwrapError; | |
| 6 | pub const outOfBounds = simple_panic.outOfBounds; | |
| 7 | pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd; | |
| 8 | pub const inactiveUnionField = simple_panic.inactiveUnionField; | |
| 9 | pub const reachedUnreachable = simple_panic.reachedUnreachable; | |
| 10 | pub const unwrapNull = simple_panic.unwrapNull; | |
| 11 | pub const castToNull = simple_panic.castToNull; | |
| 12 | pub const incorrectAlignment = simple_panic.incorrectAlignment; | |
| 13 | pub const invalidErrorCode = simple_panic.invalidErrorCode; | |
| 14 | pub const castTruncatedData = simple_panic.castTruncatedData; | |
| 15 | pub const negativeToUnsigned = simple_panic.negativeToUnsigned; | |
| 16 | pub const integerOverflow = simple_panic.integerOverflow; | |
| 17 | pub const shlOverflow = simple_panic.shlOverflow; | |
| 18 | pub const shrOverflow = simple_panic.shrOverflow; | |
| 19 | pub const divideByZero = simple_panic.divideByZero; | |
| 20 | pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder; | |
| 21 | pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds; | |
| 22 | pub const corruptSwitch = simple_panic.corruptSwitch; | |
| 23 | pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig; | |
| 24 | pub const invalidEnumValue = simple_panic.invalidEnumValue; | |
| 25 | pub const forLenMismatch = simple_panic.forLenMismatch; | |
| 26 | pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch; | |
| 27 | pub const memcpyAlias = simple_panic.memcpyAlias; | |
| 28 | pub const noreturnReturned = simple_panic.noreturnReturned; | |
| 29 | }; | |
| 30 | ||
| 31 | export fn foo(arr: *const [2]u8) void { | |
| 32 | @setRuntimeSafety(true); | |
| 33 | _ = arr[0..1 :0]; | |
| 34 | } | |
| 35 | ||
| 36 | const std = @import("std"); | |
| 37 | ||
| 38 | // error | |
| 39 | // | |
| 40 | // :3:9: error: expected type 'fn (anytype, anytype) noreturn', found 'fn () void' | |
| 41 | // :3:9: note: non-generic function cannot cast into a generic function |
test/cases/compile_errors/bad_panic_signature.zig deleted-28| ... | ... | @@ -1,28 +0,0 @@ |
| 1 | pub const Panic = struct { | |
| 2 | pub const call = badPanicSignature; | |
| 3 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 4 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 5 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 6 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 7 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 8 | pub const messages = std.debug.FormattedPanic.messages; | |
| 9 | }; | |
| 10 | ||
| 11 | fn badPanicSignature(msg: []const u8, bad1: usize, bad2: void) noreturn { | |
| 12 | _ = msg; | |
| 13 | _ = bad1; | |
| 14 | _ = bad2; | |
| 15 | @trap(); | |
| 16 | } | |
| 17 | ||
| 18 | export fn foo(a: u8) void { | |
| 19 | @setRuntimeSafety(true); | |
| 20 | _ = a + 1; // safety check to reference the panic handler | |
| 21 | } | |
| 22 | ||
| 23 | const std = @import("std"); | |
| 24 | ||
| 25 | // error | |
| 26 | // | |
| 27 | // :2:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn' | |
| 28 | // :2:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace' |
test/incremental/change_panic_handler+6-30| ... | ... | @@ -9,16 +9,8 @@ pub fn main() !u8 { |
| 9 | 9 | _ = a + 1; |
| 10 | 10 | return 1; |
| 11 | 11 | } |
| 12 | pub const Panic = struct { | |
| 13 | pub const call = myPanic; | |
| 14 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 15 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 16 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 17 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 18 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 19 | pub const messages = std.debug.FormattedPanic.messages; | |
| 20 | }; | |
| 21 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 12 | pub const panic = std.debug.FullPanic(myPanic); | |
| 13 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | |
| 22 | 14 | std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; |
| 23 | 15 | std.process.exit(0); |
| 24 | 16 | } |
| ... | ... | @@ -33,16 +25,8 @@ pub fn main() !u8 { |
| 33 | 25 | _ = a + 1; |
| 34 | 26 | return 1; |
| 35 | 27 | } |
| 36 | pub const Panic = struct { | |
| 37 | pub const call = myPanic; | |
| 38 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 39 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 40 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 41 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 42 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 43 | pub const messages = std.debug.FormattedPanic.messages; | |
| 44 | }; | |
| 45 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 28 | pub const panic = std.debug.FullPanic(myPanic); | |
| 29 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | |
| 46 | 30 | std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; |
| 47 | 31 | std.process.exit(0); |
| 48 | 32 | } |
| ... | ... | @@ -57,16 +41,8 @@ pub fn main() !u8 { |
| 57 | 41 | _ = a + 1; |
| 58 | 42 | return 1; |
| 59 | 43 | } |
| 60 | pub const Panic = struct { | |
| 61 | pub const call = myPanicNew; | |
| 62 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | |
| 63 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | |
| 64 | pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; | |
| 65 | pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; | |
| 66 | pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; | |
| 67 | pub const messages = std.debug.FormattedPanic.messages; | |
| 68 | }; | |
| 69 | fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | |
| 44 | pub const panic = std.debug.FullPanic(myPanicNew); | |
| 45 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | |
| 70 | 46 | std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; |
| 71 | 47 | std.process.exit(0); |
| 72 | 48 | } |
test/incremental/change_panic_handler_explicit created+141| ... | ... | @@ -0,0 +1,141 @@ |
| 1 | #target=x86_64-linux-selfhosted | |
| 2 | #target=x86_64-linux-cbe | |
| 3 | #target=x86_64-windows-cbe | |
| 4 | #update=initial version | |
| 5 | #file=main.zig | |
| 6 | pub fn main() !u8 { | |
| 7 | var a: u8 = undefined; | |
| 8 | a = 255; | |
| 9 | _ = a + 1; | |
| 10 | return 1; | |
| 11 | } | |
| 12 | const no_panic = std.debug.no_panic; | |
| 13 | pub const panic = struct { | |
| 14 | pub const call = myPanic; | |
| 15 | pub fn integerOverflow() noreturn { | |
| 16 | @panic("integer overflow"); | |
| 17 | } | |
| 18 | pub const sentinelMismatch = no_panic.sentinelMismatch; | |
| 19 | pub const unwrapError = no_panic.unwrapError; | |
| 20 | pub const outOfBounds = no_panic.outOfBounds; | |
| 21 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | |
| 22 | pub const inactiveUnionField = no_panic.inactiveUnionField; | |
| 23 | pub const reachedUnreachable = no_panic.reachedUnreachable; | |
| 24 | pub const unwrapNull = no_panic.unwrapNull; | |
| 25 | pub const castToNull = no_panic.castToNull; | |
| 26 | pub const incorrectAlignment = no_panic.incorrectAlignment; | |
| 27 | pub const invalidErrorCode = no_panic.invalidErrorCode; | |
| 28 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 29 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 30 | pub const shlOverflow = no_panic.shlOverflow; | |
| 31 | pub const shrOverflow = no_panic.shrOverflow; | |
| 32 | pub const divideByZero = no_panic.divideByZero; | |
| 33 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | |
| 34 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | |
| 35 | pub const corruptSwitch = no_panic.corruptSwitch; | |
| 36 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | |
| 37 | pub const invalidEnumValue = no_panic.invalidEnumValue; | |
| 38 | pub const forLenMismatch = no_panic.forLenMismatch; | |
| 39 | pub const memcpyLenMismatch = no_panic.memcpyLenMismatch; | |
| 40 | pub const memcpyAlias = no_panic.memcpyAlias; | |
| 41 | pub const noreturnReturned = no_panic.noreturnReturned; | |
| 42 | }; | |
| 43 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | |
| 44 | std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; | |
| 45 | std.process.exit(0); | |
| 46 | } | |
| 47 | const std = @import("std"); | |
| 48 | #expect_stdout="panic message: integer overflow\n" | |
| 49 | ||
| 50 | #update=change the panic handler body | |
| 51 | #file=main.zig | |
| 52 | pub fn main() !u8 { | |
| 53 | var a: u8 = undefined; | |
| 54 | a = 255; | |
| 55 | _ = a + 1; | |
| 56 | return 1; | |
| 57 | } | |
| 58 | const no_panic = std.debug.no_panic; | |
| 59 | pub const panic = struct { | |
| 60 | pub const call = myPanic; | |
| 61 | pub fn integerOverflow() noreturn { | |
| 62 | @panic("integer overflow"); | |
| 63 | } | |
| 64 | pub const sentinelMismatch = no_panic.sentinelMismatch; | |
| 65 | pub const unwrapError = no_panic.unwrapError; | |
| 66 | pub const outOfBounds = no_panic.outOfBounds; | |
| 67 | pub const startGreaterThanEnd = no_panic.startGreaterThanEnd; | |
| 68 | pub const inactiveUnionField = no_panic.inactiveUnionField; | |
| 69 | pub const reachedUnreachable = no_panic.reachedUnreachable; | |
| 70 | pub const unwrapNull = no_panic.unwrapNull; | |
| 71 | pub const castToNull = no_panic.castToNull; | |
| 72 | pub const incorrectAlignment = no_panic.incorrectAlignment; | |
| 73 | pub const invalidErrorCode = no_panic.invalidErrorCode; | |
| 74 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 75 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 76 | pub const shlOverflow = no_panic.shlOverflow; | |
| 77 | pub const shrOverflow = no_panic.shrOverflow; | |
| 78 | pub const divideByZero = no_panic.divideByZero; | |
| 79 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | |
| 80 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | |
| 81 | pub const corruptSwitch = no_panic.corruptSwitch; | |
| 82 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | |
| 83 | pub const invalidEnumValue = no_panic.invalidEnumValue; | |
| 84 | pub const forLenMismatch = no_panic.forLenMismatch; | |
| 85 | pub const memcpyLenMismatch = no_panic.memcpyLenMismatch; | |
| 86 | pub const memcpyAlias = no_panic.memcpyAlias; | |
| 87 | pub const noreturnReturned = no_panic.noreturnReturned; | |
| 88 | }; | |
| 89 | fn myPanic(msg: []const u8, _: ?usize) noreturn { | |
| 90 | std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; | |
| 91 | std.process.exit(0); | |
| 92 | } | |
| 93 | const std = @import("std"); | |
| 94 | #expect_stdout="new panic message: integer overflow\n" | |
| 95 | ||
| 96 | #update=change the panic handler function value | |
| 97 | #file=main.zig | |
| 98 | pub fn main() !u8 { | |
| 99 | var a: u8 = undefined; | |
| 100 | a = 255; | |
| 101 | _ = a + 1; | |
| 102 | return 1; | |
| 103 | } | |
| 104 | const no_panic = std.debug.no_panic; | |
| 105 | pub const panic = struct { | |
| 106 | pub const call = myPanicNew; | |
| 107 | pub fn integerOverflow() noreturn { | |
| 108 | @panic("integer overflow"); | |
| 109 | } | |
| 110 | pub const sentinelMismatch = std.debug.no_panic.sentinelMismatch; | |
| 111 | pub const unwrapError = std.debug.no_panic.unwrapError; | |
| 112 | pub const outOfBounds = std.debug.no_panic.outOfBounds; | |
| 113 | pub const startGreaterThanEnd = std.debug.no_panic.startGreaterThanEnd; | |
| 114 | pub const inactiveUnionField = std.debug.no_panic.inactiveUnionField; | |
| 115 | pub const messages = std.debug.no_panic.messages; | |
| 116 | pub const reachedUnreachable = no_panic.reachedUnreachable; | |
| 117 | pub const unwrapNull = no_panic.unwrapNull; | |
| 118 | pub const castToNull = no_panic.castToNull; | |
| 119 | pub const incorrectAlignment = no_panic.incorrectAlignment; | |
| 120 | pub const invalidErrorCode = no_panic.invalidErrorCode; | |
| 121 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 122 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 123 | pub const shlOverflow = no_panic.shlOverflow; | |
| 124 | pub const shrOverflow = no_panic.shrOverflow; | |
| 125 | pub const divideByZero = no_panic.divideByZero; | |
| 126 | pub const exactDivisionRemainder = no_panic.exactDivisionRemainder; | |
| 127 | pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds; | |
| 128 | pub const corruptSwitch = no_panic.corruptSwitch; | |
| 129 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; | |
| 130 | pub const invalidEnumValue = no_panic.invalidEnumValue; | |
| 131 | pub const forLenMismatch = no_panic.forLenMismatch; | |
| 132 | pub const memcpyLenMismatch = no_panic.memcpyLenMismatch; | |
| 133 | pub const memcpyAlias = no_panic.memcpyAlias; | |
| 134 | pub const noreturnReturned = no_panic.noreturnReturned; | |
| 135 | }; | |
| 136 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { | |
| 137 | std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; | |
| 138 | std.process.exit(0); | |
| 139 | } | |
| 140 | const std = @import("std"); | |
| 141 | #expect_stdout="third panic message: integer overflow\n" |
test/src/Cases.zig-1| ... | ... | @@ -358,7 +358,6 @@ pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void { |
| 358 | 358 | var current_file: []const u8 = "none"; |
| 359 | 359 | ctx.addFromDirInner(dir, &current_file, b) catch |err| { |
| 360 | 360 | std.debug.panicExtra( |
| 361 | @errorReturnTrace(), | |
| 362 | 361 | @returnAddress(), |
| 363 | 362 | "test harness failed to process file '{s}': {s}\n", |
| 364 | 363 | .{ current_file, @errorName(err) }, |