@@ -33,6 +33,8 @@ const FrameIndex = bits.FrameIndex;
3333
3434const InnerError = codegen.CodeGenError || error{OutOfRegisters};
3535
36+ const error_return_trace_index: Air.Inst.Index = @enumFromInt(std.math.maxInt(u32));
37+
3638gpa: Allocator,
3739pt: Zcu.PerThread,
3840air: Air,
@@ -626,6 +628,7 @@ const InstTracking = struct {
626628 switch (self.long) {
627629 .none => self.long = try cg.allocRegOrMem(inst, false),
628630 .load_frame => {},
631+ .lea_frame => return,
629632 .reserved_frame => |index| self.long = .{ .load_frame = .{ .index = index } },
630633 else => unreachable,
631634 }
@@ -962,8 +965,16 @@ pub fn generate(
962965 } },
963966 .x86_64_win => .{ .win64 = .{} },
964967 };
968+ if (call_info.error_return_trace_reg != .none) {
969+ function.register_manager.getRegAssumeFree(call_info.error_return_trace_reg, error_return_trace_index);
970+ try function.inst_tracking.putNoClobber(
971+ gpa,
972+ error_return_trace_index,
973+ .init(.{ .register = call_info.error_return_trace_reg }),
974+ );
975+ }
965976
966- function.gen() catch |err| switch (err) {
977+ function.gen(call_info.error_return_trace_reg ) catch |err| switch (err) {
967978 error.CodegenFail => return error.CodegenFail,
968979 error.OutOfRegisters => return function.fail("ran out of registers (Zig compiler bug)", .{}),
969980 else => |e| return e,
@@ -2141,7 +2152,7 @@ fn asmMemoryRegisterImmediate(
21412152 });
21422153}
21432154
2144- fn gen(self: *CodeGen) InnerError!void {
2155+ fn gen(self: *CodeGen, error_return_trace_reg: Register ) InnerError!void {
21452156 const pt = self.pt;
21462157 const zcu = pt.zcu;
21472158 const fn_info = zcu.typeToFunc(self.fn_type).?;
@@ -2220,6 +2231,13 @@ fn gen(self: *CodeGen) InnerError!void {
22202231 break :epilogue_relocs self.epilogue_relocs.items[0..epilogue_relocs_last_index];
22212232 } else self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc);
22222233
2234+ if (error_return_trace_reg != .none) try self.genSetReg(
2235+ error_return_trace_reg,
2236+ .usize,
2237+ self.getResolvedInstValue(error_return_trace_index).short,
2238+ .{},
2239+ );
2240+
22232241 try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
22242242 const backpatch_stack_dealloc = try self.asmPlaceholder();
22252243 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
@@ -2503,9 +2521,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
25032521 .optional_payload => try cg.airOptionalPayload(inst),
25042522 .unwrap_errunion_err => try cg.airUnwrapErrUnionErr(inst),
25052523 .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),
25092524
25102525 .wrap_optional => try cg.airWrapOptional(inst),
25112526 .wrap_errunion_payload => try cg.airWrapErrUnionPayload(inst),
@@ -11236,12 +11251,50 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
1123611251 .wasm_memory_size => unreachable,
1123711252 .wasm_memory_grow => unreachable,
1123811253
11254+ .err_return_trace => {
11255+ const res = try cg.tempAlloc(.usize);
11256+ try cg.genSetReg(
11257+ res.tracking(cg).short.register,
11258+ .usize,
11259+ cg.getResolvedInstValue(error_return_trace_index).short,
11260+ .{},
11261+ );
11262+ try res.moveTo(inst, cg);
11263+ },
11264+ .set_err_return_trace => {
11265+ const un_op = air_datas[@intFromEnum(inst)].un_op;
11266+ var ops = try cg.tempsFromOperands(inst, .{un_op});
11267+ switch (ops[0].unwrap(cg)) {
11268+ .ref => {
11269+ const result = try cg.allocRegOrMem(error_return_trace_index, true);
11270+ try cg.genCopy(.usize, result, ops[0].tracking(cg).short, .{});
11271+ tracking_log.debug("{} => {} (birth)", .{ error_return_trace_index, result });
11272+ cg.inst_tracking.putAssumeCapacityNoClobber(error_return_trace_index, .init(result));
11273+ },
11274+ .temp => |temp_index| {
11275+ const temp_tracking = temp_index.tracking(cg);
11276+ tracking_log.debug("{} => {} (birth)", .{ error_return_trace_index, temp_tracking.short });
11277+ cg.inst_tracking.putAssumeCapacityNoClobber(error_return_trace_index, temp_tracking.*);
11278+ assert(cg.reuseTemp(error_return_trace_index, temp_index.toIndex(), temp_tracking));
11279+ },
11280+ }
11281+ },
11282+
1123911283 .addrspace_cast => {
1124011284 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
1124111285 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
1124211286 try ops[0].moveTo(inst, cg);
1124311287 },
1124411288
11289+ .save_err_return_trace_index => {
11290+ const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
11291+ const agg_ty = ty_pl.ty.toType();
11292+ assert(agg_ty.containerLayout(zcu) != .@"packed");
11293+ var ert: Temp = .{ .index = error_return_trace_index };
11294+ var res = try ert.load(.usize, .{ .disp = @intCast(agg_ty.structFieldOffset(ty_pl.payload, zcu)) }, cg);
11295+ try res.moveTo(inst, cg);
11296+ },
11297+
1124511298 .vector_store_elem => return cg.fail("TODO implement vector_store_elem", .{}),
1124611299
1124711300 .c_va_arg => try cg.airVaArg(inst),
@@ -11697,7 +11750,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
1169711750 const target_maybe_inst = if (state.free_registers.isSet(reg_index)) null else target_slot;
1169811751 if (std.debug.runtime_safety) if (target_maybe_inst) |target_inst|
1169911752 assert(self.inst_tracking.getIndex(target_inst).? < state.inst_tracking_len);
11700- if (opts.emit_instructions) {
11753+ if (opts.emit_instructions and current_maybe_inst != target_maybe_inst ) {
1170111754 if (current_maybe_inst) |current_inst|
1170211755 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);
1170311756 if (target_maybe_inst) |target_inst|
@@ -11709,7 +11762,7 @@ fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, co
1170911762 self.register_manager.freeRegIndex(reg_index);
1171011763 }
1171111764 if (target_maybe_inst) |target_inst| {
11712- self.register_manager.getRegIndexAssumeFree(reg_index, target_maybe_inst );
11765+ self.register_manager.getRegIndexAssumeFree(reg_index, target_inst );
1171311766 self.inst_tracking.getPtr(target_inst).?.trackMaterialize(target_inst, reg_tracking);
1171411767 }
1171511768 } else if (target_maybe_inst) |_|
@@ -11750,9 +11803,10 @@ pub fn spillEflagsIfOccupied(self: *CodeGen) !void {
1175011803 }
1175111804}
1175211805
11753- pub fn spillCallerPreservedRegs(self: *CodeGen, cc: std.builtin.CallingConvention.Tag) !void {
11806+ pub fn spillCallerPreservedRegs(self: *CodeGen, cc: std.builtin.CallingConvention.Tag, ignore_reg: Register ) !void {
1175411807 switch (cc) {
11755- inline .auto, .x86_64_sysv, .x86_64_win => |tag| try self.spillRegisters(abi.getCallerPreservedRegs(tag)),
11808+ inline .auto, .x86_64_sysv, .x86_64_win => |tag| inline for (comptime abi.getCallerPreservedRegs(tag)) |reg|
11809+ if (reg != ignore_reg) try self.register_manager.getKnownReg(reg, null),
1175611810 else => unreachable,
1175711811 }
1175811812}
@@ -14406,22 +14460,6 @@ fn genUnwrapErrUnionPayloadPtrMir(
1440614460 return result;
1440714461}
1440814462
14409- fn 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-
14415- fn airSetErrReturnTrace(self: *CodeGen, inst: Air.Inst.Index) !void {
14416- _ = inst;
14417- return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch});
14418- }
14419-
14420- fn airSaveErrReturnTraceIndex(self: *CodeGen, inst: Air.Inst.Index) !void {
14421- _ = inst;
14422- return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch});
14423- }
14424-
1442514463fn airWrapOptional(self: *CodeGen, inst: Air.Inst.Index) !void {
1442614464 const pt = self.pt;
1442714465 const zcu = pt.zcu;
@@ -21188,7 +21226,7 @@ fn genCall(self: *CodeGen, info: union(enum) {
2118821226 }
2118921227
2119021228 try self.spillEflagsIfOccupied();
21191- try self.spillCallerPreservedRegs(fn_info.cc);
21229+ try self.spillCallerPreservedRegs(fn_info.cc, call_info.error_return_trace_reg );
2119221230
2119321231 // set stack arguments first because this can clobber registers
2119421232 // also clobber spill arguments as we go
@@ -21273,6 +21311,24 @@ fn genCall(self: *CodeGen, info: union(enum) {
2127321311 else => unreachable,
2127421312 };
2127521313
21314+ if (call_info.error_return_trace_reg != .none) {
21315+ if (self.inst_tracking.getPtr(error_return_trace_index)) |error_return_trace| {
21316+ if (switch (error_return_trace.short) {
21317+ .register => |reg| call_info.error_return_trace_reg != reg,
21318+ else => true,
21319+ }) {
21320+ try self.register_manager.getReg(call_info.error_return_trace_reg, error_return_trace_index);
21321+ try reg_locks.append(self.register_manager.lockReg(call_info.error_return_trace_reg));
21322+
21323+ try self.genSetReg(call_info.error_return_trace_reg, .usize, error_return_trace.short, .{});
21324+ error_return_trace.trackMaterialize(error_return_trace_index, .{
21325+ .long = error_return_trace.long,
21326+ .short = .{ .register = call_info.error_return_trace_reg },
21327+ });
21328+ }
21329+ }
21330+ }
21331+
2127621332 // now we are free to set register arguments
2127721333 switch (call_info.return_value.long) {
2127821334 .none, .unreach => {},
@@ -26098,8 +26154,13 @@ fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void {
2609826154 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);
2609926155 }
2610026156
26157+ const error_return_trace_reg = if (zcu.comp.config.any_error_tracing) error_return_trace_reg: {
26158+ const param_gpr = abi.getCAbiIntParamRegs(.auto);
26159+ break :error_return_trace_reg param_gpr[param_gpr.len - 1];
26160+ } else .none;
26161+
2610126162 try self.spillEflagsIfOccupied();
26102- try self.spillCallerPreservedRegs(.auto);
26163+ try self.spillCallerPreservedRegs(.auto, error_return_trace_reg );
2610326164
2610426165 const param_regs = abi.getCAbiIntParamRegs(.auto);
2610526166
@@ -28564,6 +28625,7 @@ const CallMCValues = struct {
2856428625 stack_align: InternPool.Alignment,
2856528626 gp_count: u32,
2856628627 fp_count: u32,
28628+ error_return_trace_reg: Register,
2856728629
2856828630 fn deinit(self: *CallMCValues, func: *CodeGen) void {
2856928631 func.gpa.free(self.args);
@@ -28598,6 +28660,7 @@ fn resolveCallingConventionValues(
2859828660 .stack_align = undefined,
2859928661 .gp_count = 0,
2860028662 .fp_count = 0,
28663+ .error_return_trace_reg = .none,
2860128664 };
2860228665 errdefer self.gpa.free(result.args);
2860328666
@@ -28842,6 +28905,11 @@ fn resolveCallingConventionValues(
2884228905 var param_x87 = abi.getCAbiX87ParamRegs(cc);
2884328906 var param_sse = abi.getCAbiSseParamRegs(cc, self.target);
2884428907
28908+ if (zcu.comp.config.any_error_tracing) {
28909+ result.error_return_trace_reg = param_gpr[param_gpr.len - 1];
28910+ param_gpr = param_gpr[0 .. param_gpr.len - 1];
28911+ }
28912+
2884528913 // Return values
2884628914 result.return_value = if (ret_ty.isNoReturn(zcu))
2884728915 .init(.unreach)
@@ -29159,6 +29227,7 @@ fn typeOf(self: *CodeGen, inst: Air.Inst.Ref) Type {
2915929227}
2916029228
2916129229fn typeOfIndex(self: *CodeGen, inst: Air.Inst.Index) Type {
29230+ if (inst == error_return_trace_index) return .usize;
2916229231 const pt = self.pt;
2916329232 const zcu = pt.zcu;
2916429233 const temp: Temp = .{ .index = inst };
0 commit comments