aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorCody Tapscott <topolarity@tapscott.me>2022-02-13 15:04:46 -0700
committerCody Tapscott <topolarity@tapscott.me>2022-02-18 14:28:32 -0700
commitef417f19e147ebfa46035dac5ad800723c8fed94 (patch)
tree147e7ec763440694c208a482b38f25c08b2b9de9 /src/value.zig
parentdee96e2e2f464c3b8edc8ec3a63cd3b1860e3a9d (diff)
downloadzig-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.zig39
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 {