Commit 7199a86b97

Jacob Young <jacobly0@users.noreply.github.com>
2025-03-24 02:46:46
Merge pull request #23256 from xtexx/fix-gh-20113
x86_64: fix packedStore miscomp by spilling EFLAGS
1 parent fe8bdf6
Changed files (2)
src
arch
test
src/arch/x86_64/CodeGen.zig
@@ -88110,12 +88110,15 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
         const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
         defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
 
+        const ptr_ty = self.typeOf(bin_op.lhs);
+        const ptr_info = ptr_ty.ptrInfo(zcu);
+        const is_packed = ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0;
+        if (is_packed) try self.spillEflagsIfOccupied();
+
         const src_mcv = try self.resolveInst(bin_op.rhs);
         const ptr_mcv = try self.resolveInst(bin_op.lhs);
-        const ptr_ty = self.typeOf(bin_op.lhs);
 
-        const ptr_info = ptr_ty.ptrInfo(zcu);
-        if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {
+        if (is_packed) {
             try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
         } else {
             try self.store(ptr_ty, ptr_mcv, src_mcv, .{ .safety = safety });
test/behavior/packed-struct.zig
@@ -1363,3 +1363,31 @@ test "byte-aligned packed relocation" {
     try expect(S.packed_value.x == 111);
     try expect(S.packed_value.y == &S.global);
 }
+
+test "packed struct store of comparison result" {
+    if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+
+    const S1 = packed struct {
+        val1: u3,
+        val2: u3,
+    };
+    const S2 = packed struct {
+        a: bool,
+        b: bool,
+    };
+
+    var A: S1 = .{ .val1 = 1, .val2 = 1 };
+    A.val2 += 1;
+    try expectEqual(1, A.val1);
+    try expectEqual(2, A.val2);
+    try expect((A.val2 & 1) != 1);
+    const result1: S2 = .{ .a = (A.val2 & 1) != 1, .b = (A.val1 & 1) != 1 };
+    try expect(result1.a);
+    try expect(!result1.b);
+
+    try expect((A.val2 == 3) == false);
+    try expect((A.val2 == 2) == true);
+    const result2: S2 = .{ .a = !(A.val2 == 3), .b = (A.val1 == 2) };
+    try expect(result2.a);
+    try expect(!result2.b);
+}