diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-10-23 18:53:28 +0200 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-11-01 20:43:27 +0100 |
| commit | 8a022d9c92e2a21b3329da1b01151d2b14f0b1da (patch) | |
| tree | 8627ebe01a779d05f09ea56a42e051753df5c9a3 /src | |
| parent | 3ecec50f0c530760653a73194fa3651b16647ef9 (diff) | |
| download | zig-8a022d9c92e2a21b3329da1b01151d2b14f0b1da.tar.gz zig-8a022d9c92e2a21b3329da1b01151d2b14f0b1da.zip | |
stage2 AArch64: implement wrap_errunion_{err,payload}
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 13fd5bcd09..99c064b551 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -3009,7 +3009,23 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { /// T to E!T fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch}); + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const error_union_ty = self.air.getRefType(ty_op.ty); + const error_ty = error_union_ty.errorUnionSet(); + const payload_ty = error_union_ty.errorUnionPayload(); + const operand = try self.resolveInst(ty_op.operand); + if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; + + const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); + const abi_align = error_union_ty.abiAlignment(self.target.*); + const stack_offset = try self.allocMem(abi_size, abi_align, inst); + const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); + const err_off = errUnionErrorOffset(payload_ty, self.target.*); + try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand); + try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 }); + + break :result MCValue{ .stack_offset = stack_offset }; + }; return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } @@ -3018,11 +3034,20 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { const error_union_ty = self.air.getRefType(ty_op.ty); + const error_ty = error_union_ty.errorUnionSet(); const payload_ty = error_union_ty.errorUnionPayload(); - const mcv = try self.resolveInst(ty_op.operand); - if (!payload_ty.hasRuntimeBits()) break :result mcv; + const operand = try self.resolveInst(ty_op.operand); + if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand; + + const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); + const abi_align = error_union_ty.abiAlignment(self.target.*); + const stack_offset = try self.allocMem(abi_size, abi_align, inst); + const payload_off = errUnionPayloadOffset(payload_ty, self.target.*); + const err_off = errUnionErrorOffset(payload_ty, self.target.*); + try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand); + try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef); - return self.fail("TODO implement wrap errunion error for non-empty payloads", .{}); + break :result MCValue{ .stack_offset = stack_offset }; }; return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } |
