diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 12d6f22bff..3620995514 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/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}), } }; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 4d2e045e4b..4deadc1a59 100644 --- a/test/behavior/union.zig +++ b/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