| author | |
| committer | |
| log | f7e045c80619b3728c54a8aecad65ea12cbe4b75 |
| tree | f8b0454f183b0c22e9f37fdf4f7432be33f2b756 |
| parent | 6705cbd5eb8f242a567e24ec21cd3c9b82eb3343 |
| parent | a26f1768d829b28023e48333588dbf30b1f25738 |
x86_64: fix packedStore miscomp by spilling EFLAGS2 files changed, 34 insertions(+), 3 deletions(-)
src/arch/x86_64/CodeGen.zig+6-3| ... | ... | @@ -88178,12 +88178,15 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 88178 | 88178 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| 88179 | 88179 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 88180 | 88180 | |
| 88181 | const ptr_ty = self.typeOf(bin_op.lhs); | |
| 88182 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 88183 | const is_packed = ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0; | |
| 88184 | if (is_packed) try self.spillEflagsIfOccupied(); | |
| 88185 | ||
| 88181 | 88186 | const src_mcv = try self.resolveInst(bin_op.rhs); |
| 88182 | 88187 | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 88183 | const ptr_ty = self.typeOf(bin_op.lhs); | |
| 88184 | 88188 | |
| 88185 | const ptr_info = ptr_ty.ptrInfo(zcu); | |
| 88186 | if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) { | |
| 88189 | if (is_packed) { | |
| 88187 | 88190 | try self.packedStore(ptr_ty, ptr_mcv, src_mcv); |
| 88188 | 88191 | } else { |
| 88189 | 88192 | try self.store(ptr_ty, ptr_mcv, src_mcv, .{ .safety = safety }); |
test/behavior/packed-struct.zig+28| ... | ... | @@ -1349,3 +1349,31 @@ test "byte-aligned packed relocation" { |
| 1349 | 1349 | try expect(S.packed_value.x == 111); |
| 1350 | 1350 | try expect(S.packed_value.y == &S.global); |
| 1351 | 1351 | } |
| 1352 | ||
| 1353 | test "packed struct store of comparison result" { | |
| 1354 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1355 | ||
| 1356 | const S1 = packed struct { | |
| 1357 | val1: u3, | |
| 1358 | val2: u3, | |
| 1359 | }; | |
| 1360 | const S2 = packed struct { | |
| 1361 | a: bool, | |
| 1362 | b: bool, | |
| 1363 | }; | |
| 1364 | ||
| 1365 | var A: S1 = .{ .val1 = 1, .val2 = 1 }; | |
| 1366 | A.val2 += 1; | |
| 1367 | try expectEqual(1, A.val1); | |
| 1368 | try expectEqual(2, A.val2); | |
| 1369 | try expect((A.val2 & 1) != 1); | |
| 1370 | const result1: S2 = .{ .a = (A.val2 & 1) != 1, .b = (A.val1 & 1) != 1 }; | |
| 1371 | try expect(result1.a); | |
| 1372 | try expect(!result1.b); | |
| 1373 | ||
| 1374 | try expect((A.val2 == 3) == false); | |
| 1375 | try expect((A.val2 == 2) == true); | |
| 1376 | const result2: S2 = .{ .a = !(A.val2 == 3), .b = (A.val1 == 2) }; | |
| 1377 | try expect(result2.a); | |
| 1378 | try expect(!result2.b); | |
| 1379 | } |