From 83991efe10d92c4b920d7b7fc75be98ed7854ad7 Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 24 Jan 2025 02:19:28 +0000 Subject: compiler: yet more panic handler changes * `std.builtin.Panic` -> `std.builtin.panic`, because it is a namespace. * `root.Panic` -> `root.panic` for the same reason. There are type checks so that we still allow the legacy `pub fn panic` strategy in the 0.14.0 release. * `std.debug.SimplePanic` -> `std.debug.simple_panic`, same reason. * `std.debug.NoPanic` -> `std.debug.no_panic`, same reason. * `std.debug.FormattedPanic` is now a function `std.debug.FullPanic` which takes as input a `panicFn` and returns a namespace with all the panic functions. This handles the incredibly common case of just wanting to override how the message is printed, whilst keeping nice formatted panics. * Remove `std.builtin.panic.messages`; now, every safety panic has its own function. This reduces binary bloat, as calls to these functions no longer need to prepare any arguments (aside from the error return trace). * Remove some legacy declarations, since a zig1.wasm update has happened. Most of these were related to the panic handler, but a quick grep for "zig1" brought up a couple more results too. Also, add some missing type checks to Sema. Resolves: #22584 formatted -> full --- src/Sema.zig | 155 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 66 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 833b05413f..b8fe4636f8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5918,13 +5918,14 @@ fn zirCompileLog( } fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const msg_inst = try sema.resolveInst(inst_data.operand); - // `panicWithMsg` would perform this coercion for us, but we can get a better - // source location if we do it here. - const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); + const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); if (block.isComptime()) { return sema.fail(block, src, "encountered @panic at comptime", .{}); @@ -5936,7 +5937,23 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void sema.branch_hint = .cold; } - try sema.panicWithMsg(block, src, coerced_msg, .@"@panic"); + if (!zcu.backendSupportsFeature(.panic_fn)) { + _ = try block.addNoOp(.trap); + return; + } + + try sema.ensureMemoizedStateResolved(src, .panic); + try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call")); + + const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call")); + const null_stack_trace = Air.internedToRef(zcu.null_stack_trace); + + const opt_usize_ty = try pt.optionalType(.usize_type); + const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ + .ty = opt_usize_ty.toIntern(), + .val = .none, + } }))); + try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_stack_trace, null_ret_addr }, .@"@panic"); } fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -13787,7 +13804,7 @@ fn maybeErrorUnwrap( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const msg_inst = try sema.resolveInst(inst_data.operand); - const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call"); + const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); const err_return_trace = try sema.getErrorReturnTrace(block); const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value }; try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); @@ -27083,15 +27100,16 @@ fn explainWhyTypeIsNotPacked( /// Backends depend on panic decls being available when lowering safety-checked /// instructions. This function ensures the panic function will be available to /// be called during that time. -fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index { +fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index { const zcu = sema.pt.zcu; try sema.ensureMemoizedStateResolved(src, .panic); - try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call")); + const panic_func = zcu.builtin_decl_values.get(panic_id.toBuiltin()); + try zcu.ensureFuncBodyAnalysisQueued(panic_func); switch (sema.owner.unwrap()) { .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true), } - return zcu.builtin_decl_values.get(panic_id.toBuiltin()); + return panic_func; } fn addSafetyCheck( @@ -27099,7 +27117,7 @@ fn addSafetyCheck( parent_block: *Block, src: LazySrcLoc, ok: Air.Inst.Ref, - panic_id: Zcu.PanicId, + panic_id: Zcu.SimplePanicId, ) !void { const gpa = sema.gpa; assert(!parent_block.isComptime()); @@ -27186,29 +27204,6 @@ fn addSafetyCheckExtra( parent_block.instructions.appendAssumeCapacity(block_inst); } -fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void { - const pt = sema.pt; - const zcu = pt.zcu; - - if (!zcu.backendSupportsFeature(.panic_fn)) { - _ = try block.addNoOp(.trap); - return; - } - - try sema.ensureMemoizedStateResolved(src, .panic); - try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call")); - - const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"Panic.call")); - const null_stack_trace = Air.internedToRef(zcu.null_stack_trace); - - const opt_usize_ty = try pt.optionalType(.usize_type); - const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ - .ty = opt_usize_ty.toIntern(), - .val = .none, - } }))); - try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation); -} - fn addSafetyCheckUnwrapError( sema: *Sema, parent_block: *Block, @@ -27246,7 +27241,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air. if (!zcu.backendSupportsFeature(.panic_fn)) { _ = try block.addNoOp(.trap); } else { - const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError"); + const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError"); const err_return_trace = try sema.getErrorReturnTrace(block); const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); @@ -27263,7 +27258,7 @@ fn addSafetyCheckIndexOob( ) !void { assert(!parent_block.isComptime()); const ok = try parent_block.addBinOp(cmp_op, index, len); - return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len }); + return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.outOfBounds", &.{ index, len }); } fn addSafetyCheckInactiveUnionField( @@ -27275,7 +27270,7 @@ fn addSafetyCheckInactiveUnionField( ) !void { assert(!parent_block.isComptime()); const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); - return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag }); + return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.inactiveUnionField", &.{ active_tag, wanted_tag }); } fn addSafetyCheckSentinelMismatch( @@ -27316,7 +27311,7 @@ fn addSafetyCheckSentinelMismatch( break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); }; - return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{ + return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ expected_sentinel, actual_sentinel, }); } @@ -27358,9 +27353,13 @@ fn addSafetyCheckCall( } /// This does not set `sema.branch_hint`. -fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void { - const msg_val = try sema.preparePanicId(src, panic_id); - try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check"); +fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void { + if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) { + _ = try block.addNoOp(.trap); + } else { + const panic_fn = try sema.preparePanicId(src, panic_id); + try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{}, .@"safety check"); + } } fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { @@ -32818,7 +32817,7 @@ fn analyzeSlice( assert(!block.isComptime()); try sema.requireRuntimeBlock(block, src, runtime_src.?); const ok = try block.addBinOp(.cmp_lte, start, end); - try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end }); + try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end }); } const new_len = if (by_length) try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) @@ -38525,14 +38524,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, break :val uncoerced_val; }, .func => val: { - if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| { - const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); - break :val .fromInterned(coerced.toInterned().?); - } - if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") { - return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name }); - } - break :val uncoerced_val; + const func_ty = try sema.getExpectedBuiltinFnType(src, builtin_decl); + const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); + break :val .fromInterned(coerced.toInterned().?); }, .string => val: { const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); @@ -38567,16 +38561,19 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, return any_changed; } -/// Given that `decl.kind() == .func`, get the type expected of the function if necessary. -/// If this will be type checked by `Sema` anyway, this function may return `null`. In -/// particular, generic functions should return `null`, as `Sema` will necessarily check -/// them at instantiation time. Returning non-null is necessary only when backends can emit -/// calls to the function, as is the case with the panic handler. -fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type { +/// Given that `decl.kind() == .func`, get the type expected of the function. +fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!Type { const pt = sema.pt; return switch (decl) { + // `noinline fn () void` + .returnError => try pt.funcType(.{ + .param_types = &.{}, + .return_type = .void_type, + .is_noinline = true, + }), + // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` - .@"Panic.call" => try pt.funcType(.{ + .@"panic.call" => try pt.funcType(.{ .param_types = &.{ .slice_const_u8_type, (try pt.optionalType( @@ -38589,8 +38586,17 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) .return_type = .noreturn_type, }), + // `fn (anytype, anytype) noreturn` + .@"panic.sentinelMismatch", + .@"panic.inactiveUnionField", + => try pt.funcType(.{ + .param_types = &.{ .generic_poison_type, .generic_poison_type }, + .return_type = .noreturn_type, + .is_generic = true, + }), + // `fn (?*StackTrace, anyerror) noreturn` - .@"Panic.unwrapError" => try pt.funcType(.{ + .@"panic.unwrapError" => try pt.funcType(.{ .param_types = &.{ (try pt.optionalType( (try pt.singleMutPtrType( @@ -38603,21 +38609,38 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) }), // `fn (usize, usize) noreturn` - .@"Panic.outOfBounds", - .@"Panic.startGreaterThanEnd", + .@"panic.outOfBounds", + .@"panic.startGreaterThanEnd", => try pt.funcType(.{ .param_types = &.{ .usize_type, .usize_type }, .return_type = .noreturn_type, }), - // Generic functions, so calls are necessarily validated by Sema - .@"Panic.sentinelMismatch", - .@"Panic.inactiveUnionField", - => null, - - // Other functions called exclusively by Sema - .returnError, - => null, + // `fn () noreturn` + .@"panic.reachedUnreachable", + .@"panic.unwrapNull", + .@"panic.castToNull", + .@"panic.incorrectAlignment", + .@"panic.invalidErrorCode", + .@"panic.castTruncatedData", + .@"panic.negativeToUnsigned", + .@"panic.integerOverflow", + .@"panic.shlOverflow", + .@"panic.shrOverflow", + .@"panic.divideByZero", + .@"panic.exactDivisionRemainder", + .@"panic.integerPartOutOfBounds", + .@"panic.corruptSwitch", + .@"panic.shiftRhsTooBig", + .@"panic.invalidEnumValue", + .@"panic.forLenMismatch", + .@"panic.memcpyLenMismatch", + .@"panic.memcpyAlias", + .@"panic.noreturnReturned", + => try pt.funcType(.{ + .param_types = &.{}, + .return_type = .noreturn_type, + }), else => unreachable, }; -- cgit v1.2.3 From b0a8931690660da753f9684d65db4b1bdfe29757 Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 24 Jan 2025 04:20:09 +0000 Subject: Sema: prepare to remove `?*StackTrace` argument from `unwrapError` and `call` Now that we propagate the error return trace to all `callconv(.auto)` functions, passing it explicitly to panic handlers is redundant. --- src/Sema.zig | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index b8fe4636f8..f2e52c2170 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5946,14 +5946,13 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call")); const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call")); - const null_stack_trace = Air.internedToRef(zcu.null_stack_trace); const opt_usize_ty = try pt.optionalType(.usize_type); const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ .ty = opt_usize_ty.toIntern(), .val = .none, } }))); - try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_stack_trace, null_ret_addr }, .@"@panic"); + try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_ret_addr }, .@"@panic"); } fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -13805,8 +13804,7 @@ fn maybeErrorUnwrap( const msg_inst = try sema.resolveInst(inst_data.operand); const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); - const err_return_trace = try sema.getErrorReturnTrace(block); - const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value }; + const args: [2]Air.Inst.Ref = .{ msg_inst, .null_value }; try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); return true; }, @@ -27242,9 +27240,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air. _ = try block.addNoOp(.trap); } else { const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError"); - const err_return_trace = try sema.getErrorReturnTrace(block); - const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; - try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); + try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{err}, .@"safety check"); } } @@ -38524,7 +38520,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, break :val uncoerced_val; }, .func => val: { - const func_ty = try sema.getExpectedBuiltinFnType(src, builtin_decl); + const func_ty = try sema.getExpectedBuiltinFnType(builtin_decl); const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); break :val .fromInterned(coerced.toInterned().?); }, @@ -38562,7 +38558,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, } /// Given that `decl.kind() == .func`, get the type expected of the function. -fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!Type { +fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Type { const pt = sema.pt; return switch (decl) { // `noinline fn () void` @@ -38572,15 +38568,10 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) .is_noinline = true, }), - // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` + // `fn ([]const u8, ?usize) noreturn` .@"panic.call" => try pt.funcType(.{ .param_types = &.{ .slice_const_u8_type, - (try pt.optionalType( - (try pt.singleMutPtrType( - try sema.getBuiltinType(src, .StackTrace), - )).toIntern(), - )).toIntern(), (try pt.optionalType(.usize_type)).toIntern(), }, .return_type = .noreturn_type, @@ -38595,16 +38586,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) .is_generic = true, }), - // `fn (?*StackTrace, anyerror) noreturn` + // `fn (anyerror) noreturn` .@"panic.unwrapError" => try pt.funcType(.{ - .param_types = &.{ - (try pt.optionalType( - (try pt.singleMutPtrType( - try sema.getBuiltinType(src, .StackTrace), - )).toIntern(), - )).toIntern(), - .anyerror_type, - }, + .param_types = &.{.anyerror_type}, .return_type = .noreturn_type, }), -- cgit v1.2.3 From 5a6666db5502079d9800ae3d41b790646238078e Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 24 Jan 2025 04:20:55 +0000 Subject: all: update for `panic.unwrapError` and `panic.call` signature changes --- lib/std/builtin.zig | 7 ++- lib/std/debug.zig | 64 +++++++++++----------- lib/std/debug/no_panic.zig | 4 +- lib/std/debug/simple_panic.zig | 56 +++++++++---------- src/Sema.zig | 2 +- src/crash_report.zig | 4 +- .../compile_errors/bad_panic_call_signature.zig | 9 ++- test/incremental/change_panic_handler | 6 +- test/incremental/change_panic_handler_explicit | 6 +- test/src/Cases.zig | 1 - 10 files changed, 79 insertions(+), 80 deletions(-) (limited to 'src/Sema.zig') diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index b2e973aea8..f860f7d891 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -1117,7 +1117,12 @@ pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn; pub const panic: type = p: { if (@hasDecl(root, "panic")) { if (@TypeOf(root.panic) != type) { - break :p std.debug.FullPanic(root.panic); // Deprecated; make `panic` a namespace instead. + // Deprecated; make `panic` a namespace instead. + break :p std.debug.FullPanic(struct { + fn panic(msg: []const u8, ra: ?usize) noreturn { + root.panic(msg, @errorReturnTrace(), ra); + } + }.panic); } break :p root.panic; } diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 0ff51a7339..7e68f16ee8 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -27,112 +27,112 @@ pub const no_panic = @import("debug/no_panic.zig"); /// A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`. /// Safety panics will use formatted printing to provide a meaningful error message. /// The signature of `panicFn` should match that of `defaultPanic`. -pub fn FullPanic(comptime panicFn: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn) type { +pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { return struct { pub const call = panicFn; pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ + std.debug.panicExtra(@returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, found, }); } - pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { + pub fn unwrapError(err: anyerror) noreturn { @branchHint(.cold); - std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); + std.debug.panicExtra(@returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); } pub fn outOfBounds(index: usize, len: usize) noreturn { @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); + std.debug.panicExtra(@returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); } pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); + std.debug.panicExtra(@returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); } pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ + std.debug.panicExtra(@returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ @tagName(accessed), @tagName(active), }); } pub fn reachedUnreachable() noreturn { @branchHint(.cold); - call("reached unreachable code", null, @returnAddress()); + call("reached unreachable code", @returnAddress()); } pub fn unwrapNull() noreturn { @branchHint(.cold); - call("attempt to use null value", null, @returnAddress()); + call("attempt to use null value", @returnAddress()); } pub fn castToNull() noreturn { @branchHint(.cold); - call("cast causes pointer to be null", null, @returnAddress()); + call("cast causes pointer to be null", @returnAddress()); } pub fn incorrectAlignment() noreturn { @branchHint(.cold); - call("incorrect alignment", null, @returnAddress()); + call("incorrect alignment", @returnAddress()); } pub fn invalidErrorCode() noreturn { @branchHint(.cold); - call("invalid error code", null, @returnAddress()); + call("invalid error code", @returnAddress()); } pub fn castTruncatedData() noreturn { @branchHint(.cold); - call("integer cast truncated bits", null, @returnAddress()); + call("integer cast truncated bits", @returnAddress()); } pub fn negativeToUnsigned() noreturn { @branchHint(.cold); - call("attempt to cast negative value to unsigned integer", null, @returnAddress()); + call("attempt to cast negative value to unsigned integer", @returnAddress()); } pub fn integerOverflow() noreturn { @branchHint(.cold); - call("integer overflow", null, @returnAddress()); + call("integer overflow", @returnAddress()); } pub fn shlOverflow() noreturn { @branchHint(.cold); - call("left shift overflowed bits", null, @returnAddress()); + call("left shift overflowed bits", @returnAddress()); } pub fn shrOverflow() noreturn { @branchHint(.cold); - call("right shift overflowed bits", null, @returnAddress()); + call("right shift overflowed bits", @returnAddress()); } pub fn divideByZero() noreturn { @branchHint(.cold); - call("division by zero", null, @returnAddress()); + call("division by zero", @returnAddress()); } pub fn exactDivisionRemainder() noreturn { @branchHint(.cold); - call("exact division produced remainder", null, @returnAddress()); + call("exact division produced remainder", @returnAddress()); } pub fn integerPartOutOfBounds() noreturn { @branchHint(.cold); - call("integer part of floating point value out of bounds", null, @returnAddress()); + call("integer part of floating point value out of bounds", @returnAddress()); } pub fn corruptSwitch() noreturn { @branchHint(.cold); - call("switch on corrupt value", null, @returnAddress()); + call("switch on corrupt value", @returnAddress()); } pub fn shiftRhsTooBig() noreturn { @branchHint(.cold); - call("shift amount is greater than the type size", null, @returnAddress()); + call("shift amount is greater than the type size", @returnAddress()); } pub fn invalidEnumValue() noreturn { @branchHint(.cold); - call("invalid enum value", null, @returnAddress()); + call("invalid enum value", @returnAddress()); } pub fn forLenMismatch() noreturn { @branchHint(.cold); - call("for loop over objects with non-equal lengths", null, @returnAddress()); + call("for loop over objects with non-equal lengths", @returnAddress()); } pub fn memcpyLenMismatch() noreturn { @branchHint(.cold); - call("@memcpy arguments have non-equal lengths", null, @returnAddress()); + call("@memcpy arguments have non-equal lengths", @returnAddress()); } pub fn memcpyAlias() noreturn { @branchHint(.cold); - call("@memcpy arguments alias", null, @returnAddress()); + call("@memcpy arguments alias", @returnAddress()); } pub fn noreturnReturned() noreturn { @branchHint(.cold); - call("'noreturn' function returned", null, @returnAddress()); + call("'noreturn' function returned", @returnAddress()); } /// To be deleted after zig1.wasm update. @@ -531,13 +531,12 @@ pub fn assertReadable(slice: []const volatile u8) void { /// Equivalent to `@panic` but with a formatted message. pub fn panic(comptime format: []const u8, args: anytype) noreturn { @branchHint(.cold); - panicExtra(@errorReturnTrace(), @returnAddress(), format, args); + panicExtra(@returnAddress(), format, args); } /// Equivalent to `@panic` but with a formatted message, and with an explicitly -/// provided `@errorReturnTrace` and return address. +/// provided return address. pub fn panicExtra( - trace: ?*std.builtin.StackTrace, ret_addr: ?usize, comptime format: []const u8, args: anytype, @@ -556,7 +555,7 @@ pub fn panicExtra( break :blk &buf; }, }; - std.builtin.panic.call(msg, trace, ret_addr); + std.builtin.panic.call(msg, ret_addr); } /// Non-zero whenever the program triggered a panic. @@ -570,7 +569,6 @@ threadlocal var panic_stage: usize = 0; /// Dumps a stack trace to standard error, then aborts. pub fn defaultPanic( msg: []const u8, - error_return_trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize, ) noreturn { @branchHint(.cold); @@ -657,7 +655,7 @@ pub fn defaultPanic( } stderr.print("{s}\n", .{msg}) catch posix.abort(); - if (error_return_trace) |t| dumpStackTrace(t.*); + if (@errorReturnTrace()) |t| dumpStackTrace(t.*); dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); } diff --git a/lib/std/debug/no_panic.zig b/lib/std/debug/no_panic.zig index edd61ab974..690453b62a 100644 --- a/lib/std/debug/no_panic.zig +++ b/lib/std/debug/no_panic.zig @@ -5,7 +5,7 @@ const std = @import("../std.zig"); -pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +pub fn call(_: []const u8, _: ?usize) noreturn { @branchHint(.cold); @trap(); } @@ -15,7 +15,7 @@ pub fn sentinelMismatch(_: anytype, _: anytype) noreturn { @trap(); } -pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn { +pub fn unwrapError(_: anyerror) noreturn { @branchHint(.cold); @trap(); } diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig index 6a6c12aa2d..aeeba5b1d2 100644 --- a/lib/std/debug/simple_panic.zig +++ b/lib/std/debug/simple_panic.zig @@ -11,9 +11,8 @@ const std = @import("../std.zig"); /// Prints the message to stderr without a newline and then traps. /// /// Explicit calls to `@panic` lower to calling this function. -pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn { +pub fn call(msg: []const u8, ra: ?usize) noreturn { @branchHint(.cold); - _ = ert; _ = ra; std.debug.lockStdErr(); const stderr = std.io.getStdErr(); @@ -23,110 +22,109 @@ pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { _ = found; - call("sentinel mismatch", null, null); + call("sentinel mismatch", null); } -pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { - _ = ert; +pub fn unwrapError(err: anyerror) noreturn { _ = &err; - call("attempt to unwrap error", null, null); + call("attempt to unwrap error", null); } pub fn outOfBounds(index: usize, len: usize) noreturn { _ = index; _ = len; - call("index out of bounds", null, null); + call("index out of bounds", null); } pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { _ = start; _ = end; - call("start index is larger than end index", null, null); + call("start index is larger than end index", null); } pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { _ = accessed; - call("access of inactive union field", null, null); + call("access of inactive union field", null); } pub fn reachedUnreachable() noreturn { - call("reached unreachable code", null, null); + call("reached unreachable code", null); } pub fn unwrapNull() noreturn { - call("attempt to use null value", null, null); + call("attempt to use null value", null); } pub fn castToNull() noreturn { - call("cast causes pointer to be null", null, null); + call("cast causes pointer to be null", null); } pub fn incorrectAlignment() noreturn { - call("incorrect alignment", null, null); + call("incorrect alignment", null); } pub fn invalidErrorCode() noreturn { - call("invalid error code", null, null); + call("invalid error code", null); } pub fn castTruncatedData() noreturn { - call("integer cast truncated bits", null, null); + call("integer cast truncated bits", null); } pub fn negativeToUnsigned() noreturn { - call("attempt to cast negative value to unsigned integer", null, null); + call("attempt to cast negative value to unsigned integer", null); } pub fn integerOverflow() noreturn { - call("integer overflow", null, null); + call("integer overflow", null); } pub fn shlOverflow() noreturn { - call("left shift overflowed bits", null, null); + call("left shift overflowed bits", null); } pub fn shrOverflow() noreturn { - call("right shift overflowed bits", null, null); + call("right shift overflowed bits", null); } pub fn divideByZero() noreturn { - call("division by zero", null, null); + call("division by zero", null); } pub fn exactDivisionRemainder() noreturn { - call("exact division produced remainder", null, null); + call("exact division produced remainder", null); } pub fn integerPartOutOfBounds() noreturn { - call("integer part of floating point value out of bounds", null, null); + call("integer part of floating point value out of bounds", null); } pub fn corruptSwitch() noreturn { - call("switch on corrupt value", null, null); + call("switch on corrupt value", null); } pub fn shiftRhsTooBig() noreturn { - call("shift amount is greater than the type size", null, null); + call("shift amount is greater than the type size", null); } pub fn invalidEnumValue() noreturn { - call("invalid enum value", null, null); + call("invalid enum value", null); } pub fn forLenMismatch() noreturn { - call("for loop over objects with non-equal lengths", null, null); + call("for loop over objects with non-equal lengths", null); } pub fn memcpyLenMismatch() noreturn { - call("@memcpy arguments have non-equal lengths", null, null); + call("@memcpy arguments have non-equal lengths", null); } pub fn memcpyAlias() noreturn { - call("@memcpy arguments alias", null, null); + call("@memcpy arguments alias", null); } pub fn noreturnReturned() noreturn { - call("'noreturn' function returned", null, null); + call("'noreturn' function returned", null); } /// To be deleted after zig1.wasm update. diff --git a/src/Sema.zig b/src/Sema.zig index f2e52c2170..2c2841f27d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2584,7 +2584,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg std.debug.print("compile error during Sema:\n", .{}); var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); - crash_report.compilerPanic("unexpected compile error occurred", null, null); + crash_report.compilerPanic("unexpected compile error occurred", null); } if (block) |start_block| { diff --git a/src/crash_report.zig b/src/crash_report.zig index 26096574d3..431381fce4 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -158,12 +158,12 @@ fn writeFilePath(file: *Zcu.File, writer: anytype) !void { try writer.writeAll(file.sub_file_path); } -pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, maybe_ret_addr: ?usize) noreturn { +pub fn compilerPanic(msg: []const u8, maybe_ret_addr: ?usize) noreturn { @branchHint(.cold); PanicSwitch.preDispatch(); const ret_addr = maybe_ret_addr orelse @returnAddress(); const stack_ctx: StackContext = .{ .current = .{ .ret_addr = ret_addr } }; - PanicSwitch.dispatch(error_return_trace, stack_ctx, msg); + PanicSwitch.dispatch(@errorReturnTrace(), stack_ctx, msg); } /// Attaches a global SIGSEGV handler diff --git a/test/cases/compile_errors/bad_panic_call_signature.zig b/test/cases/compile_errors/bad_panic_call_signature.zig index 3536397241..b383ccf651 100644 --- a/test/cases/compile_errors/bad_panic_call_signature.zig +++ b/test/cases/compile_errors/bad_panic_call_signature.zig @@ -1,9 +1,8 @@ const simple_panic = std.debug.simple_panic; pub const panic = struct { - pub fn call(msg: []const u8, bad1: usize, bad2: void) noreturn { + pub fn call(msg: []const u8, bad: usize) noreturn { _ = msg; - _ = bad1; - _ = bad2; + _ = bad; @trap(); } pub const sentinelMismatch = simple_panic.sentinelMismatch; @@ -42,5 +41,5 @@ const std = @import("std"); // error // -// :3:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn' -// :3:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace' +// :3:9: error: expected type 'fn ([]const u8, ?usize) noreturn', found 'fn ([]const u8, usize) noreturn' +// :3:9: note: parameter 1 'usize' cannot cast into '?usize' diff --git a/test/incremental/change_panic_handler b/test/incremental/change_panic_handler index 3e0674a4d9..34a1f32dab 100644 --- a/test/incremental/change_panic_handler +++ b/test/incremental/change_panic_handler @@ -10,7 +10,7 @@ pub fn main() !u8 { return 1; } pub const panic = std.debug.FullPanic(myPanic); -fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanic(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } @@ -26,7 +26,7 @@ pub fn main() !u8 { return 1; } pub const panic = std.debug.FullPanic(myPanic); -fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanic(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } @@ -42,7 +42,7 @@ pub fn main() !u8 { return 1; } pub const panic = std.debug.FullPanic(myPanicNew); -fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanicNew(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit index 12258d7ce2..5739c46c1b 100644 --- a/test/incremental/change_panic_handler_explicit +++ b/test/incremental/change_panic_handler_explicit @@ -40,7 +40,7 @@ pub const panic = struct { pub const memcpyAlias = no_panic.memcpyAlias; pub const noreturnReturned = no_panic.noreturnReturned; }; -fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanic(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } @@ -86,7 +86,7 @@ pub const panic = struct { pub const memcpyAlias = no_panic.memcpyAlias; pub const noreturnReturned = no_panic.noreturnReturned; }; -fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanic(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } @@ -133,7 +133,7 @@ pub const panic = struct { pub const memcpyAlias = no_panic.memcpyAlias; pub const noreturnReturned = no_panic.noreturnReturned; }; -fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { +fn myPanicNew(msg: []const u8, _: ?usize) noreturn { std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; std.process.exit(0); } diff --git a/test/src/Cases.zig b/test/src/Cases.zig index c49576b2f7..b57a476e89 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -358,7 +358,6 @@ pub fn addFromDir(ctx: *Cases, dir: std.fs.Dir, b: *std.Build) void { var current_file: []const u8 = "none"; ctx.addFromDirInner(dir, ¤t_file, b) catch |err| { std.debug.panicExtra( - @errorReturnTrace(), @returnAddress(), "test harness failed to process file '{s}': {s}\n", .{ current_file, @errorName(err) }, -- cgit v1.2.3 From b6726913d31f9273317ab56c4d33096aee0a588f Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 24 Jan 2025 22:16:50 +0000 Subject: Zcu: remove `null_stack_trace` The new simplifications to the panic handler have eliminated the need for this piece of memoized state. --- src/Sema.zig | 15 --------------- src/Zcu.zig | 2 -- 2 files changed, 17 deletions(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 2c2841f27d..e4a2ab05b2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -38539,21 +38539,6 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, } } - if (stage == .panic) { - // We use `getBuiltinType` because this is from an earlier stage. - const stack_trace_ty = try sema.getBuiltinType(simple_src, .StackTrace); - const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); - const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); - const null_stack_trace = try pt.intern(.{ .opt = .{ - .ty = opt_ptr_stack_trace_ty.toIntern(), - .val = .none, - } }); - if (null_stack_trace != zcu.null_stack_trace) { - zcu.null_stack_trace = null_stack_trace; - any_changed = true; - } - } - return any_changed; } diff --git a/src/Zcu.zig b/src/Zcu.zig index 3582e8af3a..e13f62f0da 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -219,8 +219,6 @@ free_type_references: std.ArrayListUnmanaged(u32) = .empty, /// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = s })`, where `s` depends on the element. builtin_decl_values: BuiltinDecl.Memoized = .initFill(.none), -/// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = .panic })`. -null_stack_trace: InternPool.Index = .none, generation: u32 = 0, -- cgit v1.2.3