Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions NOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Last updated: 2026-08-08

## gen-zig: runtime shift amounts get @intCast; literal shift LHS pinned (Closes #1932)

- `x << k` with a runtime amount emitted a raw u32/usize RHS (Zig wants u5 for u32) and `1 << family` left a comptime_int LHS; runtime amounts now emit `@intCast(rhs)` and a bare-literal LHS pins `@as(u32, lit)` (u64 above u32 range)
- Literal amounts untouched -- existing gens byte-identical
- tri-net corpus: both shift error classes gone (13 specs); 6 newly pass zig test end-to-end, 7 advance to their runtime layer (checked-add overflow in hash mixing, the spec-side +% idiom)
- FROZEN_HASH resealed

## gen-zig: invariant marker is a comment; untyped literal-init mutables pinned to u32 (Closes #1930)

- Empty invariant blocks emitted `@compileLog(...)` -- a hard error under `zig test`; the marker is now a comment
Expand Down
28 changes: 25 additions & 3 deletions bootstrap/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4151,9 +4151,31 @@ impl Codegen {
}
NodeKind::ExprBinary => {
if node.children.len() >= 2 {
self.gen_expr_maybe_paren(&node.children[0]);
self.write(&format!(" {} ", node.extra_op));
self.gen_expr_maybe_paren(&node.children[1]);
let op = node.extra_op.as_str();
// Zig shift RHS must be Log2(LHS-width)-typed (u5 for u32);
// a runtime u32/usize amount needs @intCast, and a bare
// integer-literal LHS (comptime_int) needs a pinned width
// once the amount is not comptime-known. Literal amounts
// are left untouched so existing gens stay byte-identical.
let shift_runtime_rhs = matches!(op, "<<" | ">>")
&& !matches!(node.children[1].kind, NodeKind::ExprLiteral);
if shift_runtime_rhs {
if let Some(ty) = Self::zig_int_literal_default_type(&node.children[0]) {
self.write(&format!("@as({}, ", ty));
self.gen_expr_maybe_paren(&node.children[0]);
self.write(")");
} else {
self.gen_expr_maybe_paren(&node.children[0]);
}
self.write(&format!(" {} ", op));
self.write("@intCast(");
self.gen_expr(&node.children[1]);
self.write(")");
} else {
self.gen_expr_maybe_paren(&node.children[0]);
self.write(&format!(" {} ", op));
self.gen_expr_maybe_paren(&node.children[1]);
}
}
}
NodeKind::ExprUnary => {
Expand Down
2 changes: 1 addition & 1 deletion bootstrap/stage0/FROZEN_HASH
Original file line number Diff line number Diff line change
@@ -1 +1 @@
34b8bad47530199936ab793a6596c8e3589a30baf5ebb159c10d57c1299062b8
f084381976dca390adfa048d03c70c62c58d335de8ac68790ccd93acd4f72caa
7 changes: 7 additions & 0 deletions docs/NOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Last updated: 2026-08-08

## gen-zig: runtime shift amounts get @intCast; literal shift LHS pinned (Closes #1932)

- `x << k` with a runtime amount emitted a raw u32/usize RHS (Zig wants u5 for u32) and `1 << family` left a comptime_int LHS; runtime amounts now emit `@intCast(rhs)` and a bare-literal LHS pins `@as(u32, lit)` (u64 above u32 range)
- Literal amounts untouched -- existing gens byte-identical
- tri-net corpus: both shift error classes gone (13 specs); 6 newly pass zig test end-to-end, 7 advance to their runtime layer (checked-add overflow in hash mixing, the spec-side +% idiom)
- FROZEN_HASH resealed

## gen-zig: invariant marker is a comment; untyped literal-init mutables pinned to u32 (Closes #1930)

- Empty invariant blocks emitted `@compileLog(...)` -- a hard error under `zig test` ("found compile log statement"), so every spec with an empty invariant failed before one test ran; the marker is now a comment
Expand Down
Loading