From e7cb9c9d836f6faaf9255805a767d861ae7bbc39 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Wed, 17 Jun 2026 08:33:15 +0900 Subject: [PATCH] Makefile: bootstrap via separate compilation (M4 E2-C1, #22) Rewrite `make bootstrap` to the sep build path: sep-build w6c, orchestrated by the cstage ww driver chaining the frontend via WW_W6C (stage2 w6c_ww -> ww2; stage3 ww2 -> ww3; stage4 ww3 -> ww4; cmp ww2 == ww3 == ww4). wwdump is unchainable under sep (no -o/-I, writes asm to stdout), so the chainable w6c is the bootstrapped target (test 994 pins w6c == wwdump -c). Honest boundary, no overclaim: cstage ww runs the sep glue only (dep-discovery / per-package w6c -c / archive / link) and is NOT part of the fixed point; the fixed point proves the wwstage compiler (w6c, genuinely chained) plus assembler (w6a_ww) and linker (w6l_ww) reach a byte-stable fixed point. The wwstage driver ww_ww is not yet in the loop (it can't swap its frontend) -- that closer is #66. Makefile only; all five wwstage binary pins unchanged. bootstrap is a standalone dev target, not part of make test. --- Makefile | 70 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 97781323..3fab64ed 100644 --- a/Makefile +++ b/Makefile @@ -3544,53 +3544,67 @@ clean: rm -rf $(OUT) # ---- bootstrap (phase 10) ---------------------------------------------- -# Four-stage self-host: Cstage (these C tools) → ww1 → ww2 → ww3 → ww4 -# with cmp ww2 == ww3 and cmp ww3 == ww4. Stage 1 is wwdump_ww (the -# ww-built frontend); stages 2/3/4 assemble with w6a_ww and link with -# w6l_ww — every tool below the driver is now in ww. The C `ww` driver -# still orchestrates the pipeline (porting it is the remaining phase-10 -# work). +# Four-stage self-host on the SEPARATE-COMPILATION path: Cstage (these C +# tools) builds the wwstage tools, then the wwstage compiler reproduces +# itself three times with cmp ww2 == ww3 == ww4. # -# Why a fourth stage? Stage 3 proves ww1 and ww2 (which differ in how -# they were built) emit the same machine code. Stage 4 proves ww3 is +# Orchestration vs. proof — drawn explicitly so this demo claims no more +# self-host than it delivers (#66): +# - The cstage `ww` driver runs the sep GLUE only: dep-discovery, +# per-package `w6c -c -I`, archiving, and the final link. It is a +# fixed C orchestrator and is NOT part of the fixed point. +# - The fixed point ww2 == ww3 == ww4 proves the wwstage COMPILER +# (w6c, genuinely chained — stage N's frontend is stage N-1's output, +# injected via WW_W6C) plus the wwstage ASSEMBLER (w6a_ww) and LINKER +# (w6l_ww) reach a byte-stable fixed point: the load-bearing +# compiler-reproduces-itself proof. wwdump is unchainable under sep +# (it takes no -o/-I and writes asm to stdout), so the chainable sep +# frontend w6c is the bootstrapped target (test 994 pins w6c == +# wwdump -c). +# - The wwstage DRIVER (`ww_ww`) is NOT yet in this loop: it cannot +# swap its frontend (it hardcodes /w6c_ww and honors no +# WW_W6C override). Closing that — so `ww_ww` itself carries the +# glue — is task #66. Until then cstage `ww` orchestrates and this +# bootstrap does NOT claim a fully wwstage-driven self-host. +# +# Why a fourth stage? Stage 3 proves stage-1 w6c_ww and ww2 (which differ +# in how they were built) emit the same machine code. Stage 4 proves ww3 is # byte-stable when used as a compiler — i.e. the fixed point is truly # fixed, not merely a coincidental two-stage equilibrium. BS = $(OUT)/bootstrap +W6CSRC = selfhost/cmd/w6c/main.ww +W6CINC = -I lib/ww -I selfhost/cmd/wcc bootstrap: all @echo "=== stage 0 (Cstage): C-built tools ===" - @echo " $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l" + @echo " $(BIN)/ww (sep orchestrator) $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l" @echo - @echo "=== stage 1: ww-built tools, used to drive stages 2/3/4 ===" - @ls -l $(BIN)/wwdump_ww $(BIN)/w6a_ww $(BIN)/w6l_ww $(BIN)/ww_ww + @echo "=== stage 1: wwstage tools the fixed point chains ===" + @ls -l $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww @rm -rf $(BS) && mkdir -p $(BS) @echo - @echo "=== stage 2: ww2 = ww1 self-compiles main.combined.ww ===" - @$(BIN)/wwdump_ww -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww2.s - @$(BIN)/w6a_ww -o $(BS)/ww2.o $(BS)/ww2.s - @$(BIN)/w6l_ww -o $(BS)/ww2 $(BS)/ww2.o $(LIB)/libwwrt.a + @echo "=== stage 2: ww2 = stage-1 w6c_ww sep-compiles w6c ===" + @WW_W6C=$(BIN)/w6c_ww WW_W6A=$(BIN)/w6a_ww WW_W6L=$(BIN)/w6l_ww \ + WW_PKGCACHE=$(BS)/pc2 \ + $(BIN)/ww build --sep -o $(BS)/ww2 $(W6CINC) $(W6CSRC) @ls -l $(BS)/ww2 @echo - @echo "=== stage 3: ww3 = ww2 self-compiles main.combined.ww ===" - @$(BS)/ww2 -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww3.s - @$(BIN)/w6a_ww -o $(BS)/ww3.o $(BS)/ww3.s - @$(BIN)/w6l_ww -o $(BS)/ww3 $(BS)/ww3.o $(LIB)/libwwrt.a + @echo "=== stage 3: ww3 = ww2 sep-compiles w6c ===" + @WW_W6C=$(BS)/ww2 WW_W6A=$(BIN)/w6a_ww WW_W6L=$(BIN)/w6l_ww \ + WW_PKGCACHE=$(BS)/pc3 \ + $(BIN)/ww build --sep -o $(BS)/ww3 $(W6CINC) $(W6CSRC) @ls -l $(BS)/ww3 @echo - @echo "=== stage 4: ww4 = ww3 self-compiles main.combined.ww ===" - @$(BS)/ww3 -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww4.s - @$(BIN)/w6a_ww -o $(BS)/ww4.o $(BS)/ww4.s - @$(BIN)/w6l_ww -o $(BS)/ww4 $(BS)/ww4.o $(LIB)/libwwrt.a + @echo "=== stage 4: ww4 = ww3 sep-compiles w6c ===" + @WW_W6C=$(BS)/ww3 WW_W6A=$(BIN)/w6a_ww WW_W6L=$(BIN)/w6l_ww \ + WW_PKGCACHE=$(BS)/pc4 \ + $(BIN)/ww build --sep -o $(BS)/ww4 $(W6CINC) $(W6CSRC) @ls -l $(BS)/ww4 @echo @echo "=== fixed-point gates ===" - @cmp $(BS)/ww2.s $(BS)/ww3.s && echo " ww2.s == ww3.s ✓" - @cmp $(BS)/ww2.o $(BS)/ww3.o && echo " ww2.o == ww3.o ✓ (byte-identical .o)" @cmp $(BS)/ww2 $(BS)/ww3 && echo " ww2 == ww3 ✓ (byte-identical exe)" - @cmp $(BS)/ww3.s $(BS)/ww4.s && echo " ww3.s == ww4.s ✓" - @cmp $(BS)/ww3.o $(BS)/ww4.o && echo " ww3.o == ww4.o ✓ (byte-identical .o)" @cmp $(BS)/ww3 $(BS)/ww4 && echo " ww3 == ww4 ✓ (byte-identical exe, ww3 is byte-stable as a compiler)" @echo - @echo "BOOTSTRAP OK: ww-cgen + w6a_ww + w6l_ww reach a fixed point that holds across two iterations." + @echo "BOOTSTRAP OK: ww-cgen (w6c) + w6a_ww + w6l_ww reach a fixed point that holds across two iterations (sep path)." @echo @echo "Phase 10 remaining work:" @echo " - delete cmd/wcc/ cmd/w6c/ cmd/w6a/ cmd/w6l/ cmd/ww/ in the final commit"