authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-23 21:46:46-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-23 21:46:46-04:00
logf7e045c80619b3728c54a8aecad65ea12cbe4b75
treef8b0454f183b0c22e9f37fdf4f7432be33f2b756
parent6705cbd5eb8f242a567e24ec21cd3c9b82eb3343
parenta26f1768d829b28023e48333588dbf30b1f25738

Merge pull request #23256 from xtexx/fix-gh-20113

x86_64: fix packedStore miscomp by spilling EFLAGS

2 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,12 +88178,15 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
88178 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });88178 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
88179 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);88179 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
8818088180
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 const src_mcv = try self.resolveInst(bin_op.rhs);88186 const src_mcv = try self.resolveInst(bin_op.rhs);
88182 const ptr_mcv = try self.resolveInst(bin_op.lhs);88187 const ptr_mcv = try self.resolveInst(bin_op.lhs);
88183 const ptr_ty = self.typeOf(bin_op.lhs);
8818488188
88185 const ptr_info = ptr_ty.ptrInfo(zcu);88189 if (is_packed) {
88186 if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {
88187 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);88190 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
88188 } else {88191 } else {
88189 try self.store(ptr_ty, ptr_mcv, src_mcv, .{ .safety = safety });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,3 +1349,31 @@ test "byte-aligned packed relocation" {
1349 try expect(S.packed_value.x == 111);1349 try expect(S.packed_value.x == 111);
1350 try expect(S.packed_value.y == &S.global);1350 try expect(S.packed_value.y == &S.global);
1351}1351}
1352
1353test "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}