Commit 4b2d7a9c67

Andrew Kelley <andrew@ziglang.org>
2021-09-21 00:44:09
stage2: implement comptime bitwise nand
1 parent f3147de
Changed files (5)
lib/std/math/big/int.zig
@@ -566,6 +566,7 @@ pub const Mutable = struct {
             llor(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
             r.len = b.limbs.len;
         }
+        r.positive = a.positive or b.positive;
     }
 
     /// r = a & b
@@ -580,6 +581,7 @@ pub const Mutable = struct {
             lland(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
             r.normalize(a.limbs.len);
         }
+        r.positive = a.positive and b.positive;
     }
 
     /// r = a ^ b
@@ -594,6 +596,7 @@ pub const Mutable = struct {
             llxor(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
             r.normalize(b.limbs.len);
         }
+        r.positive = a.positive or b.positive;
     }
 
     /// rma may alias x or y.
src/Sema.zig
@@ -7871,7 +7871,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
                 .Add  => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target),
                 .Sub  => try stored_val.numberSubWrap(operand_val, operand_ty, sema.arena, target),
                 .And  => try stored_val.bitwiseAnd   (operand_val,             sema.arena),
-                .Nand => try stored_val.bitwiseNand  (operand_val, operand_ty, sema.arena),
+                .Nand => try stored_val.bitwiseNand  (operand_val, operand_ty, sema.arena, target),
                 .Or   => try stored_val.bitwiseOr    (operand_val,             sema.arena),
                 .Xor  => try stored_val.bitwiseXor   (operand_val,             sema.arena),
                 .Max  => try stored_val.numberMax    (operand_val,             sema.arena),
src/value.zig
@@ -1690,12 +1690,17 @@ pub const Value = extern union {
     }
 
     /// operands must be integers; handles undefined. 
-    pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: *Allocator) !Value {
+    pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: *Allocator, target: Target) !Value {
         if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
 
-        _ = ty;
-        _ = arena;
-        @panic("TODO comptime bitwise NAND");
+        const anded = try bitwiseAnd(lhs, rhs, arena);
+
+        const all_ones = if (ty.isSignedInt())
+            try Value.Tag.int_i64.create(arena, -1)
+        else
+            try ty.maxInt(arena, target);
+
+        return bitwiseXor(anded, all_ones, arena);
     }
 
     /// operands must be integers; handles undefined. 
test/behavior/atomics.zig
@@ -167,3 +167,31 @@ fn testAtomicRmwFloat() !void {
     _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
     try expect(x == 4);
 }
+
+test "atomicrmw with ints" {
+    try testAtomicRmwInt();
+    comptime try testAtomicRmwInt();
+}
+
+fn testAtomicRmwInt() !void {
+    var x: u8 = 1;
+    var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
+    try expect(x == 3 and res == 1);
+    _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
+    try expect(x == 6);
+    _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
+    try expect(x == 5);
+    _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
+    try expect(x == 4);
+    _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
+    try expect(x == 0xfb);
+    _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
+    try expect(x == 0xff);
+    _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
+    try expect(x == 0xfd);
+
+    _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
+    try expect(x == 0xfd);
+    _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
+    try expect(x == 1);
+}
test/behavior/atomics_stage1.zig
@@ -3,39 +3,15 @@ const expect = std.testing.expect;
 const expectEqual = std.testing.expectEqual;
 const builtin = @import("builtin");
 
-test "atomicrmw with ints" {
-    try testAtomicRmwInt();
-    comptime try testAtomicRmwInt();
-}
-
-fn testAtomicRmwInt() !void {
-    var x: u8 = 1;
-    var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
-    try expect(x == 3 and res == 1);
-    _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
-    try expect(x == 6);
-    _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
-    try expect(x == 5);
-    _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
-    try expect(x == 4);
-    _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
-    try expect(x == 0xfb);
-    _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
-    try expect(x == 0xff);
-    _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
-    try expect(x == 0xfd);
-
-    _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
-    try expect(x == 0xfd);
-    _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
-    try expect(x == 1);
-}
-
 test "atomics with different types" {
     try testAtomicsWithType(bool, true, false);
-    inline for (.{ u1, i4, u5, i15, u24 }) |T| {
-        try testAtomicsWithType(T, 0, 1);
-    }
+
+    try testAtomicsWithType(u1, 0, 1);
+    try testAtomicsWithType(i4, 0, 1);
+    try testAtomicsWithType(u5, 0, 1);
+    try testAtomicsWithType(i15, 0, 1);
+    try testAtomicsWithType(u24, 0, 1);
+
     try testAtomicsWithType(u0, 0, 0);
     try testAtomicsWithType(i0, 0, 0);
 }