compiler: pass error return traces everywhere
This commit is contained in:
@@ -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();
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
@@ -12174,7 +12163,7 @@ 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();
|
||||
@@ -12182,7 +12171,7 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
43
src/Sema.zig
43
src/Sema.zig
@@ -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))
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 +
|
||||
@@ -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
|
||||
@@ -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 => {},
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
|
||||
@@ -1497,8 +1497,7 @@ pub const Object = struct {
|
||||
.unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
|
||||
};
|
||||
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
comp.config.any_error_tracing;
|
||||
const err_return_tracing = fn_info.cc == .auto and comp.config.any_error_tracing;
|
||||
|
||||
const err_ret_trace: Builder.Value = if (err_return_tracing) param: {
|
||||
const param = wip.arg(llvm_arg_i);
|
||||
@@ -2805,9 +2804,7 @@ pub const Object = struct {
|
||||
debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
|
||||
}
|
||||
|
||||
if (Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
zcu.comp.config.any_error_tracing)
|
||||
{
|
||||
if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
|
||||
const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
|
||||
debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
|
||||
}
|
||||
@@ -2970,8 +2967,7 @@ pub const Object = struct {
|
||||
llvm_arg_i += 1;
|
||||
}
|
||||
|
||||
const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
zcu.comp.config.any_error_tracing;
|
||||
const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
|
||||
|
||||
if (err_return_tracing) {
|
||||
try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
|
||||
@@ -3736,9 +3732,7 @@ pub const Object = struct {
|
||||
try llvm_params.append(o.gpa, .ptr);
|
||||
}
|
||||
|
||||
if (Type.fromInterned(fn_info.return_type).isError(zcu) and
|
||||
zcu.comp.config.any_error_tracing)
|
||||
{
|
||||
if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
|
||||
const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
|
||||
try llvm_params.append(o.gpa, try o.lowerType(ptr_ty));
|
||||
}
|
||||
@@ -5483,7 +5477,7 @@ pub const FuncGen = struct {
|
||||
break :blk ret_ptr;
|
||||
};
|
||||
|
||||
const err_return_tracing = return_type.isError(zcu) and zcu.comp.config.any_error_tracing;
|
||||
const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
|
||||
if (err_return_tracing) {
|
||||
assert(self.err_ret_trace != .none);
|
||||
try llvm_args.append(self.err_ret_trace);
|
||||
@@ -5762,6 +5756,8 @@ pub const FuncGen = struct {
|
||||
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);
|
||||
const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto;
|
||||
if (has_err_trace) assert(fg.err_ret_trace != .none);
|
||||
_ = try fg.wip.callIntrinsicAssumeCold();
|
||||
_ = try fg.wip.call(
|
||||
.normal,
|
||||
@@ -5769,7 +5765,13 @@ pub const FuncGen = struct {
|
||||
.none,
|
||||
panic_global.typeOf(&o.builder),
|
||||
panic_global.toValue(&o.builder),
|
||||
&.{
|
||||
if (has_err_trace) &.{
|
||||
fg.err_ret_trace,
|
||||
msg_ptr.toValue(),
|
||||
try o.builder.intValue(llvm_usize, msg_len),
|
||||
try o.builder.nullValue(.ptr),
|
||||
null_opt_addr_global.toValue(),
|
||||
} else &.{
|
||||
msg_ptr.toValue(),
|
||||
try o.builder.intValue(llvm_usize, msg_len),
|
||||
try o.builder.nullValue(.ptr),
|
||||
|
||||
Reference in New Issue
Block a user