authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-22 16:48:27+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-01-22 16:48:27+00:00
log0e815c652d7908be62612bb931c2ee9698dd41da
tree2fdefb0b7575805af532ed4fb60057d1cb3dc206
parent61fe307d0f05eea901577900f4ab2bdaf0ffb35f
parentd4b6a53327352dc239644dab0ec2abbe3a1b1be9
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22572 from jacobly0/new-error-trace

compiler: include error trace in all functions, implement for x86_64 backend

12 files changed, 174 insertions(+), 106 deletions(-)

lib/std/builtin.zig+2-1
...@@ -1150,9 +1150,10 @@ pub const panicInactiveUnionField = Panic.inactiveUnionField;...@@ -1150,9 +1150,10 @@ pub const panicInactiveUnionField = Panic.inactiveUnionField;
1150/// To be deleted after zig1.wasm is updated.1150/// To be deleted after zig1.wasm is updated.
1151pub const panic_messages = Panic.messages;1151pub const panic_messages = Panic.messages;
11521152
1153pub noinline fn returnError(st: *StackTrace) void {1153pub noinline fn returnError() void {
1154 @branchHint(.unlikely);1154 @branchHint(.unlikely);
1155 @setRuntimeSafety(false);1155 @setRuntimeSafety(false);
1156 const st = @errorReturnTrace().?;
1156 if (st.index < st.instruction_addresses.len)1157 if (st.index < st.instruction_addresses.len)
1157 st.instruction_addresses[st.index] = @returnAddress();1158 st.instruction_addresses[st.index] = @returnAddress();
1158 st.index += 1;1159 st.index += 1;
src/InternPool.zig+7-18
...@@ -2294,17 +2294,6 @@ pub const Key = union(enum) {...@@ -2294,17 +2294,6 @@ pub const Key = union(enum) {
2294 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);2294 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);
2295 }2295 }
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
2308 pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {2297 pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {
2309 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2298 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2310 extra_mutex.lock();2299 extra_mutex.lock();
...@@ -5975,7 +5964,7 @@ pub const FuncAnalysis = packed struct(u32) {...@@ -5975,7 +5964,7 @@ pub const FuncAnalysis = packed struct(u32) {
5975 is_analyzed: bool,5964 is_analyzed: bool,
5976 branch_hint: std.builtin.BranchHint,5965 branch_hint: std.builtin.BranchHint,
5977 is_noinline: bool,5966 is_noinline: bool,
5978 calls_or_awaits_errorable_fn: bool,5967 has_error_trace: bool,
5979 /// True if this function has an inferred error set.5968 /// True if this function has an inferred error set.
5980 inferred_error_set: bool,5969 inferred_error_set: bool,
5981 disable_instrumentation: bool,5970 disable_instrumentation: bool,
...@@ -9007,7 +8996,7 @@ pub fn getFuncDecl(...@@ -9007,7 +8996,7 @@ pub fn getFuncDecl(
9007 .is_analyzed = false,8996 .is_analyzed = false,
9008 .branch_hint = .none,8997 .branch_hint = .none,
9009 .is_noinline = key.is_noinline,8998 .is_noinline = key.is_noinline,
9010 .calls_or_awaits_errorable_fn = false,8999 .has_error_trace = false,
9011 .inferred_error_set = false,9000 .inferred_error_set = false,
9012 .disable_instrumentation = false,9001 .disable_instrumentation = false,
9013 },9002 },
...@@ -9116,7 +9105,7 @@ pub fn getFuncDeclIes(...@@ -9116,7 +9105,7 @@ pub fn getFuncDeclIes(
9116 .is_analyzed = false,9105 .is_analyzed = false,
9117 .branch_hint = .none,9106 .branch_hint = .none,
9118 .is_noinline = key.is_noinline,9107 .is_noinline = key.is_noinline,
9119 .calls_or_awaits_errorable_fn = false,9108 .has_error_trace = false,
9120 .inferred_error_set = true,9109 .inferred_error_set = true,
9121 .disable_instrumentation = false,9110 .disable_instrumentation = false,
9122 },9111 },
...@@ -9312,7 +9301,7 @@ pub fn getFuncInstance(...@@ -9312,7 +9301,7 @@ pub fn getFuncInstance(
9312 .is_analyzed = false,9301 .is_analyzed = false,
9313 .branch_hint = .none,9302 .branch_hint = .none,
9314 .is_noinline = arg.is_noinline,9303 .is_noinline = arg.is_noinline,
9315 .calls_or_awaits_errorable_fn = false,9304 .has_error_trace = false,
9316 .inferred_error_set = false,9305 .inferred_error_set = false,
9317 .disable_instrumentation = false,9306 .disable_instrumentation = false,
9318 },9307 },
...@@ -9410,7 +9399,7 @@ pub fn getFuncInstanceIes(...@@ -9410,7 +9399,7 @@ pub fn getFuncInstanceIes(
9410 .is_analyzed = false,9399 .is_analyzed = false,
9411 .branch_hint = .none,9400 .branch_hint = .none,
9412 .is_noinline = arg.is_noinline,9401 .is_noinline = arg.is_noinline,
9413 .calls_or_awaits_errorable_fn = false,9402 .has_error_trace = false,
9414 .inferred_error_set = true,9403 .inferred_error_set = true,
9415 .disable_instrumentation = false,9404 .disable_instrumentation = false,
9416 },9405 },
...@@ -12174,7 +12163,7 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {...@@ -12174,7 +12163,7 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
12174 return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);12163 return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);
12175}12164}
1217612165
12177pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {12166pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void {
12178 const unwrapped_func = func.unwrap(ip);12167 const unwrapped_func = func.unwrap(ip);
12179 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;12168 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12180 extra_mutex.lock();12169 extra_mutex.lock();
...@@ -12182,7 +12171,7 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {...@@ -12182,7 +12171,7 @@ pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void {
1218212171
12183 const analysis_ptr = ip.funcAnalysisPtr(func);12172 const analysis_ptr = ip.funcAnalysisPtr(func);
12184 var analysis = analysis_ptr.*;12173 var analysis = analysis_ptr.*;
12185 analysis.calls_or_awaits_errorable_fn = true;12174 analysis.has_error_trace = has_error_trace;
12186 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);12175 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
12187}12176}
1218812177
src/Sema.zig+19-24
...@@ -7198,14 +7198,6 @@ fn zirCall(...@@ -7198,14 +7198,6 @@ fn zirCall(
7198 const call_dbg_node: Zir.Inst.Index = @enumFromInt(@intFromEnum(inst) - 1);7198 const call_dbg_node: Zir.Inst.Index = @enumFromInt(@intFromEnum(inst) - 1);
7199 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);7199 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
7209 if (block.ownerModule().error_tracing and7201 if (block.ownerModule().error_tracing and
7210 !block.isComptime() and !block.is_typeof and (input_is_error or pop_error_return_trace))7202 !block.isComptime() and !block.is_typeof and (input_is_error or pop_error_return_trace))
7211 {7203 {
...@@ -7872,6 +7864,12 @@ fn analyzeCall(...@@ -7872,6 +7864,12 @@ fn analyzeCall(
7872 }7864 }
7873 break :msg msg;7865 break :msg msg;
7874 });7866 });
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 }
7875 for (args, 0..) |arg, arg_idx| {7873 for (args, 0..) |arg, arg_idx| {
7876 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);7874 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);
7877 }7875 }
...@@ -7946,13 +7944,6 @@ fn analyzeCall(...@@ -7946,13 +7944,6 @@ fn analyzeCall(
7946 try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());7944 try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());
7947 }7945 }
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
7956 const call_tag: Air.Inst.Tag = switch (modifier) {7947 const call_tag: Air.Inst.Tag = switch (modifier) {
7957 .auto, .no_async => .call,7948 .auto, .no_async => .call,
7958 .never_tail => .call_never_tail,7949 .never_tail => .call_never_tail,
...@@ -19706,16 +19697,16 @@ fn retWithErrTracing(...@@ -19706,16 +19697,16 @@ fn retWithErrTracing(
19706 .bool_false => false,19697 .bool_false => false,
19707 else => true,19698 else => true,
19708 };19699 };
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
19709 const gpa = sema.gpa;19705 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);
19714 const return_err_fn = Air.internedToRef(try sema.getBuiltin(src, .returnError));19706 const return_err_fn = Air.internedToRef(try sema.getBuiltin(src, .returnError));
19715 const args: [1]Air.Inst.Ref = .{err_return_trace};
1971619707
19717 if (!need_check) {19708 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");
19719 _ = try block.addUnOp(ret_tag, operand);19710 _ = try block.addUnOp(ret_tag, operand);
19720 return;19711 return;
19721 }19712 }
...@@ -19726,7 +19717,7 @@ fn retWithErrTracing(...@@ -19726,7 +19717,7 @@ fn retWithErrTracing(
1972619717
19727 var else_block = block.makeSubBlock();19718 var else_block = block.makeSubBlock();
19728 defer else_block.instructions.deinit(gpa);19719 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");
19730 _ = try else_block.addUnOp(ret_tag, operand);19721 _ = try else_block.addUnOp(ret_tag, operand);
1973119722
19732 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".fields.len +19723 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_...@@ -19837,7 +19828,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_
19837 return;19828 return;
19838 }19829 }
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;
19841 if (!start_block.ownerModule().error_tracing) return;19832 if (!start_block.ownerModule().error_tracing) return;
1984219833
19843 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere19834 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 {...@@ -21123,7 +21114,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
21123 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());21114 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
2112421115
21125 switch (sema.owner.unwrap()) {21116 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) {
21127 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);21118 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
21128 },21119 },
21129 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},21120 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
...@@ -27096,6 +27087,10 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPo...@@ -27096,6 +27087,10 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPo
27096 const zcu = sema.pt.zcu;27087 const zcu = sema.pt.zcu;
27097 try sema.ensureMemoizedStateResolved(src, .panic);27088 try sema.ensureMemoizedStateResolved(src, .panic);
27098 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));27089 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 }
27099 return zcu.builtin_decl_values.get(panic_id.toBuiltin());27094 return zcu.builtin_decl_values.get(panic_id.toBuiltin());
27100}27095}
2710127096
src/Zcu/PerThread.zig+4-6
...@@ -2596,7 +2596,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2596,7 +2596,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2596 }2596 }
25972597
2598 // reset in case calls to errorable functions are removed.2598 // 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
2601 // First few indexes of extra are reserved and set at the end.2601 // First few indexes of extra are reserved and set at the end.
2602 const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len;2602 const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len;
...@@ -2707,11 +2707,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2707,11 +2707,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27072707
2708 func.setBranchHint(ip, sema.branch_hint orelse .none);2708 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.2710 if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) {
2711 if (func.analysisUnordered(ip).calls_or_awaits_errorable_fn and2711 // We're using an error trace, but didn't start out with one from the caller.
2712 zcu.comp.config.any_error_tracing and2712 // We'll have to create it at the start of the function.
2713 !sema.fn_ret_ty.isError(zcu))
2714 {
2715 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {2713 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
2716 error.ComptimeReturn => unreachable,2714 error.ComptimeReturn => unreachable,
2717 error.ComptimeBreak => unreachable,2715 error.ComptimeBreak => unreachable,
src/arch/x86_64/CodeGen.zig+123-40
...@@ -33,6 +33,8 @@ const FrameIndex = bits.FrameIndex;...@@ -33,6 +33,8 @@ const FrameIndex = bits.FrameIndex;
3333
34const InnerError = codegen.CodeGenError || error{OutOfRegisters};34const InnerError = codegen.CodeGenError || error{OutOfRegisters};
3535
36const err_ret_trace_index: Air.Inst.Index = @enumFromInt(std.math.maxInt(u32));
37
36gpa: Allocator,38gpa: Allocator,
37pt: Zcu.PerThread,39pt: Zcu.PerThread,
38air: Air,40air: Air,
...@@ -55,6 +57,7 @@ va_info: union {...@@ -55,6 +57,7 @@ va_info: union {
55 win64: struct {},57 win64: struct {},
56},58},
57ret_mcv: InstTracking,59ret_mcv: InstTracking,
60err_ret_trace_reg: Register,
58fn_type: Type,61fn_type: Type,
59src_loc: Zcu.LazySrcLoc,62src_loc: Zcu.LazySrcLoc,
6063
...@@ -626,6 +629,7 @@ const InstTracking = struct {...@@ -626,6 +629,7 @@ const InstTracking = struct {
626 switch (self.long) {629 switch (self.long) {
627 .none => self.long = try cg.allocRegOrMem(inst, false),630 .none => self.long = try cg.allocRegOrMem(inst, false),
628 .load_frame => {},631 .load_frame => {},
632 .lea_frame => return,
629 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },633 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
630 else => unreachable,634 else => unreachable,
631 }635 }
...@@ -887,6 +891,7 @@ pub fn generate(...@@ -887,6 +891,7 @@ pub fn generate(
887 .args = undefined, // populated after `resolveCallingConventionValues`891 .args = undefined, // populated after `resolveCallingConventionValues`
888 .va_info = undefined, // populated after `resolveCallingConventionValues`892 .va_info = undefined, // populated after `resolveCallingConventionValues`
889 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`893 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
894 .err_ret_trace_reg = undefined, // populated after `resolveCallingConventionValues`
890 .fn_type = fn_type,895 .fn_type = fn_type,
891 .src_loc = src_loc,896 .src_loc = src_loc,
892 .end_di_line = func.rbrace_line,897 .end_di_line = func.rbrace_line,
...@@ -935,6 +940,7 @@ pub fn generate(...@@ -935,6 +940,7 @@ pub fn generate(
935940
936 function.args = call_info.args;941 function.args = call_info.args;
937 function.ret_mcv = call_info.return_value;942 function.ret_mcv = call_info.return_value;
943 function.err_ret_trace_reg = call_info.err_ret_trace_reg;
938 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), .init(.{944 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), .init(.{
939 .size = Type.usize.abiSize(zcu),945 .size = Type.usize.abiSize(zcu),
940 .alignment = Type.usize.abiAlignment(zcu).min(call_info.stack_align),946 .alignment = Type.usize.abiAlignment(zcu).min(call_info.stack_align),
...@@ -962,6 +968,14 @@ pub fn generate(...@@ -962,6 +968,14 @@ pub fn generate(
962 } },968 } },
963 .x86_64_win => .{ .win64 = .{} },969 .x86_64_win => .{ .win64 = .{} },
964 };970 };
971 if (call_info.err_ret_trace_reg != .none) {
972 function.register_manager.getRegAssumeFree(call_info.err_ret_trace_reg, err_ret_trace_index);
973 try function.inst_tracking.putNoClobber(
974 gpa,
975 err_ret_trace_index,
976 .init(.{ .register = call_info.err_ret_trace_reg }),
977 );
978 }
965979
966 function.gen() catch |err| switch (err) {980 function.gen() catch |err| switch (err) {
967 error.CodegenFail => return error.CodegenFail,981 error.CodegenFail => return error.CodegenFail,
...@@ -1042,6 +1056,7 @@ pub fn generateLazy(...@@ -1042,6 +1056,7 @@ pub fn generateLazy(
1042 .args = undefined,1056 .args = undefined,
1043 .va_info = undefined,1057 .va_info = undefined,
1044 .ret_mcv = undefined,1058 .ret_mcv = undefined,
1059 .err_ret_trace_reg = undefined,
1045 .fn_type = undefined,1060 .fn_type = undefined,
1046 .src_loc = src_loc,1061 .src_loc = src_loc,
1047 .end_di_line = undefined, // no debug info yet1062 .end_di_line = undefined, // no debug info yet
...@@ -2503,9 +2518,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -2503,9 +2518,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2503 .optional_payload => try cg.airOptionalPayload(inst),2518 .optional_payload => try cg.airOptionalPayload(inst),
2504 .unwrap_errunion_err => try cg.airUnwrapErrUnionErr(inst),2519 .unwrap_errunion_err => try cg.airUnwrapErrUnionErr(inst),
2505 .unwrap_errunion_payload => try cg.airUnwrapErrUnionPayload(inst),2520 .unwrap_errunion_payload => try cg.airUnwrapErrUnionPayload(inst),
2506 .err_return_trace => try cg.airErrReturnTrace(inst),
2507 .set_err_return_trace => try cg.airSetErrReturnTrace(inst),
2508 .save_err_return_trace_index=> try cg.airSaveErrReturnTraceIndex(inst),
25092521
2510 .wrap_optional => try cg.airWrapOptional(inst),2522 .wrap_optional => try cg.airWrapOptional(inst),
2511 .wrap_errunion_payload => try cg.airWrapErrUnionPayload(inst),2523 .wrap_errunion_payload => try cg.airWrapErrUnionPayload(inst),
...@@ -11236,12 +11248,46 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -11236,12 +11248,46 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
11236 .wasm_memory_size => unreachable,11248 .wasm_memory_size => unreachable,
11237 .wasm_memory_grow => unreachable,11249 .wasm_memory_grow => unreachable,
1123811250
11251 .err_return_trace => {
11252 const ert: Temp = .{ .index = err_ret_trace_index };
11253 try ert.moveTo(inst, cg);
11254 },
11255 .set_err_return_trace => {
11256 const un_op = air_datas[@intFromEnum(inst)].un_op;
11257 var ops = try cg.tempsFromOperands(inst, .{un_op});
11258 switch (ops[0].unwrap(cg)) {
11259 .ref => {
11260 const result = try cg.allocRegOrMem(err_ret_trace_index, true);
11261 try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});
11262 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, result });
11263 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, .init(result));
11264 },
11265 .temp => |temp_index| {
11266 const temp_tracking = temp_index.tracking(cg);
11267 tracking_log.debug("{} => {} (birth)", .{ err_ret_trace_index, temp_tracking.short });
11268 cg.inst_tracking.putAssumeCapacityNoClobber(err_ret_trace_index, temp_tracking.*);
11269 assert(cg.reuseTemp(err_ret_trace_index, temp_index.toIndex(), temp_tracking));
11270 },
11271 .err_ret_trace => unreachable,
11272 }
11273 },
11274
11239 .addrspace_cast => {11275 .addrspace_cast => {
11240 const ty_op = air_datas[@intFromEnum(inst)].ty_op;11276 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
11241 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});11277 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
11242 try ops[0].moveTo(inst, cg);11278 try ops[0].moveTo(inst, cg);
11243 },11279 },
1124411280
11281 .save_err_return_trace_index => {
11282 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
11283 const agg_ty = ty_pl.ty.toType();
11284 assert(agg_ty.containerLayout(zcu) != .@"packed");
11285 var ert: Temp = .{ .index = err_ret_trace_index };
11286 var res = try ert.load(.usize, .{ .disp = @intCast(agg_ty.structFieldOffset(ty_pl.payload, zcu)) }, cg);
11287 try ert.die(cg);
11288 try res.moveTo(inst, cg);
11289 },
11290
11245 .vector_store_elem => return cg.fail("TODO implement vector_store_elem", .{}),11291 .vector_store_elem => return cg.fail("TODO implement vector_store_elem", .{}),
1124611292
11247 .c_va_arg => try cg.airVaArg(inst),11293 .c_va_arg => try cg.airVaArg(inst),
...@@ -11697,7 +11743,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co...@@ -11697,7 +11743,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
11697 const target_maybe_inst = if (state.free_registers.isSet(reg_index)) null else target_slot;11743 const target_maybe_inst = if (state.free_registers.isSet(reg_index)) null else target_slot;
11698 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|11744 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
11699 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);11745 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
11700 if (opts.emit_instructions) {11746 if (opts.emit_instructions and current_maybe_inst != target_maybe_inst) {
11701 if (current_maybe_inst) |current_inst|11747 if (current_maybe_inst) |current_inst|
11702 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);11748 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);
11703 if (target_maybe_inst) |target_inst|11749 if (target_maybe_inst) |target_inst|
...@@ -11709,7 +11755,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co...@@ -11709,7 +11755,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
11709 self.register_manager.freeRegIndex(reg_index);11755 self.register_manager.freeRegIndex(reg_index);
11710 }11756 }
11711 if (target_maybe_inst) |target_inst| {11757 if (target_maybe_inst) |target_inst| {
11712 self.register_manager.getRegIndexAssumeFree(reg_index, target_maybe_inst);11758 self.register_manager.getRegIndexAssumeFree(reg_index, target_inst);
11713 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);11759 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);
11714 }11760 }
11715 } else if (target_maybe_inst) |_|11761 } else if (target_maybe_inst) |_|
...@@ -11750,9 +11796,10 @@ pub fn spillEflagsIfOccupied(self: *CodeGen) !void {...@@ -11750,9 +11796,10 @@ pub fn spillEflagsIfOccupied(self: *CodeGen) !void {
11750 }11796 }
11751}11797}
1175211798
11753pub fn spillCallerPreservedRegs(self: *CodeGen, cc: std.builtin.CallingConvention.Tag) !void {11799pub fn spillCallerPreservedRegs(self: *CodeGen, cc: std.builtin.CallingConvention.Tag, ignore_reg: Register) !void {
11754 switch (cc) {11800 switch (cc) {
11755 inline .auto, .x86_64_sysv, .x86_64_win => |tag| try self.spillRegisters(abi.getCallerPreservedRegs(tag)),11801 inline .auto, .x86_64_sysv, .x86_64_win => |tag| inline for (comptime abi.getCallerPreservedRegs(tag)) |reg|
11802 if (reg != ignore_reg) try self.register_manager.getKnownReg(reg, null),
11756 else => unreachable,11803 else => unreachable,
11757 }11804 }
11758}11805}
...@@ -14406,22 +14453,6 @@ fn genUnwrapErrUnionPayloadPtrMir(...@@ -14406,22 +14453,6 @@ fn genUnwrapErrUnionPayloadPtrMir(
14406 return result;14453 return result;
14407}14454}
1440814455
14409fn airErrReturnTrace(self: *CodeGen, inst: Air.Inst.Index) !void {
14410 _ = inst;
14411 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});
14412 //return self.finishAir(inst, result, .{ .none, .none, .none });
14413}
14414
14415fn airSetErrReturnTrace(self: *CodeGen, inst: Air.Inst.Index) !void {
14416 _ = inst;
14417 return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
14418}
14419
14420fn airSaveErrReturnTraceIndex(self: *CodeGen, inst: Air.Inst.Index) !void {
14421 _ = inst;
14422 return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
14423}
14424
14425fn airWrapOptional(self: *CodeGen, inst: Air.Inst.Index) !void {14456fn airWrapOptional(self: *CodeGen, inst: Air.Inst.Index) !void {
14426 const pt = self.pt;14457 const pt = self.pt;
14427 const zcu = pt.zcu;14458 const zcu = pt.zcu;
...@@ -21188,7 +21219,7 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -21188,7 +21219,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
21188 }21219 }
2118921220
21190 try self.spillEflagsIfOccupied();21221 try self.spillEflagsIfOccupied();
21191 try self.spillCallerPreservedRegs(fn_info.cc);21222 try self.spillCallerPreservedRegs(fn_info.cc, call_info.err_ret_trace_reg);
2119221223
21193 // set stack arguments first because this can clobber registers21224 // set stack arguments first because this can clobber registers
21194 // also clobber spill arguments as we go21225 // also clobber spill arguments as we go
...@@ -21273,6 +21304,24 @@ fn genCall(self: *CodeGen, info: union(enum) {...@@ -21273,6 +21304,24 @@ fn genCall(self: *CodeGen, info: union(enum) {
21273 else => unreachable,21304 else => unreachable,
21274 };21305 };
2127521306
21307 if (call_info.err_ret_trace_reg != .none) {
21308 if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
21309 if (switch (err_ret_trace.short) {
21310 .register => |reg| call_info.err_ret_trace_reg != reg,
21311 else => true,
21312 }) {
21313 try self.register_manager.getReg(call_info.err_ret_trace_reg, err_ret_trace_index);
21314 try reg_locks.append(self.register_manager.lockReg(call_info.err_ret_trace_reg));
21315
21316 try self.genSetReg(call_info.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
21317 err_ret_trace.trackMaterialize(err_ret_trace_index, .{
21318 .long = err_ret_trace.long,
21319 .short = .{ .register = call_info.err_ret_trace_reg },
21320 });
21321 }
21322 }
21323 }
21324
21276 // now we are free to set register arguments21325 // now we are free to set register arguments
21277 switch (call_info.return_value.long) {21326 switch (call_info.return_value.long) {
21278 .none, .unreach => {},21327 .none, .unreach => {},
...@@ -21447,6 +21496,17 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -21447,6 +21496,17 @@ fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
21447 else => unreachable,21496 else => unreachable,
21448 }21497 }
21449 self.ret_mcv.liveOut(self, inst);21498 self.ret_mcv.liveOut(self, inst);
21499
21500 if (self.err_ret_trace_reg != .none) {
21501 if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
21502 if (switch (err_ret_trace.short) {
21503 .register => |reg| self.err_ret_trace_reg != reg,
21504 else => true,
21505 }) try self.genSetReg(self.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
21506 err_ret_trace.liveOut(self, err_ret_trace_index);
21507 }
21508 }
21509
21450 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });21510 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });
2145121511
21452 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction21512 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
...@@ -21467,6 +21527,17 @@ fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -21467,6 +21527,17 @@ fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void {
21467 else => unreachable,21527 else => unreachable,
21468 }21528 }
21469 self.ret_mcv.liveOut(self, inst);21529 self.ret_mcv.liveOut(self, inst);
21530
21531 if (self.err_ret_trace_reg != .none) {
21532 if (self.inst_tracking.getPtr(err_ret_trace_index)) |err_ret_trace| {
21533 if (switch (err_ret_trace.short) {
21534 .register => |reg| self.err_ret_trace_reg != reg,
21535 else => true,
21536 }) try self.genSetReg(self.err_ret_trace_reg, .usize, err_ret_trace.short, .{});
21537 err_ret_trace.liveOut(self, err_ret_trace_index);
21538 }
21539 }
21540
21470 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });21541 try self.finishAir(inst, .unreach, .{ un_op, .none, .none });
2147121542
21472 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction21543 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
...@@ -26098,8 +26169,13 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -26098,8 +26169,13 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void {
26098 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);26169 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);
26099 }26170 }
2610026171
26172 const err_ret_trace_reg = if (zcu.comp.config.any_error_tracing) err_ret_trace_reg: {
26173 const param_gpr = abi.getCAbiIntParamRegs(.auto);
26174 break :err_ret_trace_reg param_gpr[param_gpr.len - 1];
26175 } else .none;
26176
26101 try self.spillEflagsIfOccupied();26177 try self.spillEflagsIfOccupied();
26102 try self.spillCallerPreservedRegs(.auto);26178 try self.spillCallerPreservedRegs(.auto, err_ret_trace_reg);
2610326179
26104 const param_regs = abi.getCAbiIntParamRegs(.auto);26180 const param_regs = abi.getCAbiIntParamRegs(.auto);
2610526181
...@@ -28564,6 +28640,7 @@ const CallMCValues = struct {...@@ -28564,6 +28640,7 @@ const CallMCValues = struct {
28564 stack_align: InternPool.Alignment,28640 stack_align: InternPool.Alignment,
28565 gp_count: u32,28641 gp_count: u32,
28566 fp_count: u32,28642 fp_count: u32,
28643 err_ret_trace_reg: Register,
2856728644
28568 fn deinit(self: *CallMCValues, func: *CodeGen) void {28645 fn deinit(self: *CallMCValues, func: *CodeGen) void {
28569 func.gpa.free(self.args);28646 func.gpa.free(self.args);
...@@ -28598,6 +28675,7 @@ fn resolveCallingConventionValues(...@@ -28598,6 +28675,7 @@ fn resolveCallingConventionValues(
28598 .stack_align = undefined,28675 .stack_align = undefined,
28599 .gp_count = 0,28676 .gp_count = 0,
28600 .fp_count = 0,28677 .fp_count = 0,
28678 .err_ret_trace_reg = .none,
28601 };28679 };
28602 errdefer self.gpa.free(result.args);28680 errdefer self.gpa.free(result.args);
2860328681
...@@ -28842,6 +28920,11 @@ fn resolveCallingConventionValues(...@@ -28842,6 +28920,11 @@ fn resolveCallingConventionValues(
28842 var param_x87 = abi.getCAbiX87ParamRegs(cc);28920 var param_x87 = abi.getCAbiX87ParamRegs(cc);
28843 var param_sse = abi.getCAbiSseParamRegs(cc, self.target);28921 var param_sse = abi.getCAbiSseParamRegs(cc, self.target);
2884428922
28923 if (zcu.comp.config.any_error_tracing) {
28924 result.err_ret_trace_reg = param_gpr[param_gpr.len - 1];
28925 param_gpr = param_gpr[0 .. param_gpr.len - 1];
28926 }
28927
28845 // Return values28928 // Return values
28846 result.return_value = if (ret_ty.isNoReturn(zcu))28929 result.return_value = if (ret_ty.isNoReturn(zcu))
28847 .init(.unreach)28930 .init(.unreach)
...@@ -29159,16 +29242,8 @@ fn typeOf(self: *CodeGen, inst: Air.Inst.Ref) Type {...@@ -29159,16 +29242,8 @@ fn typeOf(self: *CodeGen, inst: Air.Inst.Ref) Type {
29159}29242}
2916029243
29161fn typeOfIndex(self: *CodeGen, inst: Air.Inst.Index) Type {29244fn typeOfIndex(self: *CodeGen, inst: Air.Inst.Index) Type {
29162 const pt = self.pt;
29163 const zcu = pt.zcu;
29164 const temp: Temp = .{ .index = inst };29245 const temp: Temp = .{ .index = inst };
29165 return switch (temp.unwrap(self)) {29246 return temp.typeOf(self);
29166 .ref => switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
29167 .loop_switch_br => self.typeOf(self.air.unwrapSwitch(inst).operand),
29168 else => self.air.typeOfIndex(inst, &zcu.intern_pool),
29169 },
29170 .temp => temp.typeOf(self),
29171 };
29172}29247}
2917329248
29174fn intCompilerRtAbiName(int_bits: u32) u8 {29249fn intCompilerRtAbiName(int_bits: u32) u8 {
...@@ -29336,10 +29411,12 @@ const Temp = struct {...@@ -29336,10 +29411,12 @@ const Temp = struct {
29336 fn unwrap(temp: Temp, cg: *CodeGen) union(enum) {29411 fn unwrap(temp: Temp, cg: *CodeGen) union(enum) {
29337 ref: Air.Inst.Ref,29412 ref: Air.Inst.Ref,
29338 temp: Index,29413 temp: Index,
29414 err_ret_trace,
29339 } {29415 } {
29340 switch (temp.index.unwrap()) {29416 switch (temp.index.unwrap()) {
29341 .ref => |ref| return .{ .ref = ref },29417 .ref => |ref| return .{ .ref = ref },
29342 .target => |target_index| {29418 .target => |target_index| {
29419 if (temp.index == err_ret_trace_index) return .err_ret_trace;
29343 const temp_index: Index = @enumFromInt(target_index);29420 const temp_index: Index = @enumFromInt(target_index);
29344 assert(temp_index.isValid(cg));29421 assert(temp_index.isValid(cg));
29345 return .{ .temp = temp_index };29422 return .{ .temp = temp_index };
...@@ -29349,14 +29426,18 @@ const Temp = struct {...@@ -29349,14 +29426,18 @@ const Temp = struct {
2934929426
29350 fn typeOf(temp: Temp, cg: *CodeGen) Type {29427 fn typeOf(temp: Temp, cg: *CodeGen) Type {
29351 return switch (temp.unwrap(cg)) {29428 return switch (temp.unwrap(cg)) {
29352 .ref => |ref| cg.typeOf(ref),29429 .ref => switch (cg.air.instructions.items(.tag)[@intFromEnum(temp.index)]) {
29430 .loop_switch_br => cg.typeOf(cg.air.unwrapSwitch(temp.index).operand),
29431 else => cg.air.typeOfIndex(temp.index, &cg.pt.zcu.intern_pool),
29432 },
29353 .temp => |temp_index| temp_index.typeOf(cg),29433 .temp => |temp_index| temp_index.typeOf(cg),
29434 .err_ret_trace => .usize,
29354 };29435 };
29355 }29436 }
2935629437
29357 fn isMut(temp: Temp, cg: *CodeGen) bool {29438 fn isMut(temp: Temp, cg: *CodeGen) bool {
29358 return switch (temp.unwrap(cg)) {29439 return switch (temp.unwrap(cg)) {
29359 .ref => false,29440 .ref, .err_ret_trace => false,
29360 .temp => |temp_index| switch (temp_index.tracking(cg).short) {29441 .temp => |temp_index| switch (temp_index.tracking(cg).short) {
29361 .none,29442 .none,
29362 .unreach,29443 .unreach,
...@@ -29456,7 +29537,7 @@ const Temp = struct {...@@ -29456,7 +29537,7 @@ const Temp = struct {
29456 fn toOffset(temp: *Temp, off: i32, cg: *CodeGen) !void {29537 fn toOffset(temp: *Temp, off: i32, cg: *CodeGen) !void {
29457 if (off == 0) return;29538 if (off == 0) return;
29458 switch (temp.unwrap(cg)) {29539 switch (temp.unwrap(cg)) {
29459 .ref => {},29540 .ref, .err_ret_trace => {},
29460 .temp => |temp_index| {29541 .temp => |temp_index| {
29461 const temp_tracking = temp_index.tracking(cg);29542 const temp_tracking = temp_index.tracking(cg);
29462 switch (temp_tracking.short) {29543 switch (temp_tracking.short) {
...@@ -29617,6 +29698,7 @@ const Temp = struct {...@@ -29617,6 +29698,7 @@ const Temp = struct {
29617 },29698 },
29618 }29699 }
29619 },29700 },
29701 .err_ret_trace => unreachable,
29620 }29702 }
29621 const new_temp = try temp.getLimb(limb_ty, limb_index, cg);29703 const new_temp = try temp.getLimb(limb_ty, limb_index, cg);
29622 try temp.die(cg);29704 try temp.die(cg);
...@@ -29633,7 +29715,7 @@ const Temp = struct {...@@ -29633,7 +29715,7 @@ const Temp = struct {
29633 }29715 }
2963429716
29635 fn toReg(temp: *Temp, new_reg: Register, cg: *CodeGen) !bool {29717 fn toReg(temp: *Temp, new_reg: Register, cg: *CodeGen) !bool {
29636 const val, const ty = val_ty: switch (temp.unwrap(cg)) {29718 const val, const ty: Type = val_ty: switch (temp.unwrap(cg)) {
29637 .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) },29719 .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) },
29638 .temp => |temp_index| {29720 .temp => |temp_index| {
29639 const temp_tracking = temp_index.tracking(cg);29721 const temp_tracking = temp_index.tracking(cg);
...@@ -29641,6 +29723,7 @@ const Temp = struct {...@@ -29641,6 +29723,7 @@ const Temp = struct {
29641 temp_tracking.short.register == new_reg) return false;29723 temp_tracking.short.register == new_reg) return false;
29642 break :val_ty .{ temp_tracking.short, temp_index.typeOf(cg) };29724 break :val_ty .{ temp_tracking.short, temp_index.typeOf(cg) };
29643 },29725 },
29726 .err_ret_trace => .{ temp.tracking(cg).short, .usize },
29644 };29727 };
29645 const new_temp_index = cg.next_temp_index;29728 const new_temp_index = cg.next_temp_index;
29646 try cg.register_manager.getReg(new_reg, new_temp_index.toIndex());29729 try cg.register_manager.getReg(new_reg, new_temp_index.toIndex());
...@@ -30167,7 +30250,7 @@ const Temp = struct {...@@ -30167,7 +30250,7 @@ const Temp = struct {
3016730250
30168 fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void {30251 fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void {
30169 if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) {30252 if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) {
30170 .ref => {30253 .ref, .err_ret_trace => {
30171 const result = try cg.allocRegOrMem(inst, true);30254 const result = try cg.allocRegOrMem(inst, true);
30172 try cg.genCopy(cg.typeOfIndex(inst), result, temp.tracking(cg).short, .{});30255 try cg.genCopy(cg.typeOfIndex(inst), result, temp.tracking(cg).short, .{});
30173 tracking_log.debug("{} => {} (birth)", .{ inst, result });30256 tracking_log.debug("{} => {} (birth)", .{ inst, result });
...@@ -30184,7 +30267,7 @@ const Temp = struct {...@@ -30184,7 +30267,7 @@ const Temp = struct {
3018430267
30185 fn die(temp: Temp, cg: *CodeGen) !void {30268 fn die(temp: Temp, cg: *CodeGen) !void {
30186 switch (temp.unwrap(cg)) {30269 switch (temp.unwrap(cg)) {
30187 .ref => {},30270 .ref, .err_ret_trace => {},
30188 .temp => |temp_index| try temp_index.tracking(cg).die(cg, temp_index.toIndex()),30271 .temp => |temp_index| try temp_index.tracking(cg).die(cg, temp_index.toIndex()),
30189 }30272 }
30190 }30273 }
src/codegen/llvm.zig+14-12
...@@ -1497,8 +1497,7 @@ pub const Object = struct {...@@ -1497,8 +1497,7 @@ pub const Object = struct {
1497 .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),1497 .unsigned => try attributes.addRetAttr(.zeroext, &o.builder),
1498 };1498 };
14991499
1500 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and1500 const err_return_tracing = fn_info.cc == .auto and comp.config.any_error_tracing;
1501 comp.config.any_error_tracing;
15021501
1503 const err_ret_trace: Builder.Value = if (err_return_tracing) param: {1502 const err_ret_trace: Builder.Value = if (err_return_tracing) param: {
1504 const param = wip.arg(llvm_arg_i);1503 const param = wip.arg(llvm_arg_i);
...@@ -2805,9 +2804,7 @@ pub const Object = struct {...@@ -2805,9 +2804,7 @@ pub const Object = struct {
2805 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));2804 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void));
2806 }2805 }
28072806
2808 if (Type.fromInterned(fn_info.return_type).isError(zcu) and2807 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
2809 zcu.comp.config.any_error_tracing)
2810 {
2811 const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());2808 const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
2812 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));2809 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty));
2813 }2810 }
...@@ -2970,8 +2967,7 @@ pub const Object = struct {...@@ -2970,8 +2967,7 @@ pub const Object = struct {
2970 llvm_arg_i += 1;2967 llvm_arg_i += 1;
2971 }2968 }
29722969
2973 const err_return_tracing = Type.fromInterned(fn_info.return_type).isError(zcu) and2970 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
2974 zcu.comp.config.any_error_tracing;
29752971
2976 if (err_return_tracing) {2972 if (err_return_tracing) {
2977 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);2973 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
...@@ -3736,9 +3732,7 @@ pub const Object = struct {...@@ -3736,9 +3732,7 @@ pub const Object = struct {
3736 try llvm_params.append(o.gpa, .ptr);3732 try llvm_params.append(o.gpa, .ptr);
3737 }3733 }
37383734
3739 if (Type.fromInterned(fn_info.return_type).isError(zcu) and3735 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
3740 zcu.comp.config.any_error_tracing)
3741 {
3742 const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());3736 const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType());
3743 try llvm_params.append(o.gpa, try o.lowerType(ptr_ty));3737 try llvm_params.append(o.gpa, try o.lowerType(ptr_ty));
3744 }3738 }
...@@ -5483,7 +5477,7 @@ pub const FuncGen = struct {...@@ -5483,7 +5477,7 @@ pub const FuncGen = struct {
5483 break :blk ret_ptr;5477 break :blk ret_ptr;
5484 };5478 };
54855479
5486 const err_return_tracing = return_type.isError(zcu) and zcu.comp.config.any_error_tracing;5480 const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing;
5487 if (err_return_tracing) {5481 if (err_return_tracing) {
5488 assert(self.err_ret_trace != .none);5482 assert(self.err_ret_trace != .none);
5489 try llvm_args.append(self.err_ret_trace);5483 try llvm_args.append(self.err_ret_trace);
...@@ -5762,6 +5756,8 @@ pub const FuncGen = struct {...@@ -5762,6 +5756,8 @@ pub const FuncGen = struct {
5762 const panic_nav = ip.getNav(panic_func.owner_nav);5756 const panic_nav = ip.getNav(panic_func.owner_nav);
5763 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;5757 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5764 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);5758 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5759 const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto;
5760 if (has_err_trace) assert(fg.err_ret_trace != .none);
5765 _ = try fg.wip.callIntrinsicAssumeCold();5761 _ = try fg.wip.callIntrinsicAssumeCold();
5766 _ = try fg.wip.call(5762 _ = try fg.wip.call(
5767 .normal,5763 .normal,
...@@ -5769,7 +5765,13 @@ pub const FuncGen = struct {...@@ -5769,7 +5765,13 @@ pub const FuncGen = struct {
5769 .none,5765 .none,
5770 panic_global.typeOf(&o.builder),5766 panic_global.typeOf(&o.builder),
5771 panic_global.toValue(&o.builder),5767 panic_global.toValue(&o.builder),
5772 &.{5768 if (has_err_trace) &.{
5769 fg.err_ret_trace,
5770 msg_ptr.toValue(),
5771 try o.builder.intValue(llvm_usize, msg_len),
5772 try o.builder.nullValue(.ptr),
5773 null_opt_addr_global.toValue(),
5774 } else &.{
5773 msg_ptr.toValue(),5775 msg_ptr.toValue(),
5774 try o.builder.intValue(llvm_usize, msg_len),5776 try o.builder.intValue(llvm_usize, msg_len),
5775 try o.builder.nullValue(.ptr),5777 try o.builder.nullValue(.ptr),
src/target.zig+1-1
...@@ -708,7 +708,7 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt...@@ -708,7 +708,7 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
708 else => false,708 else => false,
709 },709 },
710 .error_return_trace => switch (backend) {710 .error_return_trace => switch (backend) {
711 .stage2_llvm => true,711 .stage2_llvm, .stage2_x86_64 => true,
712 else => false,712 else => false,
713 },713 },
714 .is_named_enum_value => switch (backend) {714 .is_named_enum_value => switch (backend) {
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1
...@@ -15,6 +15,6 @@ pub export fn entry() void {...@@ -15,6 +15,6 @@ pub export fn entry() void {
15// error15// error
16//16//
17// :7:25: error: unable to resolve comptime value17// :7:25: error: unable to resolve comptime value
18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_165.C' must be comptime-known18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_441.C' must be comptime-known
19// :4:16: note: struct requires comptime because of this field19// :4:16: note: struct requires comptime because of this field
20// :4:16: note: types are not available at runtime20// :4:16: note: types are not available at runtime
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-1
...@@ -16,5 +16,5 @@ pub export fn entry2() void {...@@ -16,5 +16,5 @@ pub export fn entry2() void {
16//16//
17// :3:6: error: no field or member function named 'copy' in '[]const u8'17// :3:6: error: no field or member function named 'copy' in '[]const u8'
18// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'18// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
19// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_169'19// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_445'
20// :12:6: note: struct declared here20// :12:6: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig+1-1
...@@ -6,6 +6,6 @@ export fn foo() void {...@@ -6,6 +6,6 @@ export fn foo() void {
66
7// error7// error
8//8//
9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_158'9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_434'
10// :3:16: note: struct declared here10// :3:16: note: struct declared here
11// :1:11: note: struct declared here11// :1:11: note: struct declared here
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig+1-1
...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {...@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {
12// backend=stage212// backend=stage2
13// target=native13// target=native
14//14//
15// :7:21: error: expected type 'error{A,C}', found 'error{A,B}'15// :7:21: error: expected type 'error{C,A}', found 'error{A,B}'
16// :7:21: note: 'error.B' not a member of destination error set16// :7:21: note: 'error.B' not a member of destination error set