authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 15:44:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 15:44:09-07:00
log4b2d7a9c67760aa9a81bfd364ac0d88cbb9737f1
tree2b3b5a2faf3a6c335d032c05bd7884e371ebabae
parentf3147de7a28767a27406355fd2d93d1bbcec9437

stage2: implement comptime bitwise nand


5 files changed, 48 insertions(+), 36 deletions(-)

lib/std/math/big/int.zig+3
......@@ -566,6 +566,7 @@ pub const Mutable = struct {
566566 llor(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
567567 r.len = b.limbs.len;
568568 }
569 r.positive = a.positive or b.positive;
569570 }
570571
571572 /// r = a & b
......@@ -580,6 +581,7 @@ pub const Mutable = struct {
580581 lland(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
581582 r.normalize(a.limbs.len);
582583 }
584 r.positive = a.positive and b.positive;
583585 }
584586
585587 /// r = a ^ b
......@@ -594,6 +596,7 @@ pub const Mutable = struct {
594596 llxor(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]);
595597 r.normalize(b.limbs.len);
596598 }
599 r.positive = a.positive or b.positive;
597600 }
598601
599602 /// rma may alias x or y.
src/Sema.zig+1-1
......@@ -7871,7 +7871,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
78717871 .Add => try stored_val.numberAddWrap(operand_val, operand_ty, sema.arena, target),
78727872 .Sub => try stored_val.numberSubWrap(operand_val, operand_ty, sema.arena, target),
78737873 .And => try stored_val.bitwiseAnd (operand_val, sema.arena),
7874 .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena),
7874 .Nand => try stored_val.bitwiseNand (operand_val, operand_ty, sema.arena, target),
78757875 .Or => try stored_val.bitwiseOr (operand_val, sema.arena),
78767876 .Xor => try stored_val.bitwiseXor (operand_val, sema.arena),
78777877 .Max => try stored_val.numberMax (operand_val, sema.arena),
src/value.zig+9-4
......@@ -1690,12 +1690,17 @@ pub const Value = extern union {
16901690 }
16911691
16921692 /// operands must be integers; handles undefined.
1693 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: *Allocator) !Value {
1693 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: *Allocator, target: Target) !Value {
16941694 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
16951695
1696 _ = ty;
1697 _ = arena;
1698 @panic("TODO comptime bitwise NAND");
1696 const anded = try bitwiseAnd(lhs, rhs, arena);
1697
1698 const all_ones = if (ty.isSignedInt())
1699 try Value.Tag.int_i64.create(arena, -1)
1700 else
1701 try ty.maxInt(arena, target);
1702
1703 return bitwiseXor(anded, all_ones, arena);
16991704 }
17001705
17011706 /// operands must be integers; handles undefined.
test/behavior/atomics.zig+28
......@@ -167,3 +167,31 @@ fn testAtomicRmwFloat() !void {
167167 _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
168168 try expect(x == 4);
169169}
170
171test "atomicrmw with ints" {
172 try testAtomicRmwInt();
173 comptime try testAtomicRmwInt();
174}
175
176fn testAtomicRmwInt() !void {
177 var x: u8 = 1;
178 var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
179 try expect(x == 3 and res == 1);
180 _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
181 try expect(x == 6);
182 _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
183 try expect(x == 5);
184 _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
185 try expect(x == 4);
186 _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
187 try expect(x == 0xfb);
188 _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
189 try expect(x == 0xff);
190 _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
191 try expect(x == 0xfd);
192
193 _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
194 try expect(x == 0xfd);
195 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
196 try expect(x == 1);
197}
test/behavior/atomics_stage1.zig+7-31
......@@ -3,39 +3,15 @@ const expect = std.testing.expect;
33const expectEqual = std.testing.expectEqual;
44const builtin = @import("builtin");
55
6test "atomicrmw with ints" {
7 try testAtomicRmwInt();
8 comptime try testAtomicRmwInt();
9}
10
11fn testAtomicRmwInt() !void {
12 var x: u8 = 1;
13 var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
14 try expect(x == 3 and res == 1);
15 _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
16 try expect(x == 6);
17 _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
18 try expect(x == 5);
19 _ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
20 try expect(x == 4);
21 _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
22 try expect(x == 0xfb);
23 _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
24 try expect(x == 0xff);
25 _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
26 try expect(x == 0xfd);
27
28 _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
29 try expect(x == 0xfd);
30 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
31 try expect(x == 1);
32}
33
346test "atomics with different types" {
357 try testAtomicsWithType(bool, true, false);
36 inline for (.{ u1, i4, u5, i15, u24 }) |T| {
37 try testAtomicsWithType(T, 0, 1);
38 }
8
9 try testAtomicsWithType(u1, 0, 1);
10 try testAtomicsWithType(i4, 0, 1);
11 try testAtomicsWithType(u5, 0, 1);
12 try testAtomicsWithType(i15, 0, 1);
13 try testAtomicsWithType(u24, 0, 1);
14
3915 try testAtomicsWithType(u0, 0, 0);
4016 try testAtomicsWithType(i0, 0, 0);
4117}