aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-10-23 18:53:28 +0200
committerjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-11-01 20:43:27 +0100
commit8a022d9c92e2a21b3329da1b01151d2b14f0b1da (patch)
tree8627ebe01a779d05f09ea56a42e051753df5c9a3 /src
parent3ecec50f0c530760653a73194fa3651b16647ef9 (diff)
downloadzig-8a022d9c92e2a21b3329da1b01151d2b14f0b1da.tar.gz
zig-8a022d9c92e2a21b3329da1b01151d2b14f0b1da.zip
stage2 AArch64: implement wrap_errunion_{err,payload}
Diffstat (limited to 'src')
-rw-r--r--src/arch/aarch64/CodeGen.zig33
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 });
}