diff options
| author | Cody Tapscott <topolarity@tapscott.me> | 2022-02-13 15:04:46 -0700 |
|---|---|---|
| committer | Cody Tapscott <topolarity@tapscott.me> | 2022-02-18 14:28:32 -0700 |
| commit | ef417f19e147ebfa46035dac5ad800723c8fed94 (patch) | |
| tree | 147e7ec763440694c208a482b38f25c08b2b9de9 /src/value.zig | |
| parent | dee96e2e2f464c3b8edc8ec3a63cd3b1860e3a9d (diff) | |
| download | zig-ef417f19e147ebfa46035dac5ad800723c8fed94.tar.gz zig-ef417f19e147ebfa46035dac5ad800723c8fed94.zip | |
stage2: Implement `@bitReverse` and `@byteSwap`
This change implements the above built-ins for Sema and the LLVM
backend. Other backends have had placeholders added for lowering.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig index 25073d3194..84167e394f 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1334,6 +1334,45 @@ pub const Value = extern union { } } + pub fn bitReverse(val: Value, ty: Type, target: Target, arena: Allocator) !Value { + assert(!val.isUndef()); + + const info = ty.intInfo(target); + + var buffer: Value.BigIntSpace = undefined; + const operand_bigint = val.toBigInt(&buffer); + + 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.bitReverse(operand_bigint, info.signedness, info.bits); + + return fromBigInt(arena, result_bigint.toConst()); + } + + pub fn byteSwap(val: Value, ty: Type, target: Target, arena: Allocator) !Value { + assert(!val.isUndef()); + + const info = ty.intInfo(target); + + // Bit count must be evenly divisible by 8 + assert(info.bits % 8 == 0); + + var buffer: Value.BigIntSpace = undefined; + const operand_bigint = val.toBigInt(&buffer); + + 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.byteSwap(operand_bigint, info.signedness, info.bits / 8); + + return fromBigInt(arena, result_bigint.toConst()); + } + /// Asserts the value is an integer and not undefined. /// Returns the number of bits the value requires to represent stored in twos complement form. pub fn intBitCountTwosComp(self: Value, target: Target) usize { |
