x64: fix switch condition mir; pass more union tests

This commit is contained in:
Jakub Konka 2022-02-28 15:25:40 +01:00
parent a61ac9ecbf
commit 16f9774d2d
3 changed files with 24 additions and 27 deletions

View File

@ -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();

View File

@ -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(),

View File

@ -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