Files
ww/selfhost/CLAUDE.md

2.2 KiB

selfhost — ww reimplementation of the toolchain (wcc, w6c, w6a, w6l, ww, wwdump). Compiled by the C bootstrap (../cmd/); the goal is to eventually compile itself.

Identifiers: Plan 9 style. lowercase, words run together (newbuf, tcpsock, parsefile). No snake_case.

Syntax and idioms: Hare-shaped. Trailing ;, = after fn/type signatures, export for visibility, match/?/! for tagged-union errors. Consult ref/hare/ for canonical signatures and error-handling patterns before inventing your own.

The C bootstrap's cgen has known silent-miscompilation traps. They produce wrong runtime behavior, not compile errors. When porting C → ww here, default to the workarounds:

  1. amalloc(n) with n < struct size silently corrupts neighbours. No error — the bump arena hands out n bytes and field writes overflow into the next record. When introducing or growing a struct, audit every amalloc(_, n) call site and over-size (we routinely pass 48 for a 40-byte struct). Symptom: linked-list prepends lose all but the most recent entry.

Fixed (no workaround needed):

  • def NAME: str = "..." field access. .len/.ptr on an Sdef ident now inline the literal length / strlit address rather than reading BP+8. See cmd/w6c/cgen.c N_DOT.
  • Two-level field write through pointer field: r.sym.isdyn = 1 where r.sym: *T now stores. The chained-N_DOT N_ASSIGN branch evaluates the inner pointer and stores at *(ptr + field.offset). See cmd/w6c/cgen.c N_ASSIGN and selfhost/cmd/wcc/cgenexpr.ww cgassign.
  • Tuple return (scalar, str) (24B). Returns now follow an AX:DX:CX convention: AX = scalar elem, DX = str.ptr, CX = str.len. Receive sites all destructure off the same regs regardless of positional order: let n, s = call(); // ww comma form let (n, s) = call(); // Hare-style paren form let t: (i64, str) = call(); // positional t.0 / t.1.len Wwstage parser + cgen are byte-identical to C cgen on these shapes. See cmd/w6c/cgen.c N_RETURN/N_LET/N_DOT/N_MLET, lib/ww/parse/{stmt, expr}.ww and selfhost/cmd/wcc/{cgenstmt,cgenexpr,cgenutil,cgendecl}.ww.

If a port "should work" but the binary is wrong, suspect these first.