aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-09-25 16:20:19 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-09-26 12:35:14 -0700
commitf2c8940aa6b1bd6ca20730e13b8148af002e1b91 (patch)
tree295c72daba87d055c3f6dd0a8ca8e33a54847741 /lib
parent76f0b6e7d8dfa527f8776a4ffe61400fd84d871a (diff)
downloadzig-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.zig73
-rw-r--r--lib/std/debug.zig19
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;