Ports cmd/6l/{dyn,dynout}.c into selfhost/cmd/6l/{dyn,dynout}.ww:
ET_DYN .so loading + PT_INTERP/PT_DYNAMIC ELF emission with .rela.plt,
.gnu.version_r, BIND_NOW. lsym grows dyn fields; pass.ww promotes
undefs to dyn; out.ww dispatches; main.ww takes -L/-l. The ww driver
forwards -L/-l to 6l_ww so 'ww_ww build snake.ww -L /usr/lib -l ncurses
-l c' runs without cc.
Test 996 pins byte-identical output to C-6l on snake.
'make bootstrap' gains a fourth stage with cmp ww3 == ww4, proving
ww3 is byte-stable when used as a compiler — not just a coincidental
two-stage equilibrium.
Four wwstage 6c cgen quirks surfaced and are documented in dynout.ww's
header (two-level field-write through a pointer field, (scalar, str)
tuple returns, def : str, ≤6 arg calling convention).
Sets up the cc-free fresh-checkout flow without yet committing the
stage-0 binaries. The pieces are in place; flipping the switch is
one `git add -f` away when the compiler is judged stable.
bootstrap/<arch>/{ww,6c,6a,6l} stage-0 binaries (gitignored)
bootstrap/README.md layout + workflow
Two new targets:
make bootstrap-snapshot populates bootstrap/$(ARCH)/ from the
currently-built wwstage
make nocc starts from bootstrap/$(ARCH)/, rebuilds
the wwstage from source, gates on
stage-0 == rebuilt byte-for-byte. Lands
in $(OUT)/nocc/ so $(OUT)/ stays
untouched. cc is never invoked.
The fixed-point gate has the same shape as `make bootstrap`, just
the entry point flipped: that target trusts cstage; nocc trusts
the checked-in (or local-snapshot) stage-0 binaries.
Implementation notes:
- libwwrt.a is assembled with stage-0 6a, members ordered to match
$(RT_OBJ) so the embedded symbol table reproduces the cstage
build byte-for-byte.
- The driver's default lib path is $self_dir/../../lib, which under
$(NOCC_BIN) resolves to $(NOCC_OUT)/lib (libwwrt only). Each
ww-build invocation passes -I $(CURDIR)/lib so `use os` etc.
resolve to source.
- Stage-0 binaries are duplicated under both natural names (ww/6c/
6a/6l) and _ww-suffixed names so the wwstage driver's
hard-coded join_path_lit(self_dir, "6c_ww") still finds them.
When cmd/wwc/ gets deleted at v1.0, that duplication and the
_ww suffix in the driver both go away.
Phase 10 step 8 (delete the C trees) is deferred to v1.0 — until the
compiler stops churning we keep Cstage as the fresh-checkout entry
point. Split the Makefile so the two stages are named, and add
BOOTSTRAP.md describing the cstage → ww1 → ww2 → ww3 fixed-point
flow. PLAN.md gets a status note pointing at it.