From 724d75363855176aa5e6b3d9bcd1656e2cc1f6a6 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Wed, 14 Sep 2022 13:49:54 -0700 Subject: stage2: Add `.save_err_return_trace_index` AIR op 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. --- src/codegen/c.zig | 6 ++++++ src/codegen/llvm.zig | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 072091d9b2..d6584d75ae 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1935,6 +1935,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), .err_return_trace => try airErrReturnTrace(f, inst), .set_err_return_trace => try airSetErrReturnTrace(f, inst), + .save_err_return_trace_index => try airSaveErrReturnTraceIndex(f, inst), .wasm_memory_size => try airWasmMemorySize(f, inst), .wasm_memory_grow => try airWasmMemoryGrow(f, inst), @@ -3625,6 +3626,11 @@ fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{}); } +fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { + _ = inst; + return f.fail("TODO: C backend: implement airSaveErrReturnTraceIndex", .{}); +} + fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b0d1588007..3ebca13c20 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4592,6 +4592,7 @@ pub const FuncGen = struct { .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), .err_return_trace => try self.airErrReturnTrace(inst), .set_err_return_trace => try self.airSetErrReturnTrace(inst), + .save_err_return_trace_index => try self.airSaveErrReturnTraceIndex(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -6543,6 +6544,24 @@ pub const FuncGen = struct { return null; } + fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + if (self.liveness.isUnused(inst)) return null; + + const target = self.dg.module.getTarget(); + + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + //const struct_ty = try self.resolveInst(ty_pl.ty); + const struct_ty = self.air.getRefType(ty_pl.ty); + const field_index = ty_pl.payload; + + var ptr_ty_buf: Type.Payload.Pointer = undefined; + const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, ""); + const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); + return self.load(field_ptr, field_ptr_ty); + } + fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { if (self.liveness.isUnused(inst)) return null; -- cgit v1.2.3