zig

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

commit d0e90b94e9cab14cbabab9655e2210f3c620892a (tree)
parent 2d62c61b70e5eecacc6d7988cc084b45f86f449c
Author: Motiejus <motiejus@jakstys.lt>
Date:   Sat,  7 Mar 2026 08:07:02 +0000

sema: fix zirBitCount comptime folding to use 128-bit wide values

Replace 64-bit isComptimeInt with 128-bit isComptimeIntWide for CLZ,
CTZ, and POPCOUNT comptime evaluation. Correctly handles integer types
wider than 64 bits (e.g. u128, i128).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

Diffstat:
Mstage0/sema.c | 58+++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/stage0/sema.c b/stage0/sema.c @@ -1287,41 +1287,57 @@ static AirInstRef zirBitCount( TypeIndex result_ty = ipIntern(sema->ip, key); // Comptime folding: if operand is a comptime integer, evaluate now. - int64_t val; - if (isComptimeInt(sema, operand, &val)) { - uint64_t uval = (uint64_t)val; + // Use the wide (128-bit) path to handle types wider than 64 bits. + uint64_t val_lo, val_hi; + bool val_neg; + if (isComptimeIntWide(sema, operand, &val_lo, &val_hi, &val_neg)) { uint64_t result = 0; switch (air_tag) { - case AIR_INST_CLZ: - if (uval == 0 || bits == 0) + case AIR_INST_CLZ: { + if ((val_lo == 0 && val_hi == 0) || bits == 0) { result = bits; - else { - result = 0; - uint64_t mask = (uint64_t)1 << (bits - 1); - while ((uval & mask) == 0) { + } else { + // Count leading zeros from bit (bits-1) downward. + uint16_t b = bits; + while (b > 0) { + b--; + uint64_t word = (b >= 64) ? val_hi : val_lo; + uint16_t bit_pos = b % 64; + if ((word >> bit_pos) & 1) + break; result++; - mask >>= 1; } } break; - case AIR_INST_CTZ: - if (uval == 0) + } + case AIR_INST_CTZ: { + if (val_lo == 0 && val_hi == 0) { result = bits; - else { - result = 0; - while ((uval & 1) == 0) { + } else { + // Count trailing zeros from bit 0 upward. + for (uint16_t b = 0; b < bits; b++) { + uint64_t word = (b >= 64) ? val_hi : val_lo; + uint16_t bit_pos = b % 64; + if ((word >> bit_pos) & 1) + break; result++; - uval >>= 1; } } break; - case AIR_INST_POPCOUNT: - result = 0; - while (uval != 0) { - result += uval & 1; - uval >>= 1; + } + case AIR_INST_POPCOUNT: { + // Count all set bits. + uint64_t lo = val_lo, hi = val_hi; + while (lo) { + result += lo & 1; + lo >>= 1; + } + while (hi) { + result += hi & 1; + hi >>= 1; } break; + } default: break; }