commit 8cdc8667f407c24d96452c66c3afe94d10ae1a5d (tree)
parent d4636dc6cc8b6cf84251996ab916c3da986f0043
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 7 Mar 2026 09:47:12 +0000
sema: port zirBitReverse (@bitReverse)
Add handler for ZIR_INST_BIT_REVERSE which was previously falling
through to default void mapping.
Comptime folding: reverses each bit in the 128-bit representation
of the integer value. Runtime fallback: emits AIR_INST_BIT_REVERSE.
Ported from Sema.zig zirBitReverse → arith.bitReverse.
Also adds AIR_INST_BIT_REVERSE to semaTypeOf ty_op group.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 49 | +++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 49 insertions(+), 0 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -602,6 +602,7 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) {
case AIR_INST_CTZ:
case AIR_INST_POPCOUNT:
case AIR_INST_BYTE_SWAP:
+ case AIR_INST_BIT_REVERSE:
case AIR_INST_ABS:
case AIR_INST_NEG:
case AIR_INST_NEG_OPTIMIZED:
@@ -1607,6 +1608,47 @@ static AirInstRef zirByteSwap(Sema* sema, SemaBlock* block, uint32_t inst) {
return semaAddInst(block, AIR_INST_BYTE_SWAP, data);
}
+// zirBitReverse: handle bit_reverse ZIR instruction (@bitReverse).
+// Ported from src/Sema.zig zirBitReverse.
+// Reverses the bit order of an integer value at comptime, or emits
+// AIR_INST_BIT_REVERSE for runtime.
+static AirInstRef zirBitReverse(Sema* sema, SemaBlock* block, uint32_t inst) {
+ ZirInstRef operand_ref = sema->code.inst_datas[inst].un_node.operand;
+ AirInstRef operand = resolveInst(sema, operand_ref);
+ TypeIndex operand_ty = semaTypeOf(sema, operand);
+
+ // Comptime folding for integer operands.
+ // Ported from Sema.zig zirBitReverse → arith.bitReverse.
+ uint64_t val_lo, val_hi;
+ bool val_neg;
+ if (isComptimeIntWide(sema, operand, &val_lo, &val_hi, &val_neg)) {
+ uint16_t bits = 0;
+ if (sema->ip->items[operand_ty].tag == IP_KEY_INT_TYPE)
+ bits = sema->ip->items[operand_ty].data.int_type.bits;
+ if (bits > 0 && bits <= 128) {
+ uint64_t r_lo = 0, r_hi = 0;
+ for (uint16_t b = 0; b < bits; b++) {
+ uint64_t word = (b >= 64) ? val_hi : val_lo;
+ uint16_t bit_pos = (uint16_t)(b % 64);
+ uint64_t bit = (word >> bit_pos) & 1;
+ uint16_t dest = (uint16_t)(bits - 1 - b);
+ uint16_t dp = (uint16_t)(dest % 64);
+ if (dest >= 64)
+ r_hi |= bit << dp;
+ else
+ r_lo |= bit << dp;
+ }
+ return internComptimeInt(sema, operand_ty, r_lo, r_hi, false);
+ }
+ }
+
+ AirInstData data;
+ memset(&data, 0, sizeof(data));
+ data.ty_op.ty_ref = AIR_REF_FROM_IP(operand_ty);
+ data.ty_op.operand = operand;
+ return semaAddInst(block, AIR_INST_BIT_REVERSE, data);
+}
+
// zirCmpEq: handle cmp_eq/cmp_neq ZIR instructions.
// Ported from src/Sema.zig zirCmpEq.
static AirInstRef zirCmpEq(
@@ -12372,6 +12414,13 @@ bool analyzeBodyInner(
i++;
continue;
+ // @bitReverse.
+ case ZIR_INST_BIT_REVERSE:
+ instMapPut(
+ &sema->inst_map, inst, zirBitReverse(sema, block, inst));
+ i++;
+ continue;
+
// @abs.
case ZIR_INST_ABS:
instMapPut(&sema->inst_map, inst, zirAbs(sema, block, inst));