Commit 66d28d0f20

Jakub Konka <kubkon@jakubkonka.com>
2022-02-28 19:49:46
x64: implement get_union_tag for register
1 parent decc90e
Changed files (2)
src
arch
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -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}),
         }
     };
test/behavior/union.zig
@@ -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