From 16f9774d2d6f358c97637e35609dfe0fc14cb501 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 28 Feb 2022 15:25:40 +0100 Subject: [PATCH] x64: fix switch condition mir; pass more union tests --- src/arch/x86_64/CodeGen.zig | 34 ++++++++++++++++++---------------- src/arch/x86_64/Emit.zig | 6 ++++++ test/behavior/union.zig | 11 ----------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index bf5ebf4d41..45d9767320 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/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(); diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index fc43e61c17..f4d365dc4f 100644 --- a/src/arch/x86_64/Emit.zig +++ b/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(), diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 760eec53b2..07461df6eb 100644 --- a/test/behavior/union.zig +++ b/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