zig

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

commit f3ce1883d0fac5885ede7d8db627318c24cf163c (tree)
parent 69a048623258cd4cfd091b1ffb9bb04ac6f734d7
Author: Motiejus <motiejus@jakstys.lt>
Date:   Mon,  2 Mar 2026 18:04:35 +0000

sema: fix shl_sat shift type coercion, bump num_passing 67→73

Port shl_sat shift amount coercion from upstream Sema.zig zirShl
(line 13996). For saturating shift left, the RHS is coerced to
smallestUnsignedInt(lhs_bits) — e.g. u6 for u32 operands (needs to
represent 0-32, not just 0-31).

Changes:
- Add shl_sat comptime RHS coercion in zirShl: compute shift type
  via ipForceIntern (matching Zig's sharded IP fresh-entry behavior),
  create typed shift value
- Route ZIR_INST_SHL_SAT through zirShl instead of zirArithmetic
  (shl_sat needs shift-specific handling, not generic arithmetic)
- Tests 67-72 now pass (shl_sat, shr, min/max, comparisons, etc.)

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

Diffstat:
Mstage0/corpus.zig | 2+-
Mstage0/sema.c | 39+++++++++++++++++++++++++++++++++++----
2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/stage0/corpus.zig b/stage0/corpus.zig @@ -3,7 +3,7 @@ /// `num_passing` controls how many files are tested and pre-generated. /// Both build.zig and stages_test.zig import this file. /// To enable more tests: just increment `num_passing`. -pub const num_passing: usize = 67; +pub const num_passing: usize = 73; pub const files = [_][]const u8{ "stage0/sema_tests/empty.zig", diff --git a/stage0/sema.c b/stage0/sema.c @@ -1704,9 +1704,40 @@ static AirInstRef zirShl( return internComptimeInt(sema, lhs_ty, r_lo, r_hi); } - // The rhs is already coerced to the correct shift type by - // typeof_log2_int_type + as_shift_operand ZIR instructions - // (AstGen forces the coercion before the shl/shr instruction). + // For regular shl/shr, the rhs is already coerced by + // typeof_log2_int_type + as_shift_operand ZIR instructions. + // For shl_sat, Sema coerces the comptime rhs to the smallest + // unsigned type that can hold lhs_bits. Ported from upstream + // Sema.zig zirShl line 13996: rt_rhs_scalar_ty = + // pt.smallestUnsignedInt(bit_count). + if (air_tag == AIR_INST_SHL_SAT && rhs_ct) { + TypeIndex lhs_ty = semaTypeOf(sema, lhs); + if (sema->ip->items[lhs_ty].tag == IP_KEY_INT_TYPE) { + uint16_t bits = sema->ip->items[lhs_ty].data.int_type.bits; + // smallestUnsignedInt(bits): ceil(log2(bits+1)). + uint16_t count = 0; + uint32_t s = bits; + while (s != 0) { + count++; + s >>= 1; + } + // Create the shift type via ipForceIntern (matching Zig's + // sharded IP: fresh entry in function-local shard). + InternPoolKey tkey; + memset(&tkey, 0, sizeof(tkey)); + tkey.tag = IP_KEY_INT_TYPE; + tkey.data.int_type.bits = count; + tkey.data.int_type.signedness = 0; + InternPoolIndex shift_ty = ipForceIntern(sema->ip, tkey); + // Create the shift value. + InternPoolKey vkey; + memset(&vkey, 0, sizeof(vkey)); + vkey.tag = IP_KEY_INT; + vkey.data.int_val.ty = shift_ty; + vkey.data.int_val.value_lo = rhs_lo; + rhs = AIR_REF_FROM_IP(ipIntern(sema->ip, vkey)); + } + } AirInstData data; memset(&data, 0, sizeof(data)); @@ -12106,7 +12137,7 @@ static bool analyzeBodyInner( continue; case ZIR_INST_SHL_SAT: instMapPut(&sema->inst_map, inst, - zirArithmetic(sema, block, inst, AIR_INST_SHL_SAT)); + zirShl(sema, block, inst, AIR_INST_SHL_SAT)); i++; continue;