| author | |
| committer | |
| log | 7199a86b9776a0d44e9fceb98ac6567eb6db3d6e |
| tree | d270b1c96bb461862ab944d3b5659969dd14505f |
| parent | fe8bdf6f049e59cffe0033baa4d1738a64fd21cf |
x86_64: fix packedStore miscomp by spilling EFLAGS2 files changed, 34 insertions(+), 3 deletions(-)
src/arch/x86_64/CodeGen.zig+6-3| ... | ... | @@ -88110,12 +88110,15 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 88110 | 88110 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| 88111 | 88111 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 88112 | 88112 | |
| 88113 | const ptr_ty = self.typeOf(bin_op.lhs); | |
| 88114 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 88115 | const is_packed = ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0; | |
| 88116 | if (is_packed) try self.spillEflagsIfOccupied(); | |
| 88117 | ||
| 88113 | 88118 | const src_mcv = try self.resolveInst(bin_op.rhs); |
| 88114 | 88119 | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 88115 | const ptr_ty = self.typeOf(bin_op.lhs); | |
| 88116 | 88120 | |
| 88117 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 88118 | if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) { | |
| 88121 | if (is_packed) { | |
| 88119 | 88122 | try self.packedStore(ptr_ty, ptr_mcv, src_mcv); |
| 88120 | 88123 | } else { |
| 88121 | 88124 | try self.store(ptr_ty, ptr_mcv, src_mcv, .{ .safety = safety }); |
test/behavior/packed-struct.zig+28| ... | ... | @@ -1363,3 +1363,31 @@ test "byte-aligned packed relocation" { |
| 1363 | 1363 | try expect(S.packed_value.x == 111); |
| 1364 | 1364 | try expect(S.packed_value.y == &S.global); |
| 1365 | 1365 | } |
| 1366 | ||
| 1367 | test "packed struct store of comparison result" { | |
| 1368 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1369 | ||
| 1370 | const S1 = packed struct { | |
| 1371 | val1: u3, | |
| 1372 | val2: u3, | |
| 1373 | }; | |
| 1374 | const S2 = packed struct { | |
| 1375 | a: bool, | |
| 1376 | b: bool, | |
| 1377 | }; | |
| 1378 | ||
| 1379 | var A: S1 = .{ .val1 = 1, .val2 = 1 }; | |
| 1380 | A.val2 += 1; | |
| 1381 | try expectEqual(1, A.val1); | |
| 1382 | try expectEqual(2, A.val2); | |
| 1383 | try expect((A.val2 & 1) != 1); | |
| 1384 | const result1: S2 = .{ .a = (A.val2 & 1) != 1, .b = (A.val1 & 1) != 1 }; | |
| 1385 | try expect(result1.a); | |
| 1386 | try expect(!result1.b); | |
| 1387 | ||
| 1388 | try expect((A.val2 == 3) == false); | |
| 1389 | try expect((A.val2 == 2) == true); | |
| 1390 | const result2: S2 = .{ .a = !(A.val2 == 3), .b = (A.val1 == 2) }; | |
| 1391 | try expect(result2.a); | |
| 1392 | try expect(!result2.b); | |
| 1393 | } |