| author | |
| committer | |
| log | 724d75363855176aa5e6b3d9bcd1656e2cc1f6a6 |
| tree | f3b5c2e68dcc355ade60e3c75065002715040790 |
| parent | 3007fdde45868142654d0bfa59bc0e17e5f24a1c |
This is encoded as a primitive AIR instruction to resolve one corner
case: A function may include a `catch { ... }` or `else |err| { ... }`
block but not call any errorable fn. In that case, there is no error
return trace to save the index of and codegen needs to avoid
interacting with the non-existing error trace.
By using a primitive AIR op, we can depend on Liveness to mark this
unused in this corner case.12 files changed, 76 insertions(+), 10 deletions(-)
src/Air.zig+5| ... | @@ -733,6 +733,10 @@ pub const Inst = struct { | ... | @@ -733,6 +733,10 @@ pub const Inst = struct { |
| 733 | /// Uses the `ty_op` field. | 733 | /// Uses the `ty_op` field. |
| 734 | addrspace_cast, | 734 | addrspace_cast, |
| 735 | 735 | ||
| 736 | /// Saves the error return trace index, if any. Otherwise, returns 0. | ||
| 737 | /// Uses the `ty_op` field. | ||
| 738 | save_err_return_trace_index, | ||
| 739 | |||
| 736 | pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag { | 740 | pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag { |
| 737 | switch (op) { | 741 | switch (op) { |
| 738 | .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt, | 742 | .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt, |
| ... | @@ -1179,6 +1183,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -1179,6 +1183,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1179 | .slice_len, | 1183 | .slice_len, |
| 1180 | .ret_addr, | 1184 | .ret_addr, |
| 1181 | .frame_addr, | 1185 | .frame_addr, |
| 1186 | .save_err_return_trace_index, | ||
| 1182 | => return Type.usize, | 1187 | => return Type.usize, |
| 1183 | 1188 | ||
| 1184 | .wasm_memory_grow => return Type.i32, | 1189 | .wasm_memory_grow => return Type.i32, |
src/Liveness.zig+2| ... | @@ -228,6 +228,7 @@ pub fn categorizeOperand( | ... | @@ -228,6 +228,7 @@ pub fn categorizeOperand( |
| 228 | .frame_addr, | 228 | .frame_addr, |
| 229 | .wasm_memory_size, | 229 | .wasm_memory_size, |
| 230 | .err_return_trace, | 230 | .err_return_trace, |
| 231 | .save_err_return_trace_index, | ||
| 231 | => return .none, | 232 | => return .none, |
| 232 | 233 | ||
| 233 | .fence => return .write, | 234 | .fence => return .write, |
| ... | @@ -805,6 +806,7 @@ fn analyzeInst( | ... | @@ -805,6 +806,7 @@ fn analyzeInst( |
| 805 | .frame_addr, | 806 | .frame_addr, |
| 806 | .wasm_memory_size, | 807 | .wasm_memory_size, |
| 807 | .err_return_trace, | 808 | .err_return_trace, |
| 809 | .save_err_return_trace_index, | ||
| 808 | => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }), | 810 | => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }), |
| 809 | 811 | ||
| 810 | .not, | 812 | .not, |
src/Sema.zig+17-10| ... | @@ -16228,22 +16228,28 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -16228,22 +16228,28 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 16228 | // This is only relevant at runtime. | 16228 | // This is only relevant at runtime. |
| 16229 | if (block.is_comptime) return Air.Inst.Ref.zero_usize; | 16229 | if (block.is_comptime) return Air.Inst.Ref.zero_usize; |
| 16230 | 16230 | ||
| 16231 | // In the corner case that `catch { ... }` or `else |err| { ... }` is used in a function | ||
| 16232 | // that does *not* make any errorable calls, we still need an error trace to interact with | ||
| 16233 | // the AIR instructions we've already emitted. | ||
| 16234 | if (sema.owner_func != null) | ||
| 16235 | sema.owner_func.?.calls_or_awaits_errorable_fn = true; | ||
| 16236 | |||
| 16237 | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; | 16231 | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 16238 | const ok = sema.mod.comp.bin_file.options.error_return_tracing and | 16232 | const ok = sema.mod.comp.bin_file.options.error_return_tracing and |
| 16239 | backend_supports_error_return_tracing; | 16233 | backend_supports_error_return_tracing; |
| 16240 | if (!ok) return Air.Inst.Ref.zero_usize; | 16234 | if (!ok) return Air.Inst.Ref.zero_usize; |
| 16241 | 16235 | ||
| 16236 | // This is encoded as a primitive AIR instruction to resolve one corner case: A function | ||
| 16237 | // may include a `catch { ... }` or `else |err| { ... }` block but not call any errorable | ||
| 16238 | // fn. In that case, there is no error return trace to save the index of and codegen needs | ||
| 16239 | // to avoid interacting with the non-existing error trace. | ||
| 16240 | // | ||
| 16241 | // By using a primitive AIR op, we can depend on Liveness to mark this unused in this corner case. | ||
| 16242 | |||
| 16242 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); | 16243 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); |
| 16243 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); | 16244 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); |
| 16244 | const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty); | 16245 | const field_index = try sema.structFieldIndex(block, stack_trace_ty, "index", src); |
| 16245 | const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); | 16246 | return block.addInst(.{ |
| 16246 | return sema.fieldVal(block, src, err_return_trace, "index", src); | 16247 | .tag = .save_err_return_trace_index, |
| 16248 | .data = .{ .ty_pl = .{ | ||
| 16249 | .ty = try sema.addType(stack_trace_ty), | ||
| 16250 | .payload = @intCast(u32, field_index), | ||
| 16251 | } }, | ||
| 16252 | }); | ||
| 16247 | } | 16253 | } |
| 16248 | 16254 | ||
| 16249 | fn zirRestoreErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 16255 | fn zirRestoreErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -16254,7 +16260,8 @@ fn zirRestoreErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -16254,7 +16260,8 @@ fn zirRestoreErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 16254 | if (block.is_comptime) return; | 16260 | if (block.is_comptime) return; |
| 16255 | 16261 | ||
| 16256 | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; | 16262 | const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; |
| 16257 | const ok = sema.mod.comp.bin_file.options.error_return_tracing and | 16263 | const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and |
| 16264 | sema.mod.comp.bin_file.options.error_return_tracing and | ||
| 16258 | backend_supports_error_return_tracing; | 16265 | backend_supports_error_return_tracing; |
| 16259 | if (!ok) return; | 16266 | if (!ok) return; |
| 16260 | 16267 |
src/arch/aarch64/CodeGen.zig+6| ... | @@ -702,6 +702,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -702,6 +702,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 702 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 702 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 703 | .err_return_trace => try self.airErrReturnTrace(inst), | 703 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 704 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), | 704 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| 705 | .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst), | ||
| 705 | 706 | ||
| 706 | .wrap_optional => try self.airWrapOptional(inst), | 707 | .wrap_optional => try self.airWrapOptional(inst), |
| 707 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 708 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | @@ -2867,6 +2868,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2867,6 +2868,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 2867 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); | 2868 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 2868 | } | 2869 | } |
| 2869 | 2870 | ||
| 2871 | fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2872 | _ = inst; | ||
| 2873 | return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch}); | ||
| 2874 | } | ||
| 2875 | |||
| 2870 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 2876 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 2871 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2877 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2872 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2878 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/arch/arm/CodeGen.zig+6| ... | @@ -751,6 +751,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -751,6 +751,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 751 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 751 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 752 | .err_return_trace => try self.airErrReturnTrace(inst), | 752 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 753 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), | 753 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| 754 | .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst), | ||
| 754 | 755 | ||
| 755 | .wrap_optional => try self.airWrapOptional(inst), | 756 | .wrap_optional => try self.airWrapOptional(inst), |
| 756 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 757 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | @@ -2116,6 +2117,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2116,6 +2117,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 2116 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); | 2117 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 2117 | } | 2118 | } |
| 2118 | 2119 | ||
| 2120 | fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2121 | _ = inst; | ||
| 2122 | return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch}); | ||
| 2123 | } | ||
| 2124 | |||
| 2119 | /// T to E!T | 2125 | /// T to E!T |
| 2120 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 2126 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2121 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2127 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
src/arch/riscv64/CodeGen.zig+6| ... | @@ -665,6 +665,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -665,6 +665,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 665 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 665 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 666 | .err_return_trace => try self.airErrReturnTrace(inst), | 666 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 667 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), | 667 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| 668 | .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst), | ||
| 668 | 669 | ||
| 669 | .wrap_optional => try self.airWrapOptional(inst), | 670 | .wrap_optional => try self.airWrapOptional(inst), |
| 670 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 671 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | @@ -1329,6 +1330,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1329,6 +1330,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 1329 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); | 1330 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 1330 | } | 1331 | } |
| 1331 | 1332 | ||
| 1333 | fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1334 | _ = inst; | ||
| 1335 | return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch}); | ||
| 1336 | } | ||
| 1337 | |||
| 1332 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 1338 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1333 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1339 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1334 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1340 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
src/arch/sparc64/CodeGen.zig+1| ... | @@ -679,6 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -679,6 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 679 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 679 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 680 | .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"), | 680 | .err_return_trace => @panic("TODO try self.airErrReturnTrace(inst)"), |
| 681 | .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"), | 681 | .set_err_return_trace => @panic("TODO try self.airSetErrReturnTrace(inst)"), |
| 682 | .save_err_return_trace_index=> @panic("TODO try self.airSaveErrReturnTraceIndex(inst)"), | ||
| 682 | 683 | ||
| 683 | .wrap_optional => try self.airWrapOptional(inst), | 684 | .wrap_optional => try self.airWrapOptional(inst), |
| 684 | .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"), | 685 | .wrap_errunion_payload => @panic("TODO try self.airWrapErrUnionPayload(inst)"), |
src/arch/wasm/CodeGen.zig+1| ... | @@ -1857,6 +1857,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1857,6 +1857,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1857 | .tag_name, | 1857 | .tag_name, |
| 1858 | .err_return_trace, | 1858 | .err_return_trace, |
| 1859 | .set_err_return_trace, | 1859 | .set_err_return_trace, |
| 1860 | .save_err_return_trace_index, | ||
| 1860 | .is_named_enum_value, | 1861 | .is_named_enum_value, |
| 1861 | .error_set_has_value, | 1862 | .error_set_has_value, |
| 1862 | .addrspace_cast, | 1863 | .addrspace_cast, |
src/arch/x86_64/CodeGen.zig+6| ... | @@ -756,6 +756,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -756,6 +756,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 756 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 756 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 757 | .err_return_trace => try self.airErrReturnTrace(inst), | 757 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 758 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), | 758 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| 759 | .save_err_return_trace_index=> try self.airSaveErrReturnTraceIndex(inst), | ||
| 759 | 760 | ||
| 760 | .wrap_optional => try self.airWrapOptional(inst), | 761 | .wrap_optional => try self.airWrapOptional(inst), |
| 761 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 762 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | @@ -1973,6 +1974,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1973,6 +1974,11 @@ fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 1973 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); | 1974 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 1974 | } | 1975 | } |
| 1975 | 1976 | ||
| 1977 | fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1978 | _ = inst; | ||
| 1979 | return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch}); | ||
| 1980 | } | ||
| 1981 | |||
| 1976 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 1982 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1977 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1983 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1978 | if (self.liveness.isUnused(inst)) { | 1984 | if (self.liveness.isUnused(inst)) { |
src/codegen/c.zig+6| ... | @@ -1935,6 +1935,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1935,6 +1935,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1935 | .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), | 1935 | .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), |
| 1936 | .err_return_trace => try airErrReturnTrace(f, inst), | 1936 | .err_return_trace => try airErrReturnTrace(f, inst), |
| 1937 | .set_err_return_trace => try airSetErrReturnTrace(f, inst), | 1937 | .set_err_return_trace => try airSetErrReturnTrace(f, inst), |
| 1938 | .save_err_return_trace_index => try airSaveErrReturnTraceIndex(f, inst), | ||
| 1938 | 1939 | ||
| 1939 | .wasm_memory_size => try airWasmMemorySize(f, inst), | 1940 | .wasm_memory_size => try airWasmMemorySize(f, inst), |
| 1940 | .wasm_memory_grow => try airWasmMemoryGrow(f, inst), | 1941 | .wasm_memory_grow => try airWasmMemoryGrow(f, inst), |
| ... | @@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3625 | return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{}); | 3626 | return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{}); |
| 3626 | } | 3627 | } |
| 3627 | 3628 | ||
| 3629 | fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { | ||
| 3630 | _ = inst; | ||
| 3631 | return f.fail("TODO: C backend: implement airSaveErrReturnTraceIndex", .{}); | ||
| 3632 | } | ||
| 3633 | |||
| 3628 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | 3634 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3629 | if (f.liveness.isUnused(inst)) | 3635 | if (f.liveness.isUnused(inst)) |
| 3630 | return CValue.none; | 3636 | return CValue.none; |
src/codegen/llvm.zig+19| ... | @@ -4592,6 +4592,7 @@ pub const FuncGen = struct { | ... | @@ -4592,6 +4592,7 @@ pub const FuncGen = struct { |
| 4592 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), | 4592 | .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), |
| 4593 | .err_return_trace => try self.airErrReturnTrace(inst), | 4593 | .err_return_trace => try self.airErrReturnTrace(inst), |
| 4594 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), | 4594 | .set_err_return_trace => try self.airSetErrReturnTrace(inst), |
| 4595 | .save_err_return_trace_index => try self.airSaveErrReturnTraceIndex(inst), | ||
| 4595 | 4596 | ||
| 4596 | .wrap_optional => try self.airWrapOptional(inst), | 4597 | .wrap_optional => try self.airWrapOptional(inst), |
| 4597 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), | 4598 | .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), |
| ... | @@ -6543,6 +6544,24 @@ pub const FuncGen = struct { | ... | @@ -6543,6 +6544,24 @@ pub const FuncGen = struct { |
| 6543 | return null; | 6544 | return null; |
| 6544 | } | 6545 | } |
| 6545 | 6546 | ||
| 6547 | fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | ||
| 6548 | if (self.liveness.isUnused(inst)) return null; | ||
| 6549 | |||
| 6550 | const target = self.dg.module.getTarget(); | ||
| 6551 | |||
| 6552 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 6553 | //const struct_ty = try self.resolveInst(ty_pl.ty); | ||
| 6554 | const struct_ty = self.air.getRefType(ty_pl.ty); | ||
| 6555 | const field_index = ty_pl.payload; | ||
| 6556 | |||
| 6557 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | ||
| 6558 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; | ||
| 6559 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); | ||
| 6560 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, ""); | ||
| 6561 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); | ||
| 6562 | return self.load(field_ptr, field_ptr_ty); | ||
| 6563 | } | ||
| 6564 | |||
| 6546 | fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 6565 | fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 6547 | if (self.liveness.isUnused(inst)) return null; | 6566 | if (self.liveness.isUnused(inst)) return null; |
| 6548 | 6567 |
src/print_air.zig+1| ... | @@ -197,6 +197,7 @@ const Writer = struct { | ... | @@ -197,6 +197,7 @@ const Writer = struct { |
| 197 | .unreach, | 197 | .unreach, |
| 198 | .ret_addr, | 198 | .ret_addr, |
| 199 | .frame_addr, | 199 | .frame_addr, |
| 200 | .save_err_return_trace_index, | ||
| 200 | => try w.writeNoOp(s, inst), | 201 | => try w.writeNoOp(s, inst), |
| 201 | 202 | ||
| 202 | .const_ty, | 203 | .const_ty, |