diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-28 11:39:53 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-28 11:40:25 +0100 |
| commit | 57a823582cfb86a7c85c4598f5580325fb674ec4 (patch) | |
| tree | 9d61aace33516dd2036ddae27630251a287adf8c /src | |
| parent | 4d0c48738bbfe5f657c72f4f52fbcd4c73d4034c (diff) | |
| download | zig-57a823582cfb86a7c85c4598f5580325fb674ec4.tar.gz zig-57a823582cfb86a7c85c4598f5580325fb674ec4.zip | |
x64: impl airGetUnionTag
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 34 |
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 { |
