Closes the byte-identity gap between selfhost/cmd/wwc/cgen.ww and
the C cgen, so a ww_ww-built binary matches the cstage-built binary
on the same input. The bootstrap fixed point was already green;
these are the bytes inside that fixed point that diverged from
what cmd/6c emits.
Slot allocation:
- local_add dedups by name (mirror cmd/6c/cgen.c:localoff). Two
`let cp: pos;` in disjoint if-branches share one slot. The
stored tnode is refreshed on each hit so a later `let m: *node`
shadowing an earlier `let m: i32` sees its own type when
emitting `m.next` — without this the N_DOT cgen fell into the
SB-symbol fallback and the linker complained about undefined
`next`.
- scan_locals dedups at frame-size time to keep the prologue SUBQ
in sync. cgfn seeds c.locals with param-name stubs before the
scan so a body's `let <param-name>` reuses the param slot, then
resets c.locals before emission so real offsets get installed.
- local_alloc (no dedup) for N_MCASE bindings: C cgen handles a
match as an expression with by-value `locals`, so two separate
matches each get fresh slots for `v`/`e`.
Per-instruction matching:
- `return;` in a void fn zeros AX (C cgen falls through to
cgexpr_int(c, 0)).
- N_INTLIT prints i64 (signed), not u64. FNV-1a's offset basis
now prints as `$-3750763034362895579`, matching `$%lld`.
- *p = strexpr push order swapped to PUSH AX / PUSH BX → POP CX
/ POP AX (cgen.c:1033-1041).
Feature port from 635818e (the half that the wwdump corpus
actually exercises):
- N_IDENT used as a value with fn type now LEAQs through
ffi_resolve, so `let fp = some_ffi_fn;` emits the C symbol.
- N_CALL on a bare ident checks local_find_node first; a local
fn-pointer dispatches as `cgexpr(callee); CALL AX` instead of
`CALL ident(SB)`.
Tests 990 probe 6 and 994 are byte-identical on mem/err/tok/smoke
+ the four selfhost main.combined.ww files. Bootstrap still
ww2 == ww3.