x64: implement get_union_tag for register

This commit is contained in:
Jakub Konka
2022-02-28 19:49:46 +01:00
parent decc90e0e7
commit 66d28d0f20
2 changed files with 14 additions and 7 deletions

View File

@@ -1783,8 +1783,9 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
},
.register => {
// TODO reuse operand
const shift = @intCast(u6, err_ty.bitSize(self.target.*));
const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*)));
try self.shiftRegister(result.register.to64(), shift);
break :result MCValue{
.register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))),
};
@@ -2169,11 +2170,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
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) {
const offset: i32 = if (layout.tag_align < layout.payload_align) @intCast(i32, layout.payload_size) else 0;
break :blk try self.copyToRegisterWithInstTracking(inst, tag_ty, .{
.stack_offset = off - offset,
});
@@ -2181,6 +2182,17 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
return self.fail("TODO implement get_union_tag for ABI larger than 8 bytes and operand {}", .{operand});
},
.register => {
const shift: u6 = if (layout.tag_align < layout.payload_align)
@intCast(u6, layout.payload_size * 8)
else
0;
const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand);
try self.shiftRegister(result.register.to64(), shift);
break :blk MCValue{
.register = registerAlias(result.register, @intCast(u32, layout.tag_size)),
};
},
else => return self.fail("TODO implement get_union_tag for {}", .{operand}),
}
};

View File

@@ -272,7 +272,6 @@ const TheUnion = union(TheTag) {
C: i32,
};
test "cast union to tag type of union" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -292,7 +291,6 @@ test "union field access gives the enum values" {
}
test "cast tag type of union to union" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -307,7 +305,6 @@ const Value2 = union(Letter2) {
};
test "implicit cast union to its tag type" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -470,7 +467,6 @@ test "initialize global array of union" {
}
test "update the tag value for zero-sized unions" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -706,7 +702,6 @@ test "union with only 1 field casted to its enum type which has enum value speci
}
test "@enumToInt works on unions" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO