From 4b2d7a9c67760aa9a81bfd364ac0d88cbb9737f1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 20 Sep 2021 15:44:09 -0700 Subject: [PATCH] stage2: implement comptime bitwise nand --- lib/std/math/big/int.zig | 3 +++ src/Sema.zig | 2 +- src/value.zig | 13 +++++++---- test/behavior/atomics.zig | 28 +++++++++++++++++++++++ test/behavior/atomics_stage1.zig | 38 ++++++-------------------------- 5 files changed, 48 insertions(+), 36 deletions(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 9efd4d5752..d223d3135f 100644 --- a/lib/std/math/big/int.zig +++ b/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. diff --git a/src/Sema.zig b/src/Sema.zig index 72dc25a58a..f53dbea90c 100644 --- a/src/Sema.zig +++ b/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), diff --git a/src/value.zig b/src/value.zig index 177359d652..934aab7bc8 100644 --- a/src/value.zig +++ b/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. diff --git a/test/behavior/atomics.zig b/test/behavior/atomics.zig index 311fb4b3b2..14e0933c52 100644 --- a/test/behavior/atomics.zig +++ b/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); +} diff --git a/test/behavior/atomics_stage1.zig b/test/behavior/atomics_stage1.zig index 424f33b403..f37d1dc8c1 100644 --- a/test/behavior/atomics_stage1.zig +++ b/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); }