aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-28 11:39:53 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-28 11:40:25 +0100
commit57a823582cfb86a7c85c4598f5580325fb674ec4 (patch)
tree9d61aace33516dd2036ddae27630251a287adf8c /src
parent4d0c48738bbfe5f657c72f4f52fbcd4c73d4034c (diff)
downloadzig-57a823582cfb86a7c85c4598f5580325fb674ec4.tar.gz
zig-57a823582cfb86a7c85c4598f5580325fb674ec4.zip
x64: impl airGetUnionTag
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 7b828013bd..6891df0a41 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2132,8 +2132,38 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
if (self.liveness.isUnused(inst)) {
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
}
- return self.fail("TODO implement airGetUnionTag for {}", .{self.target.cpu.arch});
- // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
+
+ const tag_ty = self.air.typeOfIndex(inst);
+ const union_ty = self.air.typeOf(ty_op.operand);
+ const layout = union_ty.unionGetLayout(self.target.*);
+
+ if (layout.tag_size == 0) {
+ return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none });
+ }
+
+ // TODO reusing the operand
+ const operand = try self.resolveInst(ty_op.operand);
+ operand.freezeIfRegister(&self.register_manager);
+ defer operand.unfreezeIfRegister(&self.register_manager);
+
+ const tag_abi_size = tag_ty.abiSize(self.target.*);
+ const offset: i32 = if (layout.tag_align < layout.payload_align) @intCast(i32, layout.payload_size) else 0;
+ const dst_mcv: MCValue = blk: {
+ switch (operand) {
+ .stack_offset => |off| {
+ if (tag_abi_size <= 8) {
+ break :blk try self.copyToRegisterWithInstTracking(inst, tag_ty, .{
+ .stack_offset = off - offset,
+ });
+ }
+
+ return self.fail("TODO implement get_union_tag for ABI larger than 8 bytes and operand {}", .{operand});
+ },
+ else => return self.fail("TODO implement get_union_tag for {}", .{operand}),
+ }
+ };
+
+ return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
}
fn airClz(self: *Self, inst: Air.Inst.Index) !void {