Commit fd788c4
feat(codegen): real body lowering for field writers + width-exact scalar accesses (climb Step 2)
Lowers a single-statement field writer
region.set $p .field, <value>; -> [local.get p, <push value>, <store>{offset}]
to a real typed store + access-site (value = a matching-typed scalar param, a
bool, or a numeric literal; compound expressions fall back to the stub). Extends
the Step-1 reader to every scalar width and makes BOTH directions width-exact.
Op set: add I64/F64 load+store and the sub-width integer accesses
I32Load8{U,S}/I32Load16{U,S}/I32Store8/I32Store16, so a 1- or 2-byte field uses a
1- or 2-byte access (sign-extending i8/i16, zero-extending u8/u16/bool) — never a
4-byte i32 access that would touch the neighbour's bytes.
Hardening from an adversarial review of the diff (9 confirmed findings; the 5 in
this change's own code are fixed here):
* narrow fields lower to store8/store16 + load8/load16, not i32.store/i32.load
(was corrupting/over-reading adjacent packed fields — validated clean, so the
verifier could not catch it);
* a region-handle param is no longer accepted as a stored scalar value
(pointer-into-scalar type confusion) -> falls back to the stub;
* an out-of-width integer literal no longer silently wraps (4294967296 as i32),
and an f32-overflowing float literal no longer becomes f32.const inf -> stub;
* a synthesised memory (module declares none) is now sized to cover the accessed
region, so a real offset cannot point past linear memory and trap.
Verification:
* tests/execute_lowering.rs - NEW Tier-1 differential EXECUTION gate: runs the
lowered module in-process (wasmi, pure-Rust, no system engine) and asserts
set->get round-trips every scalar width (incl. narrow sign/zero-extension)
and that narrow stores do not clobber neighbours. Proven non-vacuous: it fails
if the narrow-width bug is reintroduced. Turns 'the op widths argue
correctness' into 'the engine demonstrates it'.
* corpus.rs - writer + per-defect regression tests; 6/6 example corpus stays
green; every emitted module still passes wasmparser::Validator + L2/L7/L10.
The 3 pre-existing parser panics the review also surfaced (div-by-zero / integer
overflow in the array-size evaluator + compute_region_byte_size, violating the
never-panic contract) are out of scope here -> separate hardening PR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent c369d0d commit fd788c4
6 files changed
Lines changed: 868 additions & 30 deletions
File tree
- crates/typed-wasm-codegen
- src
- tests
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
191 | 191 | | |
192 | 192 | | |
193 | 193 | | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
194 | 222 | | |
195 | 223 | | |
196 | 224 | | |
197 | 225 | | |
198 | 226 | | |
199 | 227 | | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
200 | 234 | | |
201 | 235 | | |
202 | 236 | | |
| |||
338 | 372 | | |
339 | 373 | | |
340 | 374 | | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
341 | 383 | | |
342 | 384 | | |
| 385 | + | |
| 386 | + | |
343 | 387 | | |
344 | 388 | | |
345 | 389 | | |
| |||
0 commit comments