Commit Graph

2 Commits

Author SHA1 Message Date
ce3a25a0b4 test: contain sepwork scratch per-driver tmpdir, fix /tmp+in-repo leak (#8)
The wcc test drivers ran `ww build <bare-/tmp src>` with no -o, so the
compiler's <stem>.sepwork scratch landed beside the source and was never
cleaned: unbounded /tmp growth (2195 stale dirs observed) that fills tmpfs
and fabricates phantom test failures + silent harness aborts, and for
in-repo fixture builds leaked .sepwork into the tracked tree.

Each leaking build now writes its source + output inside a per-invocation
tmpdir, passes -o <tmpdir>/<stem> so the .sepwork lands inside it, and
rm -rf's the tmpdir on every exit path -- including fopen-fail and the
expected-fail reject builds (scratch is mkdir'd before the build can fail).
`ww run` and explicit-`-o`/byte-id helpers are left as-is; the 990/993
byte-id comparison logic is byte-for-byte unchanged.

Two items filed separately (this commit holds the no-Makefile / no-main.c
rail):
- #13: a stale <src>.s byte-id readback (749) silently no-ops since
  separate-compile emits .s to <ostem>.sepwork/__root.s; documented inline.
- #14: build-system Makefile recipes build selfhost/cmd/*/main.ww with no
  -o and leak main.sepwork in-tree (bounded, gitignored; own commit).

One concern -- sepwork leak hygiene -- across 228 drivers; uniform
transform applied per-file and two-round reviewed. make test: all 402
passed, zero net-new /tmp scratch, zero test-driven in-repo .sepwork.
2026-06-22 23:29:39 +09:00
98460e0220 cstage+selfhost+test: fix nested call-rhs silent zero in structlit fill (3rd of family)
Sister bug to #17 / #18. The structlit-fill helper handled nested
N_STRUCTLIT field values but a struct-typed field whose VALUE is an
N_CALL (call returning a struct, #4 cgreturn ABI) fell through to the
cgexpr-then-AX-store path — landing AX=first qword and silently
dropping DX/CX. For 16B/24B inner returns the trailing 8B/16B stayed
zero (whatever was in the destination slot beforehand).

Fix: a new N_CALL+struct branch in cg_structlit_fill / cgstructlitfill,
placed between the nested-N_STRUCTLIT recursion and the scalar
cgexpr fallthrough. Emits cgexpr -> BX reload (non-BP modes only) ->
MOVQ AX/DX/CX x full + sized tail (MOVL/MOVW/MOVB) per #4's receive
shape.

INVARIANT (commented inline both stages): between cgexpr(N_CALL) and
the AX/DX/CX stores below, no instruction may touch AX/DX/CX. Only
the BX reload (MOVQ srcoff(BP),BX or LEAQ name(SB),BX) is safe.

Sized-tail dispatch is {1->MOVB, 2->MOVW, 4->MOVL, else MOVQ}. Unlike
the scalar fallthrough — which still uses the {1/4/else MOVQ} shape
to stay byte-identical with cstage pending #13 — the new branch is
correctness-by-construction: MOVW for tail==2 only fires on call-rhs
shapes that didn't compile before, and both stages emit it
symmetrically (705's 10B inner row pins this).

Guard `fsz <= 24 && fsz%8 in {0,1,2,4}` mirrors #4's cgreturn ABI:
>24B falls through (sret deferred), and fsz%8 in {3,5,6,7} would need
shift-store — also unsupported by #4. Filed as task #21 (covers both
cgreturn and call-rhs's identical gap).

Two #15 sidesteps, both documented inline:

  1. wwstage's fi.fsz for an inner-struct field is slot-padded
     (8-rounded), not natural — using it would emit 2x MOVQ where
     cstage emits MOVQ+MOVL for a 12B inner. The new wwstage branch
     uses structnaturalsize(csi) to recover the natural size, matching
     cstage's fl->type->size (check.c hands the helper natural sizes).
     This sidesteps #15 without touching its scope.

  2. The outer struct's totsize diverges across stages when
     maxalign<8 (wwstage rounds to 8 universally; cstage to maxalign).
     The 705 test rows pin `x: i64` on the outer to force outer
     maxalign=8, keeping BP offsets stable across stages. Test-side
     sidestep only; also #15 territory.

Files:
  - cmd/w6c/cgen.c              cg_structlit_fill extended
  - selfhost/cmd/wcc/cgenutil.ww  cgstructlitfill mirror
  - selfhost/cmd/{w6c,wwdump}/main.combined.ww  auto-regen
  - test/wcc/705_nested_call_rhs.c  8 rows, table-driven; pins cstage
    exit + wwstage exit + .s byte-identity. Tail widths 0/4/2/1, dst
    modes DST_BP + DST_PTR_LOCAL, shallow + 3-deep.
  - Makefile  705 wiring

Test: 65/65 PASS. 994_w6c_ww + 995_self_rebuild PASS (byte-identity
holds — load-bearing).
2026-05-15 19:07:29 +09:00