Skip to content

Commit 0e815c6

Browse files
authored
Merge pull request #22572 from jacobly0/new-error-trace
compiler: include error trace in all functions, implement for x86_64 backend
2 parents 61fe307 + d4b6a53 commit 0e815c6

File tree

12 files changed

+174
-106
lines changed

12 files changed

+174
-106
lines changed

lib/std/builtin.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,9 +1150,10 @@ pub const panicInactiveUnionField = Panic.inactiveUnionField;
11501150
/// To be deleted after zig1.wasm is updated.
11511151
pub const panic_messages = Panic.messages;
11521152

1153-
pub noinline fn returnError(st: *StackTrace) void {
1153+
pub noinline fn returnError() void {
11541154
@branchHint(.unlikely);
11551155
@setRuntimeSafety(false);
1156+
const st = @errorReturnTrace().?;
11561157
if (st.index < st.instruction_addresses.len)
11571158
st.instruction_addresses[st.index] = @returnAddress();
11581159
st.index += 1;

src/InternPool.zig

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,17 +2294,6 @@ pub const Key = union(enum) {
22942294
return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);
22952295
}
22962296

2297-
pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void {
2298-
const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2299-
extra_mutex.lock();
2300-
defer extra_mutex.unlock();
2301-
2302-
const analysis_ptr = func.analysisPtr(ip);
2303-
var analysis = analysis_ptr.*;
2304-
analysis.calls_or_awaits_errorable_fn = value;
2305-
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
2306-
}
2307-
23082297
pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {
23092298
const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
23102299
extra_mutex.lock();
@@ -5975,7 +5964,7 @@ pub const FuncAnalysis = packed struct(u32) {
59755964
is_analyzed: bool,
59765965
branch_hint: std.builtin.BranchHint,
59775966
is_noinline: bool,
5978-
calls_or_awaits_errorable_fn: bool,
5967+
has_error_trace: bool,
59795968
/// True if this function has an inferred error set.
59805969
inferred_error_set: bool,
59815970
disable_instrumentation: bool,
@@ -9007,7 +8996,7 @@ pub fn getFuncDecl(
90078996
.is_analyzed = false,
90088997
.branch_hint = .none,
90098998
.is_noinline = key.is_noinline,
9010-
.calls_or_awaits_errorable_fn = false,
8999+
.has_error_trace = false,
90119000
.inferred_error_set = false,
90129001
.disable_instrumentation = false,
90139002
},
@@ -9116,7 +9105,7 @@ pub fn getFuncDeclIes(
91169105
.is_analyzed = false,
91179106
.branch_hint = .none,
91189107
.is_noinline = key.is_noinline,
9119-
.calls_or_awaits_errorable_fn = false,
9108+
.has_error_trace = false,
91209109
.inferred_error_set = true,
91219110
.disable_instrumentation = false,
91229111
},
@@ -9312,7 +9301,7 @@ pub fn getFuncInstance(
93129301
.is_analyzed = false,
93139302
.branch_hint = .none,
93149303
.is_noinline = arg.is_noinline,
9315-
.calls_or_awaits_errorable_fn = false,
9304+
.has_error_trace = false,
93169305
.inferred_error_set = false,
93179306
.disable_instrumentation = false,
93189307
},
@@ -9410,7 +9399,7 @@ pub fn getFuncInstanceIes(
94109399
.is_analyzed = false,
94119400
.branch_hint = .none,
94129401
.is_noinline = arg.is_noinline,
9413-
.calls_or_awaits_errorable_fn = false,
9402+
.has_error_trace = false,
94149403
.inferred_error_set = true,
94159404
.disable_instrumentation = false,
94169405
},
@@ -12174,15 +12163,15 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
1217412163
return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);
1217512164
}
1217612165

12177-
pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
12166+
pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void {
1217812167
const unwrapped_func = func.unwrap(ip);
1217912168
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
1218012169
extra_mutex.lock();
1218112170
defer extra_mutex.unlock();
1218212171

1218312172
const analysis_ptr = ip.funcAnalysisPtr(func);
1218412173
var analysis = analysis_ptr.*;
12185-
analysis.calls_or_awaits_errorable_fn = true;
12174+
analysis.has_error_trace = has_error_trace;
1218612175
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
1218712176
}
1218812177

src/Sema.zig

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7198,14 +7198,6 @@ fn zirCall(
71987198
const call_dbg_node: Zir.Inst.Index = @enumFromInt(@intFromEnum(inst) - 1);
71997199
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
72007200

7201-
switch (sema.owner.unwrap()) {
7202-
.@"comptime", .type, .memoized_state, .nav_ty, .nav_val => input_is_error = false,
7203-
.func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
7204-
// No errorable fn actually called; we have no error return trace
7205-
input_is_error = false;
7206-
},
7207-
}
7208-
72097201
if (block.ownerModule().error_tracing and
72107202
!block.isComptime() and !block.is_typeof and (input_is_error or pop_error_return_trace))
72117203
{
@@ -7872,6 +7864,12 @@ fn analyzeCall(
78727864
}
78737865
break :msg msg;
78747866
});
7867+
if (func_ty_info.cc == .auto) {
7868+
switch (sema.owner.unwrap()) {
7869+
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
7870+
.func => |owner_func| ip.funcSetHasErrorTrace(owner_func, true),
7871+
}
7872+
}
78757873
for (args, 0..) |arg, arg_idx| {
78767874
try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);
78777875
}
@@ -7946,13 +7944,6 @@ fn analyzeCall(
79467944
try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());
79477945
}
79487946

7949-
switch (sema.owner.unwrap()) {
7950-
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
7951-
.func => |owner_func| if (resolved_ret_ty.isError(zcu)) {
7952-
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
7953-
},
7954-
}
7955-
79567947
const call_tag: Air.Inst.Tag = switch (modifier) {
79577948
.auto, .no_async => .call,
79587949
.never_tail => .call_never_tail,
@@ -19706,16 +19697,16 @@ fn retWithErrTracing(
1970619697
.bool_false => false,
1970719698
else => true,
1970819699
};
19700+
19701+
// This means we're returning something that might be an error!
19702+
// This should only be possible with the `auto` cc, so we definitely have an error trace.
19703+
assert(pt.zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).has_error_trace);
19704+
1970919705
const gpa = sema.gpa;
19710-
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
19711-
try stack_trace_ty.resolveFields(pt);
19712-
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
19713-
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
1971419706
const return_err_fn = Air.internedToRef(try sema.getBuiltin(src, .returnError));
19715-
const args: [1]Air.Inst.Ref = .{err_return_trace};
1971619707

1971719708
if (!need_check) {
19718-
try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");
19709+
try sema.callBuiltin(block, src, return_err_fn, .never_inline, &.{}, .@"error return");
1971919710
_ = try block.addUnOp(ret_tag, operand);
1972019711
return;
1972119712
}
@@ -19726,7 +19717,7 @@ fn retWithErrTracing(
1972619717

1972719718
var else_block = block.makeSubBlock();
1972819719
defer else_block.instructions.deinit(gpa);
19729-
try sema.callBuiltin(&else_block, src, return_err_fn, .never_inline, &args, .@"error return");
19720+
try sema.callBuiltin(&else_block, src, return_err_fn, .never_inline, &.{}, .@"error return");
1973019721
_ = try else_block.addUnOp(ret_tag, operand);
1973119722

1973219723
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len +
@@ -19837,7 +19828,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_
1983719828
return;
1983819829
}
1983919830

19840-
if (!zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).calls_or_awaits_errorable_fn) return;
19831+
if (!zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).has_error_trace) return;
1984119832
if (!start_block.ownerModule().error_tracing) return;
1984219833

1984319834
assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
@@ -21123,7 +21114,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
2112321114
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
2112421115

2112521116
switch (sema.owner.unwrap()) {
21126-
.func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
21117+
.func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) {
2112721118
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
2112821119
},
2112921120
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
@@ -27096,6 +27087,10 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPo
2709627087
const zcu = sema.pt.zcu;
2709727088
try sema.ensureMemoizedStateResolved(src, .panic);
2709827089
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
27090+
switch (sema.owner.unwrap()) {
27091+
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
27092+
.func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true),
27093+
}
2709927094
return zcu.builtin_decl_values.get(panic_id.toBuiltin());
2710027095
}
2710127096

src/Zcu/PerThread.zig

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,7 +2596,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
25962596
}
25972597

25982598
// reset in case calls to errorable functions are removed.
2599-
func.setCallsOrAwaitsErrorableFn(ip, false);
2599+
ip.funcSetHasErrorTrace(func_index, fn_ty_info.cc == .auto);
26002600

26012601
// First few indexes of extra are reserved and set at the end.
26022602
const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len;
@@ -2707,11 +2707,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27072707

27082708
func.setBranchHint(ip, sema.branch_hint orelse .none);
27092709

2710-
// If we don't get an error return trace from a caller, create our own.
2711-
if (func.analysisUnordered(ip).calls_or_awaits_errorable_fn and
2712-
zcu.comp.config.any_error_tracing and
2713-
!sema.fn_ret_ty.isError(zcu))
2714-
{
2710+
if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) {
2711+
// We're using an error trace, but didn't start out with one from the caller.
2712+
// We'll have to create it at the start of the function.
27152713
sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
27162714
error.ComptimeReturn => unreachable,
27172715
error.ComptimeBreak => unreachable,

0 commit comments

Comments
 (0)