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:
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;