Commit 16f9774d2d

Jakub Konka <kubkon@jakubkonka.com>
2022-02-28 15:25:40
x64: fix switch condition mir; pass more union tests
1 parent a61ac9e
Changed files (3)
src
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -3967,36 +3967,22 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
                 .dead, .unreach => unreachable,
                 .immediate => |imm| {
                     _ = try self.addInst(.{
-                        .tag = .@"test",
+                        .tag = .xor,
                         .ops = (Mir.Ops{
                             .reg1 = registerAlias(cond_reg, abi_size),
                         }).encode(),
                         .data = .{ .imm = @intCast(u32, imm) },
                     });
-                    return self.addInst(.{
-                        .tag = .cond_jmp_eq_ne,
-                        .ops = (Mir.Ops{
-                            .flags = 0b00,
-                        }).encode(),
-                        .data = .{ .inst = undefined },
-                    });
                 },
                 .register => |reg| {
                     _ = try self.addInst(.{
-                        .tag = .@"test",
+                        .tag = .xor,
                         .ops = (Mir.Ops{
                             .reg1 = registerAlias(cond_reg, abi_size),
                             .reg2 = registerAlias(reg, abi_size),
                         }).encode(),
                         .data = undefined,
                     });
-                    return self.addInst(.{
-                        .tag = .cond_jmp_eq_ne,
-                        .ops = (Mir.Ops{
-                            .flags = 0b00,
-                        }).encode(),
-                        .data = .{ .inst = undefined },
-                    });
                 },
                 .stack_offset => {
                     if (abi_size <= 8) {
@@ -4010,6 +3996,22 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
                     return self.fail("TODO implement switch mir when case is {}", .{case});
                 },
             }
+
+            _ = try self.addInst(.{
+                .tag = .@"test",
+                .ops = (Mir.Ops{
+                    .reg1 = registerAlias(cond_reg, abi_size),
+                    .reg2 = registerAlias(cond_reg, abi_size),
+                }).encode(),
+                .data = undefined,
+            });
+            return self.addInst(.{
+                .tag = .cond_jmp_eq_ne,
+                .ops = (Mir.Ops{
+                    .flags = 0b00,
+                }).encode(),
+                .data = .{ .inst = undefined },
+            });
         },
         .stack_offset => {
             try self.spillCompareFlagsIfOccupied();
src/arch/x86_64/Emit.zig
@@ -1859,6 +1859,9 @@ fn lowerToRmEnc(
     switch (reg_or_mem) {
         .register => |src_reg| {
             const encoder = try Encoder.init(code, 4);
+            if (reg.size() == 16) {
+                encoder.prefix16BitMode();
+            }
             encoder.rex(.{
                 .w = setRexWRegister(reg) or setRexWRegister(src_reg),
                 .r = reg.isExtended(),
@@ -1902,6 +1905,9 @@ fn lowerToMrEnc(
     switch (reg_or_mem) {
         .register => |dst_reg| {
             const encoder = try Encoder.init(code, 3);
+            if (dst_reg.size() == 16) {
+                encoder.prefix16BitMode();
+            }
             encoder.rex(.{
                 .w = setRexWRegister(dst_reg) or setRexWRegister(reg),
                 .r = reg.isExtended(),
test/behavior/union.zig
@@ -171,7 +171,6 @@ test "access a member of tagged union with conflicting enum tag name" {
 }
 
 test "constant tagged union with payload" {
-    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;
 
@@ -271,7 +270,6 @@ fn testComparison() !void {
 }
 
 test "comparison between union and enum literal" {
-    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;
 
@@ -343,7 +341,6 @@ pub const PackThis = union(enum) {
 };
 
 test "constant packed 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;
 
@@ -509,7 +506,6 @@ test "update the tag value for zero-sized unions" {
 }
 
 test "union initializer generates padding only if needed" {
-    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;
 
@@ -522,7 +518,6 @@ test "union initializer generates padding only if needed" {
 }
 
 test "runtime tag name with single field" {
-    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;
 
@@ -535,7 +530,6 @@ test "runtime tag name with single field" {
 }
 
 test "method call on an empty 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;
 
@@ -599,7 +593,6 @@ test "tagged union type" {
 }
 
 test "tagged union as return value" {
-    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;
 
@@ -680,7 +673,6 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
 }
 
 test "switch on union with only 1 field" {
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
@@ -710,7 +702,6 @@ const PartialInstWithPayload = union(enum) {
 };
 
 test "union with only 1 field casted to its enum type which has enum value specified" {
-    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;
 
@@ -848,7 +839,6 @@ test "@unionInit stored to a const" {
 }
 
 test "@unionInit can modify a union type" {
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
@@ -891,7 +881,6 @@ test "@unionInit can modify a pointer value" {
 }
 
 test "union no tag with struct member" {
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO