diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-09-25 16:20:19 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-09-26 12:35:14 -0700 |
| commit | f2c8940aa6b1bd6ca20730e13b8148af002e1b91 (patch) | |
| tree | 295c72daba87d055c3f6dd0a8ca8e33a54847741 /lib | |
| parent | 76f0b6e7d8dfa527f8776a4ffe61400fd84d871a (diff) | |
| download | zig-f2c8940aa6b1bd6ca20730e13b8148af002e1b91.tar.gz zig-f2c8940aa6b1bd6ca20730e13b8148af002e1b91.zip | |
reintroduce the std.builtin safety panic helpers
motivated by performance
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/builtin.zig | 73 | ||||
| -rw-r--r-- | lib/std/debug.zig | 19 |
2 files changed, 84 insertions, 8 deletions
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 8530a64fed..4edcebad53 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -803,6 +803,7 @@ pub const PanicCause = union(enum) { memcpy_alias, noreturn_returned, explicit_call: []const u8, + sentinel_mismatch_isize: SentinelMismatchIsize, pub const IndexOutOfBounds = struct { index: usize, @@ -819,22 +820,82 @@ pub const PanicCause = union(enum) { found: usize, }; + pub const SentinelMismatchIsize = struct { + expected: isize, + found: isize, + }; + pub const InactiveUnionField = struct { active: []const u8, accessed: []const u8, }; }; -pub noinline fn returnError(st: *StackTrace) void { +pub fn panicSentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { @branchHint(.cold); - @setRuntimeSafety(false); - addErrRetTraceAddr(st, @returnAddress()); + switch (@typeInfo(@TypeOf(expected))) { + .int => |int| switch (int.signedness) { + .unsigned => if (int.bits <= @bitSizeOf(usize)) panic(.{ .sentinel_mismatch_usize = .{ + .expected = expected, + .found = found, + } }, null, @returnAddress()), + .signed => if (int.bits <= @bitSizeOf(isize)) panic(.{ .sentinel_mismatch_isize = .{ + .expected = expected, + .found = found, + } }, null, @returnAddress()), + }, + .@"enum" => |info| switch (@typeInfo(info.tag_type)) { + .int => |int| switch (int.signedness) { + .unsigned => if (int.bits <= @bitSizeOf(usize)) panic(.{ .sentinel_mismatch_usize = .{ + .expected = @intFromEnum(expected), + .found = @intFromEnum(found), + } }, null, @returnAddress()), + .signed => if (int.bits <= @bitSizeOf(isize)) panic(.{ .sentinel_mismatch_isize = .{ + .expected = @intFromEnum(expected), + .found = @intFromEnum(found), + } }, null, @returnAddress()), + }, + else => comptime unreachable, + }, + else => {}, + } + panic(.sentinel_mismatch_other, null, @returnAddress()); } -pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void { - if (st.index < st.instruction_addresses.len) - st.instruction_addresses[st.index] = addr; +pub fn panicUnwrapError(ert: ?*StackTrace, err: anyerror) noreturn { + @branchHint(.cold); + panic(.{ .unwrap_error = err }, ert, @returnAddress()); +} + +pub fn panicOutOfBounds(index: usize, len: usize) noreturn { + @branchHint(.cold); + panic(.{ .index_out_of_bounds = .{ + .index = index, + .len = len, + } }, null, @returnAddress()); +} + +pub fn panicStartGreaterThanEnd(start: usize, end: usize) noreturn { + @branchHint(.cold); + panic(.{ .start_index_greater_than_end = .{ + .start = start, + .end = end, + } }, null, @returnAddress()); +} +pub fn panicInactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { + @branchHint(.cold); + panic(.{ .inactive_union_field = .{ + .active = @tagName(active), + .accessed = @tagName(accessed), + } }, null, @returnAddress()); +} + +pub noinline fn returnError(st: *StackTrace) void { + @branchHint(.unlikely); + @setRuntimeSafety(false); + if (st.index < st.instruction_addresses.len) + st.instruction_addresses[st.index] = @returnAddress(); st.index += 1; } diff --git a/lib/std/debug.zig b/lib/std/debug.zig index d6312598d1..7bfc6b321e 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -453,7 +453,7 @@ threadlocal var panic_stage: usize = 0; // This function avoids a dependency on formatted printing. pub fn defaultPanic( cause: std.builtin.PanicCause, - trace: ?*const std.builtin.StackTrace, + error_return_trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize, ) noreturn { @branchHint(.cold); @@ -568,7 +568,7 @@ pub fn defaultPanic( defer unlockStdErr(); io.getStdErr().writeAll(msg) catch posix.abort(); - if (trace) |t| dumpStackTrace(t.*); + if (error_return_trace) |t| dumpStackTrace(t.*); dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); } @@ -621,6 +621,12 @@ pub fn fmtPanicCause(buffer: []u8, cause: std.builtin.PanicCause) usize { i += fmtBuf(buffer[i..], ", found "); i += fmtInt10(buffer[i..], mm.found); }, + .sentinel_mismatch_isize => |mm| { + i += fmtBuf(buffer[i..], "sentinel mismatch: expected "); + i += fmtInt10s(buffer[i..], mm.expected); + i += fmtBuf(buffer[i..], ", found "); + i += fmtInt10s(buffer[i..], mm.found); + }, .sentinel_mismatch_other => i += fmtBuf(buffer[i..], "sentinel mismatch"), .unwrap_error => |err| { i += fmtBuf(buffer[i..], "attempt to unwrap error: "); @@ -653,6 +659,15 @@ fn fmtBuf(out_buf: []u8, s: []const u8) usize { return s.len; } +fn fmtInt10s(out_buf: []u8, integer_value: isize) usize { + if (integer_value < 0) { + out_buf[0] = '-'; + return 1 + fmtInt10(out_buf[1..], @abs(integer_value)); + } else { + return fmtInt10(out_buf, @abs(integer_value)); + } +} + fn fmtInt10(out_buf: []u8, integer_value: usize) usize { var tmp_buf: [50]u8 = undefined; var i: usize = tmp_buf.len; |
