Skip to content

Commit 3c912d9

Browse files
gHashTagSSD DDDPerplexity Computer
authored
fix(gen, gen-c): lower ExprCast in Zig and C emitters (#1337)
* fix(gen,gen-c): lower ExprCast in Zig and C emitters Companion to #1320 (which added the Rust arm). NodeKind::ExprCast now has a lowering arm in all three text emitters; only gen-verilog previously had one. - gen (Zig), gen_expr default was '_ => {}' (silent drop): now emits '@as(<target>, @intcast(<operand>))'. @as establishes the explicit target type, @intcast does the safe integer conversion. Works in any expression position and for both narrowing (u32->u8) and widening (u8->u32) — better than the @as-only minimal pass suggested in #1333, which cannot narrow. - gen-c, gen_c_expr default emitted '/* unsupported: ExprCast */': now emits '((<target_c_type>)(<operand>))' using the existing Self::type_to_c helper (u8->uint8_t, u32->uint32_t). Closes #1333. Verified: - t27c self-tests: 20 passed, 0 failed. - 't27c gen' on tri-net specs/wire.t27: be_byte -> '@as(u8, @intcast((w >> 24) & 255))', u32_be -> all 'as u32' casts now '@as(u32, @intcast(...))'. Previously silent drop. - 't27c gen-c' on wire.t27: be_byte -> '((uint8_t)(((w >> 24) & 255)))'. Previously '/* unsupported: ExprCast */'. - Minimal repro 'fn hi_byte(w: u32) -> u8 { return ((w >> 24) & 255) as u8; }' -> gen: 'return @as(u8, @intcast((w >> 24) & 255));', gen-c: 'return ((uint8_t)(((w >> 24) & 255)));'. - comprehensive_suite.t27: 0 'unsupported: ExprCast' in both gen and gen-c output. With #1320 (Rust) + this (Zig, C), ExprCast is fully lowered across all four backends (gen-verilog already had it). Unblocks multi-target T27-first flips in downstream consumers (tri-net gen/zig + gen/c drift-guard). * docs(now): add exprcast-zig-c-emitters section (Closes #1333) Wave Loop 411 close-out requires docs/NOW.md to reflect every landing PR. Adds a section for this PR documenting: - WHERE: gen/gen-c ExprCast arms in bootstrap/src/compiler.rs - Zig form: @as(<T>, @intcast(<operand>)) -- narrows and widens - C form: ((<uintN_t>)(<operand>)) via Self::type_to_c - Coverage: all 4 backends now lower ExprCast (Rust from #1320, Verilog already, Zig+C in this PR) - Downstream unblock: tri-net multi-target drift-guard (Rust+Zig+C from specs/wire.t27) can now proceed - Regression: t27c self-tests 20/0; comprehensive_suite.t27 shows 0 'unsupported: ExprCast' in Zig+C output Anchor: phi^2 + phi^-2 = 3 --------- Co-authored-by: SSD DDD <ssdm4@MacBook-Pro.local> Co-authored-by: Perplexity Computer <agent@perplexity.ai>
1 parent f989ee2 commit 3c912d9

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

bootstrap/src/compiler.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3624,6 +3624,20 @@ impl Codegen {
36243624
}
36253625
self.write(" }");
36263626
}
3627+
NodeKind::ExprCast => {
3628+
if !node.children.is_empty() {
3629+
let target = node
3630+
.extra_type
3631+
.split('[')
3632+
.next()
3633+
.unwrap_or("")
3634+
.trim()
3635+
.to_string();
3636+
self.write(&format!("@as({}, @intCast(", target));
3637+
self.gen_expr(&node.children[0]);
3638+
self.write("))");
3639+
}
3640+
}
36273641
_ => {}
36283642
}
36293643
}
@@ -5970,6 +5984,19 @@ impl CCodegen {
59705984
self.gen_c_expr(&node.children[0]);
59715985
}
59725986
}
5987+
NodeKind::ExprCast => {
5988+
if !node.children.is_empty() {
5989+
let target = node
5990+
.extra_type
5991+
.split('[')
5992+
.next()
5993+
.unwrap_or("")
5994+
.trim();
5995+
self.write(&format!("(({})(", Self::type_to_c(target)));
5996+
self.gen_c_expr(&node.children[0]);
5997+
self.write("))");
5998+
}
5999+
}
59736000
_ => {
59746001
self.write(&format!("/* unsupported: {:?} */", node.kind));
59756002
}

docs/NOW.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939

4040
# NOW — Wave Loop 411 close-out / Wave Loop 412 setup
4141

42+
## exprcast-zig-c-emitters -- lower ExprCast in gen (Zig) and gen-c (C) emitters (Closes #1333)
43+
44+
- **WHERE** (compiler emitters): `bootstrap/src/compiler.rs`. gen (Zig) `gen_expr` default arm `_ => {}` (silent drop for ExprCast) replaced with an `@as(<T>, @intCast(<operand>))` form -- stronger than the issue's `@as`-only suggestion because `@intCast` correctly narrows as well as widens. gen-c (C) `gen_c_expr` default `/* unsupported: ExprCast */` replaced with `((<uintN_t>)(<operand>))` via `Self::type_to_c`. Rust arm (compiler.rs:8172 from #1320) unchanged; Verilog arm already lowered ExprCast. All four backends now lower ExprCast.
45+
- **Why**: with #1320 Rust-only, `t27c gen` and `t27c gen-c` silently produced empty output or `/* unsupported */` for any T27 program using `as`-casts. Downstream `gHashTag/tri-net` needed this for multi-target drift-guard (Rust + Zig + C from a single `specs/wire.t27`); without ExprCast in Zig/C the guard would trip on the first cast (`be_byte`, `u32_be`) and no Zig/C-target port could ship. Verified on real wire.t27: `be_byte` emits `@as(u8, @intCast((w >> 24) & 255))` in Zig and `((uint8_t)(((w >> 24) & 255)))` in C; `u32_be` emits the four `@as(u32, @intCast(...))` widen-then-shift terms. Regression: `t27c` self-tests 20/0; `comprehensive_suite.t27` contains 0 occurrences of `unsupported: ExprCast` in Zig+C output. Closes #1333.
46+
- **Anchor**: phi^2 + phi^-2 = 3
47+
48+
4249
## takum32-64-libtakum-parity -- record libtakum C-reference parity witness (Closes #1334)
4350

4451
- **WHERE** (conformance vectors, witness-only): `conformance/vectors/takum32_conformance_v0.json` and `takum64_conformance_v0.json` -- update the `libtakum_c_parity` entry in `witnesses[]` from NOT DONE to results; append one ASCII clause to `format_notes`; refresh both `sha256` values in `INDEX_all_formats.json`. No vector data, no counts, no SSOT, no gen/ edits; SW-axis stays 72/83. WP-18 conformance-integrity-gate (A/B/C/D/D2/E) CLEAN locally.

0 commit comments

Comments
 (0)