zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Mstage0/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));