Commit 9ccf8d3332
Changed files (5)
lib
src
lib/std/builtin.zig
@@ -761,18 +761,91 @@ pub const TestFn = struct {
func: *const fn () anyerror!void,
};
+const old_version = std.SemanticVersion.parse("0.14.0-dev.1659+4ceefca14") catch unreachable;
+const is_old = @import("builtin").zig_version.order(old_version) != .gt;
+
/// This function type is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
-pub const PanicFn = fn (PanicCause, ?*StackTrace, ?usize) noreturn;
+pub const PanicFn = if (is_old)
+ fn ([]const u8, ?*StackTrace, ?usize) noreturn
+else
+ fn (PanicCause, ?*StackTrace, ?usize) noreturn;
/// The entry point for auto-generated calls by the compiler.
-pub const panic: PanicFn = if (@hasDecl(root, "panic"))
+pub const panic: PanicFn = if (is_old)
+ defaultPanicOld
+else if (@hasDecl(root, "panic"))
root.panic
else if (@hasDecl(root, "os") and @hasDecl(root.os, "panic"))
root.os.panic
else
std.debug.defaultPanic;
+pub fn defaultPanicOld(
+ msg: []const u8,
+ trace: ?*const std.builtin.StackTrace,
+ first_trace_addr: ?usize,
+) noreturn {
+ @branchHint(.cold);
+ std.debug.print("old panic: {s}\n", .{msg});
+ _ = trace;
+ _ = first_trace_addr;
+ @trap();
+}
+
+pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual });
+}
+
+pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(st, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
+}
+
+pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
+}
+
+pub fn panicStartGreaterThanEnd(start: usize, end: usize) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
+}
+
+pub fn panicInactiveUnionField(active: anytype, wanted: @TypeOf(active)) noreturn {
+ @branchHint(.cold);
+ std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ @tagName(wanted), @tagName(active) });
+}
+
+pub const panic_messages = struct {
+ pub const unreach = "reached unreachable code";
+ pub const unwrap_null = "attempt to use null value";
+ pub const cast_to_null = "cast causes pointer to be null";
+ pub const incorrect_alignment = "incorrect alignment";
+ pub const invalid_error_code = "invalid error code";
+ pub const cast_truncated_data = "integer cast truncated bits";
+ pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
+ pub const integer_overflow = "integer overflow";
+ pub const shl_overflow = "left shift overflowed bits";
+ pub const shr_overflow = "right shift overflowed bits";
+ pub const divide_by_zero = "division by zero";
+ pub const exact_division_remainder = "exact division produced remainder";
+ pub const inactive_union_field = "access of inactive union field";
+ pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
+ pub const corrupt_switch = "switch on corrupt value";
+ pub const shift_rhs_too_big = "shift amount is greater than the type size";
+ pub const invalid_enum_value = "invalid enum value";
+ pub const sentinel_mismatch = "sentinel mismatch";
+ pub const unwrap_error = "attempt to unwrap error";
+ pub const index_out_of_bounds = "index out of bounds";
+ pub const start_index_greater_than_end = "start index is larger than end index";
+ pub const for_len_mismatch = "for loop over objects with non-equal lengths";
+ pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
+ pub const memcpy_alias = "@memcpy arguments alias";
+ pub const noreturn_returned = "'noreturn' function returned";
+};
+
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const PanicCause = union(enum) {
lib/std/debug.zig
@@ -437,7 +437,7 @@ pub fn panicExtra(
break :blk &buf;
},
};
- std.builtin.panic(msg, trace, ret_addr);
+ std.builtin.panic(.{ .explicit_call = msg }, trace, ret_addr);
}
/// Non-zero whenever the program triggered a panic.
@@ -487,18 +487,6 @@ pub fn defaultPanic(
.freestanding => {
@trap();
},
- .wasi => {
- // TODO: before merging my branch, unify this logic with the main panic logic
- var buffer: [1000]u8 = undefined;
- var i: usize = 0;
- i += fmtPanicCause(buffer[i..], cause);
- buffer[i] = '\n';
- i += 1;
- const msg = buffer[0..i];
- lockStdErr();
- io.getStdErr().writeAll(msg) catch {};
- @trap();
- },
.uefi => {
const uefi = std.os.uefi;
@@ -571,7 +559,7 @@ pub fn defaultPanic(
i += fmtInt10(buffer[i..], std.Thread.getCurrentId());
i += fmtBuf(buffer[i..], " panic: ");
}
- i += fmtPanicCause(&buffer, cause);
+ i += fmtPanicCause(buffer[i..], cause);
buffer[i] = '\n';
i += 1;
const msg = buffer[0..i];
@@ -672,7 +660,7 @@ fn fmtInt10(out_buf: []u8, integer_value: usize) usize {
while (true) {
i -= 1;
- tmp_buf[i] = '0' + (a % 10);
+ tmp_buf[i] = '0' + @as(u8, @intCast(a % 10));
a /= 10;
if (a == 0) break;
}
src/codegen/llvm.zig
@@ -3848,13 +3848,13 @@ pub const Object = struct {
.undef => unreachable, // handled above
.simple_value => |simple_value| switch (simple_value) {
- .undefined,
- .void,
- .null,
- .empty_struct,
- .@"unreachable",
- .generic_poison,
- => unreachable, // non-runtime values
+ .undefined => unreachable, // non-runtime value
+ .void => unreachable, // non-runtime value
+ .null => unreachable, // non-runtime value
+ .empty_struct => unreachable, // non-runtime value
+ .@"unreachable" => unreachable, // non-runtime value
+ .generic_poison => unreachable, // non-runtime value
+
.false => .false,
.true => .true,
},
@@ -5675,43 +5675,48 @@ pub const FuncGen = struct {
}
}
- fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void {
- const o = fg.ng.object;
- const zcu = o.pt.zcu;
- const ip = &zcu.intern_pool;
- const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
- const msg_nav = ip.getNav(msg_nav_index);
- const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
- const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);
- const null_opt_addr_global = try fg.resolveNullOptUsize();
- const target = zcu.getTarget();
- const llvm_usize = try o.lowerType(Type.usize);
- // example:
- // call fastcc void @test2.panic(
- // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
- // i64 16, ; msg.len
- // ptr null, ; stack trace
- // ptr @2, ; addr (null ?usize)
- // )
- const panic_func = zcu.funcInfo(zcu.panic_func_index);
- const panic_nav = ip.getNav(panic_func.owner_nav);
- const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
- const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
- _ = try fg.wip.callIntrinsicAssumeCold();
- _ = try fg.wip.call(
- .normal,
- toLlvmCallConv(fn_info.cc, target),
- .none,
- panic_global.typeOf(&o.builder),
- panic_global.toValue(&o.builder),
- &.{
- msg_ptr.toValue(),
- try o.builder.intValue(llvm_usize, msg_len),
- try o.builder.nullValue(.ptr),
- null_opt_addr_global.toValue(),
- },
- "",
- );
+ const PanicCauseTag = @typeInfo(std.builtin.PanicCause).@"union".tag_type.?;
+
+ fn buildSimplePanic(fg: *FuncGen, panic_cause_tag: PanicCauseTag) !void {
+ // TODO update this before merging the branch
+ _ = panic_cause_tag;
+ //const o = fg.ng.object;
+ //const zcu = o.pt.zcu;
+ //const ip = &zcu.intern_pool;
+ //const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
+ //const msg_nav = ip.getNav(msg_nav_index);
+ //const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
+ //const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);
+ //const null_opt_addr_global = try fg.resolveNullOptUsize();
+ //const target = zcu.getTarget();
+ //const llvm_usize = try o.lowerType(Type.usize);
+ //// example:
+ //// call fastcc void @test2.panic(
+ //// ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
+ //// i64 16, ; msg.len
+ //// ptr null, ; stack trace
+ //// ptr @2, ; addr (null ?usize)
+ //// )
+ //const panic_func = zcu.funcInfo(zcu.panic_func_index);
+ //const panic_nav = ip.getNav(panic_func.owner_nav);
+ //const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
+ //const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
+ //_ = try fg.wip.callIntrinsicAssumeCold();
+ //_ = try fg.wip.call(
+ // .normal,
+ // toLlvmCallConv(fn_info.cc, target),
+ // .none,
+ // panic_global.typeOf(&o.builder),
+ // panic_global.toValue(&o.builder),
+ // &.{
+ // msg_ptr.toValue(),
+ // try o.builder.intValue(llvm_usize, msg_len),
+ // try o.builder.nullValue(.ptr),
+ // null_opt_addr_global.toValue(),
+ // },
+ // "",
+ //);
+ _ = try fg.wip.callIntrinsic(.normal, .none, .trap, &.{}, &.{}, "");
_ = try fg.wip.@"unreachable"();
}
src/crash_report.zig
@@ -212,7 +212,7 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
else => .not_supported,
};
- PanicSwitch.dispatch(null, stack_ctx, error_msg);
+ PanicSwitch.dispatch(null, stack_ctx, .{ .explicit_call = error_msg });
}
const WindowsSegfaultMessage = union(enum) {
@@ -338,7 +338,7 @@ const PanicSwitch = struct {
// it's happening and print a message.
var panic_state: *volatile PanicState = &panic_state_raw;
if (panic_state.awaiting_dispatch) {
- dispatch(null, .{ .current = .{ .ret_addr = null } }, "Panic while preparing callstack");
+ dispatch(null, .{ .current = .{ .ret_addr = null } }, .{ .explicit_call = "Panic while preparing callstack" });
}
panic_state.awaiting_dispatch = true;
}
@@ -518,6 +518,7 @@ const PanicSwitch = struct {
stack: StackContext,
panic_cause: std.builtin.PanicCause,
) void {
+ var buffer: [1000]u8 = undefined;
switch (state.recover_verbosity) {
.message_and_stack => {
// lower the verbosity, and restore it at the end if we don't panic.
@@ -525,7 +526,8 @@ const PanicSwitch = struct {
const stderr = io.getStdErr().writer();
stderr.writeAll("\nPanicked during a panic: ") catch {};
- stderr.writeAll(panic_cause) catch {};
+ const msg = buffer[0..std.debug.fmtPanicCause(&buffer, panic_cause)];
+ stderr.writeAll(msg) catch {};
stderr.writeAll("\nInner panic stack:\n") catch {};
if (trace) |t| {
debug.dumpStackTrace(t.*);
@@ -539,7 +541,8 @@ const PanicSwitch = struct {
const stderr = io.getStdErr().writer();
stderr.writeAll("\nPanicked while dumping inner panic stack: ") catch {};
- stderr.writeAll(panic_cause) catch {};
+ const msg = buffer[0..std.debug.fmtPanicCause(&buffer, panic_cause)];
+ stderr.writeAll(msg) catch {};
stderr.writeAll("\n") catch {};
// If we succeed, restore all the way to dumping the stack.
src/Sema.zig
@@ -2566,7 +2566,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(.{ .explicit_call = "unexpected compile error occurred" }, null, null);
}
if (block) |start_block| {
@@ -7334,17 +7334,21 @@ fn callPanic(
call_operation: CallOperation,
) !void {
const pt = sema.pt;
- if (!pt.zcu.backendSupportsFeature(.panic_fn)) {
+ const zcu = pt.zcu;
+ if (!zcu.backendSupportsFeature(.panic_fn)) {
_ = try block.addNoOp(.trap);
return;
}
const panic_cause_ty = try pt.getBuiltinType("PanicCause");
- const panic_cause = try block.addUnionInit(panic_cause_ty, @intFromEnum(tag), payload);
+ const panic_cause = if (payload == .void_value)
+ try initUnionFromEnumTag(pt, panic_cause_ty, panic_cause_ty.unionTagType(zcu).?, @intFromEnum(tag))
+ else
+ try block.addUnionInit(panic_cause_ty, @intFromEnum(tag), payload);
const panic_fn = try pt.getBuiltin("panic");
const err_return_trace = try sema.getErrorReturnTrace(block);
const opt_usize_ty = try pt.optionalType(.usize_type);
const null_usize = try pt.nullValue(opt_usize_ty);
- const args: [3]Air.Inst.Ref = .{ panic_cause, err_return_trace, Air.internedToRef(null_usize) };
+ const args: [3]Air.Inst.Ref = .{ panic_cause, err_return_trace, Air.internedToRef(null_usize.toIntern()) };
try sema.callBuiltin(block, call_src, panic_fn, .auto, &args, call_operation);
}
@@ -18326,11 +18330,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.undefined,
.null,
.enum_literal,
- => |type_info_tag| return Air.internedToRef((try pt.internUnion(.{
- .ty = type_info_ty.toIntern(),
- .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(type_info_tag))).toIntern(),
- .val = .void_value,
- }))),
+ => |type_info_tag| return initUnionFromEnumTag(pt, type_info_ty, type_info_tag_ty, @intFromEnum(type_info_tag)),
.@"fn" => {
const fn_info_ty = try getInnerType(sema, block, src, type_info_ty, "Fn");
const param_info_ty = try getInnerType(sema, block, src, fn_info_ty, "Param");
@@ -28009,7 +28009,7 @@ fn addSafetyCheckSentinelMismatch(
assert(std.mem.eql(u8, fields[1].name, "found"));
assert(fields.len == 2);
}
- const panic_cause_payload = &fail_block.addAggregateInit(mm_ty, &.{ expected_sentinel, actual_sentinel });
+ const panic_cause_payload = try fail_block.addAggregateInit(mm_ty, &.{ expected_sentinel, actual_sentinel });
try callPanic(sema, &fail_block, src, .sentinel_mismatch_usize, panic_cause_payload, .@"safety check");
} else {
try callPanic(sema, &fail_block, src, .sentinel_mismatch_other, .void_value, .@"safety check");
@@ -38997,3 +38997,11 @@ fn getInnerType(
try sema.ensureNavResolved(src, nav);
return Type.fromInterned(ip.getNav(nav).status.resolved.val);
}
+
+fn initUnionFromEnumTag(pt: Zcu.PerThread, union_ty: Type, union_tag_ty: Type, field_index: u32) !Air.Inst.Ref {
+ return Air.internedToRef((try pt.internUnion(.{
+ .ty = union_ty.toIntern(),
+ .tag = (try pt.enumValueFieldIndex(union_tag_ty, field_index)).toIntern(),
+ .val = .void_value,
+ })));
+}