diff options
| author | Robin Voetter <robin@voetter.nl> | 2021-10-16 14:47:55 +0200 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2021-10-17 20:33:04 +0200 |
| commit | 9336a87452eda87c19cb707484d0b6dfb4140b57 (patch) | |
| tree | 72d50163e2ad1389d5752de0e841b8f68755f3d5 /src/value.zig | |
| parent | 6a3659c4e005d9730fb824b77b416ef33200dbfe (diff) | |
| download | zig-9336a87452eda87c19cb707484d0b6dfb4140b57.tar.gz zig-9336a87452eda87c19cb707484d0b6dfb4140b57.zip | |
stage2: bitNot
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig index 127c6c27b4..030ee8f783 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2081,6 +2081,32 @@ pub const Value = extern union { }; } + /// operands must be integers; handles undefined. + pub fn bitwiseNot(val: Value, ty: Type, arena: *Allocator, target: Target) !Value { + if (val.isUndef()) return Value.initTag(.undef); + + const info = ty.intInfo(target); + + // TODO is this a performance issue? maybe we should try the operation without + // resorting to BigInt first. + var val_space: Value.BigIntSpace = undefined; + const val_bigint = val.toBigInt(&val_space); + const limbs = try arena.alloc( + std.math.big.Limb, + std.math.big.int.calcTwosCompLimbCount(info.bits), + ); + + var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; + result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits); + const result_limbs = result_bigint.limbs[0..result_bigint.len]; + + if (result_bigint.positive) { + return Value.Tag.int_big_positive.create(arena, result_limbs); + } else { + return Value.Tag.int_big_negative.create(arena, result_limbs); + } + } + /// operands must be integers; handles undefined. pub fn bitwiseAnd(lhs: Value, rhs: Value, arena: *Allocator) !Value { if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef); |
