Commit Graph

7 Commits

Author SHA1 Message Date
67e27589fd selfhost: mirror nullable pointer folding for (*T | void)
C-cgen-side nullable folding landed in f4efaac. This commit catches
the selfhost cgen up so a wwstage-compiled binary produces the same
ABI for `(*T | void)`.

- cgenutil: isnullabletype(), nullableptrtag() helpers shaped to
  the selfhost cgen's AST-only world view (it doesn't carry a Type
  with a .nullable flag — it walks N_TTAGGED node lists). slotsize
  returns 8 for nullable.
- cgenexpr cgmatch: nullable arm uses pointer-vs-null discriminator
  and binds only the *T case (void has size 0).
- cgenstmt cglet: nullable target spills only AX (no tag word, no
  value-word DX/CX).
- cgenstmt cgreturn: nullable return passes AX through with no
  shuffle; bare `return;` emits AX = 0 (void encoding).

Verified end-to-end: a fn returning `(*i32 | void)` compiled by the
wwstage cgen produces the same exit code as the C-cgen build. The
995 fixed-point gate stays green — no selfhost source uses nullable
yet, so the existing tagged paths are still byte-identical.
2026-05-12 02:57:47 +09:00
2f385cec00 ascii: graduate digitval to (i32 | void); selfhost tagged ABI follow-on
ascii.digitval returns (i32 | void) instead of an i32 -1 sentinel.
Two callers updated to match-on the result (lib/ww/lex/lex.ww escape
parse, selfhost/test/smoke.ww probe 6).

`!` would have been more idiomatic at both call sites — both have
verified isxdigit beforehand — but the selfhost parser doesn't yet
recognize postfix `!`/`?`, so using them in bootstrap-bound code
breaks the 993/995 byte-identity gates. Match is fine for now.

Selfhost cgen follow-on for the 8-byte-rounded tagged-union ABI
(landed in 1e2f55a for the C side):
- cgenutil.slotsize: tagged size = 8 (tag) + max(payload), padded to
  8-byte multiple. Was hardcoded 24.
- cgendecl prologue: spill size/8 arg registers, not always 3.
- cgenstmt cglet tagged-call path: spill the CX value-word only when
  the slot is >16 bytes.

All three were emitting 3-register patterns appropriate to (T | str)
sized unions and overflowing the new 16-byte (i32 | void) slots.
2026-05-12 02:10:10 +09:00
fa070b6d07 wcc: tagged-union foundations (never, void, flatten, exhaust)
- `never` bottom type: TY_NEVER, assignable to anything; size 0.
- Type-set normalization for N_TTAGGED in resolve_type:
  - flatten nested anonymous (A|B)|C → (A|B|C); named aliases stay
    nominal (not flattened through)
  - dedup duplicates (NAMED pointer-id; others structural)
  - drop `never` variants
  - collapse single-element set: (T|never) → T, (T|T) → T
- Match exhaustiveness: error when a variant is unhandled and no
  default arm covers it. Multi-pattern `case T1 | T2 =>` counts
  each alt.
- (T | void) optionals: bare `return;` from a tagged-union-returning
  fn emits the void variant's tag (payload undefined; void size 0).

selfhost mirrored: TY_NEVER constant + tynever in tctx + seedprim
entry; voidvariantindex helper; cgreturn bare-return handling.
2026-05-12 01:31:35 +09:00
c5f30f2fce ww: cgen trap batch (def-str field, chained-ptr write, scalar+str tuple ABI) 2026-05-11 20:49:21 +09:00
6219a47c6f ww: hare-feature batch (_, const, [_]T, ..., size/offset, assert, for-else) 2026-05-11 19:38:12 +09:00
97ca76d2bb selfhost: drop snake_case locals in dyn/dynout/obj + w6a + cgen + ww driver 2026-05-11 16:33:02 +09:00
1e7be36577 wcc/cgen: drop underscore from cgen_*.ww filenames 2026-05-11 16:19:46 +09:00