Skip to content

Commit df74c45

Browse files
authored
Merge pull request #11501 from Vexu/stage2-err-return-trace
stage2: error return traces
2 parents 3fde140 + 0a7f3be commit df74c45

File tree

19 files changed

+458
-49
lines changed

19 files changed

+458
-49
lines changed

lib/compiler_rt.zig

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,17 @@ comptime {
198198
const __trunctfxf2 = @import("compiler_rt/trunc_f80.zig").__trunctfxf2;
199199
@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });
200200

201-
if (builtin.zig_backend == .stage1) { // TODO
202-
switch (arch) {
203-
.i386,
204-
.x86_64,
205-
=> {
206-
const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack;
207-
@export(zig_probe_stack, .{
208-
.name = "__zig_probe_stack",
209-
.linkage = linkage,
210-
});
211-
},
212-
else => {},
213-
}
201+
switch (arch) {
202+
.i386,
203+
.x86_64,
204+
=> {
205+
const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack;
206+
@export(zig_probe_stack, .{
207+
.name = "__zig_probe_stack",
208+
.linkage = linkage,
209+
});
210+
},
211+
else => {},
214212
}
215213

216214
const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;

lib/std/builtin.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,5 +846,26 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
846846
}
847847
}
848848

849+
pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
850+
@setCold(true);
851+
std.debug.panicExtra(st, "attempt to unwrap error: {s}", .{@errorName(err)});
852+
}
853+
854+
pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
855+
@setCold(true);
856+
std.debug.panic("attempt to index out of bound: index {d}, len {d}", .{ index, len });
857+
}
858+
859+
pub noinline fn returnError(maybe_st: ?*StackTrace) void {
860+
@setCold(true);
861+
const st = maybe_st orelse return;
862+
addErrRetTraceAddr(st, @returnAddress());
863+
}
864+
865+
pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
866+
st.instruction_addresses[st.index & (st.instruction_addresses.len - 1)] = addr;
867+
st.index +%= 1;
868+
}
869+
849870
const std = @import("std.zig");
850871
const root = @import("root");

lib/test_runner.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ pub fn main() void {
9292
fail_count += 1;
9393
progress.log("FAIL ({s})\n", .{@errorName(err)});
9494
if (!have_tty) std.debug.print("FAIL ({s})\n", .{@errorName(err)});
95-
if (builtin.zig_backend != .stage2_llvm) if (@errorReturnTrace()) |trace| {
95+
if (@errorReturnTrace()) |trace| {
9696
std.debug.dumpStackTrace(trace.*);
97-
};
97+
}
9898
test_node.end();
9999
},
100100
}

src/Air.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,12 @@ pub const Inst = struct {
649649
/// flush().
650650
cmp_lt_errors_len,
651651

652+
/// Returns pointer to current error return trace.
653+
err_return_trace,
654+
655+
/// Sets the operand as the current error return trace,
656+
set_err_return_trace,
657+
652658
pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
653659
return switch (op) {
654660
.lt => .cmp_lt,
@@ -961,6 +967,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
961967
.alloc,
962968
.ret_ptr,
963969
.arg,
970+
.err_return_trace,
964971
=> return datas[inst].ty,
965972

966973
.assembly,
@@ -1048,6 +1055,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10481055
.memcpy,
10491056
.set_union_tag,
10501057
.prefetch,
1058+
.set_err_return_trace,
10511059
=> return Type.void,
10521060

10531061
.ptrtoint,

src/AstGen.zig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,33 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
856856
catch_token + 2
857857
else
858858
null;
859+
860+
var rhs = node_datas[node].rhs;
861+
while (true) switch (node_tags[rhs]) {
862+
.grouped_expression => rhs = node_datas[rhs].lhs,
863+
.unreachable_literal => {
864+
if (payload_token != null and mem.eql(u8, tree.tokenSlice(payload_token.?), "_")) {
865+
return astgen.failTok(payload_token.?, "discard of error capture; omit it instead", .{});
866+
} else if (payload_token != null) {
867+
return astgen.failTok(payload_token.?, "unused capture", .{});
868+
}
869+
const lhs = node_datas[node].lhs;
870+
871+
const operand = try reachableExpr(gz, scope, switch (rl) {
872+
.ref => .ref,
873+
else => .none,
874+
}, lhs, lhs);
875+
const result = try gz.addUnNode(switch (rl) {
876+
.ref => .err_union_payload_safe_ptr,
877+
else => .err_union_payload_safe,
878+
}, operand, node);
879+
switch (rl) {
880+
.none, .coerced_ty, .discard, .ref => return result,
881+
else => return rvalue(gz, rl, result, lhs),
882+
}
883+
},
884+
else => break,
885+
};
859886
switch (rl) {
860887
.ref => return orelseCatchExpr(
861888
gz,

src/Compilation.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14571457
errdefer if (module) |zm| zm.deinit();
14581458

14591459
const error_return_tracing = !strip and switch (options.optimize_mode) {
1460-
.Debug, .ReleaseSafe => true,
1460+
.Debug, .ReleaseSafe => (!options.target.isWasm() or options.target.os.tag == .emscripten) and
1461+
!options.target.cpu.arch.isBpf(),
14611462
.ReleaseFast, .ReleaseSmall => false,
14621463
};
14631464

src/Liveness.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ fn analyzeInst(
362362
.ret_addr,
363363
.frame_addr,
364364
.wasm_memory_size,
365+
.err_return_trace,
365366
=> return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
366367

367368
.not,
@@ -434,6 +435,7 @@ fn analyzeInst(
434435
.round,
435436
.trunc_float,
436437
.cmp_lt_errors_len,
438+
.set_err_return_trace,
437439
=> {
438440
const operand = inst_datas[inst].un_op;
439441
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });

src/Module.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,7 @@ pub const Fn = struct {
14271427
state: Analysis,
14281428
is_cold: bool = false,
14291429
is_noinline: bool = false,
1430+
calls_or_awaits_errorable_fn: bool = false,
14301431

14311432
/// Any inferred error sets that this function owns, both its own inferred error set and
14321433
/// inferred error sets of any inline/comptime functions called. Not to be confused
@@ -4838,6 +4839,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
48384839
};
48394840
defer sema.deinit();
48404841

4842+
// reset in case calls to errorable functions are removed.
4843+
func.calls_or_awaits_errorable_fn = false;
4844+
48414845
// First few indexes of extra are reserved and set at the end.
48424846
const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
48434847
try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);
@@ -4936,6 +4940,8 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
49364940
func.state = .in_progress;
49374941
log.debug("set {s} to in_progress", .{decl.name});
49384942

4943+
const last_arg_index = inner_block.instructions.items.len;
4944+
49394945
sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
49404946
// TODO make these unreachable instead of @panic
49414947
error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
@@ -4944,6 +4950,21 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
49444950
else => |e| return e,
49454951
};
49464952

4953+
// If we don't get an error return trace from a caller, create our own.
4954+
if (func.calls_or_awaits_errorable_fn and
4955+
mod.comp.bin_file.options.error_return_tracing and
4956+
!sema.fn_ret_ty.isError())
4957+
{
4958+
sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
4959+
// TODO make these unreachable instead of @panic
4960+
error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
4961+
error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
4962+
error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),
4963+
error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"),
4964+
else => |e| return e,
4965+
};
4966+
}
4967+
49474968
try wip_captures.finalize();
49484969

49494970
// Copy the block into place and mark that as the main block.

0 commit comments

Comments
 (0)