Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/std/builtin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1150,9 +1150,10 @@ pub const panicInactiveUnionField = Panic.inactiveUnionField;
/// To be deleted after zig1.wasm is updated.
pub const panic_messages = Panic.messages;

pub noinline fn returnError(st: *StackTrace) void {
pub noinline fn returnError() void {
@branchHint(.unlikely);
@setRuntimeSafety(false);
const st = @errorReturnTrace().?;
if (st.index < st.instruction_addresses.len)
st.instruction_addresses[st.index] = @returnAddress();
st.index += 1;
Expand Down
25 changes: 7 additions & 18 deletions src/InternPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2294,17 +2294,6 @@ pub const Key = union(enum) {
return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);
}

pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void {
const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
extra_mutex.lock();
defer extra_mutex.unlock();

const analysis_ptr = func.analysisPtr(ip);
var analysis = analysis_ptr.*;
analysis.calls_or_awaits_errorable_fn = value;
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
}

pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {
const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
extra_mutex.lock();
Expand Down Expand Up @@ -5975,7 +5964,7 @@ pub const FuncAnalysis = packed struct(u32) {
is_analyzed: bool,
branch_hint: std.builtin.BranchHint,
is_noinline: bool,
calls_or_awaits_errorable_fn: bool,
has_error_trace: bool,
/// True if this function has an inferred error set.
inferred_error_set: bool,
disable_instrumentation: bool,
Expand Down Expand Up @@ -9007,7 +8996,7 @@ pub fn getFuncDecl(
.is_analyzed = false,
.branch_hint = .none,
.is_noinline = key.is_noinline,
.calls_or_awaits_errorable_fn = false,
.has_error_trace = false,
.inferred_error_set = false,
.disable_instrumentation = false,
},
Expand Down Expand Up @@ -9116,7 +9105,7 @@ pub fn getFuncDeclIes(
.is_analyzed = false,
.branch_hint = .none,
.is_noinline = key.is_noinline,
.calls_or_awaits_errorable_fn = false,
.has_error_trace = false,
.inferred_error_set = true,
.disable_instrumentation = false,
},
Expand Down Expand Up @@ -9312,7 +9301,7 @@ pub fn getFuncInstance(
.is_analyzed = false,
.branch_hint = .none,
.is_noinline = arg.is_noinline,
.calls_or_awaits_errorable_fn = false,
.has_error_trace = false,
.inferred_error_set = false,
.disable_instrumentation = false,
},
Expand Down Expand Up @@ -9410,7 +9399,7 @@ pub fn getFuncInstanceIes(
.is_analyzed = false,
.branch_hint = .none,
.is_noinline = arg.is_noinline,
.calls_or_awaits_errorable_fn = false,
.has_error_trace = false,
.inferred_error_set = true,
.disable_instrumentation = false,
},
Expand Down Expand Up @@ -12174,15 +12163,15 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);
}

pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void {
const unwrapped_func = func.unwrap(ip);
const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
extra_mutex.lock();
defer extra_mutex.unlock();

const analysis_ptr = ip.funcAnalysisPtr(func);
var analysis = analysis_ptr.*;
analysis.calls_or_awaits_errorable_fn = true;
analysis.has_error_trace = has_error_trace;
@atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
}

Expand Down
43 changes: 19 additions & 24 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7191,14 +7191,6 @@ fn zirCall(
const call_dbg_node: Zir.Inst.Index = @enumFromInt(@intFromEnum(inst) - 1);
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);

switch (sema.owner.unwrap()) {
.@"comptime", .type, .memoized_state, .nav_ty, .nav_val => input_is_error = false,
.func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
// No errorable fn actually called; we have no error return trace
input_is_error = false;
},
}

if (block.ownerModule().error_tracing and
!block.isComptime() and !block.is_typeof and (input_is_error or pop_error_return_trace))
{
Expand Down Expand Up @@ -7865,6 +7857,12 @@ fn analyzeCall(
}
break :msg msg;
});
if (func_ty_info.cc == .auto) {
switch (sema.owner.unwrap()) {
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
.func => |owner_func| ip.funcSetHasErrorTrace(owner_func, true),
}
}
for (args, 0..) |arg, arg_idx| {
try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);
}
Expand Down Expand Up @@ -7939,13 +7937,6 @@ fn analyzeCall(
try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());
}

switch (sema.owner.unwrap()) {
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
.func => |owner_func| if (resolved_ret_ty.isError(zcu)) {
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
},
}

const call_tag: Air.Inst.Tag = switch (modifier) {
.auto, .no_async => .call,
.never_tail => .call_never_tail,
Expand Down Expand Up @@ -19699,16 +19690,16 @@ fn retWithErrTracing(
.bool_false => false,
else => true,
};

// This means we're returning something that might be an error!
// This should only be possible with the `auto` cc, so we definitely have an error trace.
assert(pt.zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).has_error_trace);

const gpa = sema.gpa;
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
const return_err_fn = Air.internedToRef(try sema.getBuiltin(src, .returnError));
const args: [1]Air.Inst.Ref = .{err_return_trace};

if (!need_check) {
try sema.callBuiltin(block, src, return_err_fn, .never_inline, &args, .@"error return");
try sema.callBuiltin(block, src, return_err_fn, .never_inline, &.{}, .@"error return");
_ = try block.addUnOp(ret_tag, operand);
return;
}
Expand All @@ -19719,7 +19710,7 @@ fn retWithErrTracing(

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

try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len +
Expand Down Expand Up @@ -19830,7 +19821,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_
return;
}

if (!zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).calls_or_awaits_errorable_fn) return;
if (!zcu.intern_pool.funcAnalysisUnordered(sema.owner.unwrap().func).has_error_trace) return;
if (!start_block.ownerModule().error_tracing) return;

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

switch (sema.owner.unwrap()) {
.func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
.func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) {
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
},
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
Expand Down Expand Up @@ -27089,6 +27080,10 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPo
const zcu = sema.pt.zcu;
try sema.ensureMemoizedStateResolved(src, .panic);
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
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());
}

Expand Down
10 changes: 4 additions & 6 deletions src/Zcu/PerThread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2596,7 +2596,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
}

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

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

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

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