test: re-point 990/994/#110 off combined.ww-input to sep-feed (M4 E4-keystone, #22)

The E3 driver flip makes build_one_sep the sole path; it writes
.sepwork/*.unit.ww, not <stem>.combined.ww, so the flip stops producing
combined.ww. Migrate its consumers to sep-feed first, while both build
paths still exist (reversible; all 5 stage binaries stay byte-identical):

- 990_selfhost: resolveunit drives `ww build --sep` and reads
  <stem>.sepwork/__root.unit.ww; probe_cgen_match gains err.ww (sep
  inlines fmt's .wwi only, so cs==ww holds); probe_ww_links re-expressed
  as `ww_ww build --sep`->run; probe_bootstrap_fixed_point removed (the
  monolith path it tested is deleted by E4 -- the self-application axis
  lives in `make bootstrap`, the cs==ww axis in 995).
- 994_w6c_ww: drop the combined-fed emit_eq + corpus; keep the live
  per-package cs-sep==ww-sep oracle (cmp_sepwork + diff_one + bad[]).
- #110 combined_ww_fresh gate removed (its regen-vs-committed premise
  dies with its producer).

Non-vacuity proven: a one-line emitter mutation reddens 994's per-package
cs!=ww check across 15 packages; revert restores green.
This commit is contained in:
2026-06-18 02:49:09 +09:00
parent 2c62be44a7
commit 5f85852faf
3 changed files with 80 additions and 249 deletions

View File

@@ -518,21 +518,21 @@ cleanup:
}
/* resolveunit — produce <fixture>'s RESOLVED translation unit the way
* the driver does. `ww build` concatenates the module with its
* transitive imports into <stem>.combined.ww (cmd/ww/main.c expand()),
* which is the single unit w6c/wwdump actually consume; w6c never
* resolves imports itself (cmd/w6c/main.c reads one pre-concatenated
* file). Feeding a raw module file therefore leaves its import refs
* (os.write, fmt.errorln, strconv.i64tos …) unresolved — a partial
* unit harec's module::resolve never hands the checker, and which the
* ww-stage asserttyped invariant (check.ww) is not meant to see.
* the sep driver does. `ww build --sep` composes the root package's
* <stem>.sepwork/__root.unit.ww: the transitive deps' `.wwi` interface
* stubs followed by the root package body — the single self-contained
* unit w6c/wwdump consume for the root (the producer compiles it with no
* -I; cmd/ww/main.c sep_compose_unit). Feeding a raw module file instead
* would leave its import refs (os.write, fmt.errorln, strconv.i64tos …)
* unresolved — a partial unit harec's module::resolve never hands the
* checker, and which the ww-stage asserttyped invariant must not see.
*
* Built in a private /tmp dir (a copy of the fixture) so no .combined.ww
* / .s / .o lands next to the repo source. The link step fails for an
* import-only module (no main), but .combined.ww is written before
* codegen, so we detect that artifact rather than gating on the build
* exit. Writes the owning tmpdir into `td` (caller rm -rf's it) and the
* combined path into `out`. Returns 0 on success, -1 otherwise. */
* Built in a private /tmp dir (a copy of the fixture) so the sepwork
* lands off the repo source tree. The link step fails for an import-only
* module (no main), but the unit is written before the link, so we detect
* that artifact rather than gating on the build exit. Writes the owning
* tmpdir into `td` (caller rm -rf's it) and the unit path into `out`.
* Returns 0 on success, -1 otherwise. */
static int
resolveunit(const char *bin, const char *cwd, const char *fixture,
int idx, char *td, size_t tdsz, char *out, size_t outsz)
@@ -549,18 +549,19 @@ resolveunit(const char *bin, const char *cwd, const char *fixture,
snprintf(cmd, sizeof cmd, "cp %s/%s %s", cwd, fixture, tmpsrc);
runwait(cmd);
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s/ww build %s >/dev/null 2>&1", td, bin, base);
"cd %s && timeout 180 %s/ww build --sep %s >/dev/null 2>&1",
td, bin, base);
runwait(cmd);
snprintf(out, outsz, "%s", tmpsrc);
char *dot = strrchr(out, '.');
char stem[768];
snprintf(stem, sizeof stem, "%s", tmpsrc);
char *dot = strrchr(stem, '.');
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
size_t n = strlen(out);
snprintf(out + n, outsz - n, ".combined.ww");
snprintf(out, outsz, "%s.sepwork/__root.unit.ww", stem);
return access(out, 0) == 0 ? 0 : -1;
}
/* Probe 4: ww-side checker (wwdump_ww -r) runs name resolution on each
* selfhost fixture's RESOLVED unit (imports concatenated — see
* selfhost fixture's RESOLVED unit (sep root unit — see
* resolveunit) and reports zero unresolved. The raw file would leave
* its `import` refs (os/fmt/strconv/ascii members) unresolved, i.e. the
* partial unit the asserttyped invariant must never see (harec resolves
@@ -578,9 +579,9 @@ probe_resolve(const char *bin)
};
int fail = 0;
for (int i = 0; fixtures[i]; i++) {
char td[64], combined[1024], a[256], cmd[2048];
char td[64], unit[1024], a[256], cmd[2048];
if (resolveunit(bin, cwd, fixtures[i], i, td, sizeof td,
combined, sizeof combined) != 0) {
unit, sizeof unit) != 0) {
fprintf(stderr, "resolve FAIL: %s — no resolved unit\n",
fixtures[i]);
fail++;
@@ -588,7 +589,7 @@ probe_resolve(const char *bin)
}
snprintf(a, sizeof a, "/tmp/wwd_r_%d", getpid());
snprintf(cmd, sizeof cmd, "timeout 180 %s/wwdump_ww -r %s > %s 2>/dev/null",
bin, combined, a);
bin, unit, a);
int rc = runwait(cmd);
if (rc != 0) {
fprintf(stderr, "resolve FAIL: %s exited %d (unresolved names)\n",
@@ -657,72 +658,21 @@ probe_dump_stable(const char *bin)
return fail ? -1 : 0;
}
/* Probe 9: full bootstrap fixed-point. ww1 → ww2 → ww3 with
* cmp ww2.s == ww3.s and cmp ww2 == ww3 (byte-identical binaries).
* This is the textbook self-host gate: the compiler must reach a
* fixed point under iterated self-compilation. */
static int
probe_bootstrap_fixed_point(const char *bin)
{
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return -1;
char tmpdir[64];
snprintf(tmpdir, sizeof tmpdir, "/tmp/wwfp_%d", getpid());
mkdir(tmpdir, 0755);
char ww2s[512], ww2o[512], ww2e[512];
char ww3s[512], ww3o[512], ww3e[512];
char rt[1024], cmd[4096];
snprintf(rt, sizeof rt, "%s/../lib/libwwrt.a", bin);
snprintf(ww2s, sizeof ww2s, "%s/ww2.s", tmpdir);
snprintf(ww2o, sizeof ww2o, "%s/ww2.o", tmpdir);
snprintf(ww2e, sizeof ww2e, "%s/ww2", tmpdir);
snprintf(ww3s, sizeof ww3s, "%s/ww3.s", tmpdir);
snprintf(ww3o, sizeof ww3o, "%s/ww3.o", tmpdir);
snprintf(ww3e, sizeof ww3e, "%s/ww3", tmpdir);
int fail = 0;
/* ww1 -> ww2 */
snprintf(cmd, sizeof cmd,
"timeout 180 %s/wwdump_ww -c %s/selfhost/cmd/wwdump/main.combined.ww > %s 2>/dev/null",
bin, cwd, ww2s);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: ww1 self-compile\n"); fail++; goto cleanup; }
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6a -o %s %s 2>/dev/null", bin, ww2o, ww2s);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: w6a ww2.s\n"); fail++; goto cleanup; }
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6l -o %s %s %s 2>/dev/null", bin, ww2e, ww2o, rt);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: w6l ww2\n"); fail++; goto cleanup; }
/* ww2 -> ww3 */
snprintf(cmd, sizeof cmd,
"timeout 180 %s -c %s/selfhost/cmd/wwdump/main.combined.ww > %s 2>/dev/null",
ww2e, cwd, ww3s);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: ww2 self-compile\n"); fail++; goto cleanup; }
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6a -o %s %s 2>/dev/null", bin, ww3o, ww3s);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: w6a ww3.s\n"); fail++; goto cleanup; }
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6l -o %s %s %s 2>/dev/null", bin, ww3e, ww3o, rt);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: w6l ww3\n"); fail++; goto cleanup; }
/* The fixed-point check: ww2.s == ww3.s, ww2 == ww3. */
snprintf(cmd, sizeof cmd, "cmp -s %s %s", ww2s, ww3s);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: ww2.s != ww3.s (no fixed point)\n"); fail++; }
snprintf(cmd, sizeof cmd, "cmp -s %s %s", ww2e, ww3e);
if (runwait(cmd) != 0) { fprintf(stderr, "fp FAIL: ww2 != ww3 binaries\n"); fail++; }
cleanup:
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
runwait(cmd);
return fail ? -1 : 0;
}
/* Probe 7: end-to-end via wwdump_ww. Use `ww build` to produce the
* concatenated source as a side effect, then drive ww-cgen → w6a →
* w6l → run, comparing the binary's exit code to the fixture's
* declared expectation. This is the bootstrap-grade signal: it
* doesn't require ww-cgen output to be byte-identical to C-cgen,
* only to be functionally correct. The byte-match probe above is
* useful while it lasts but layout choices (slot allocation order,
* spill placement) eventually diverge between cgens; correctness is
* the test that scales. */
/* Probe 7: end-to-end via the ww driver's sep path. `ww_ww build --sep`
* drives the ww-side toolchain (w6c_ww → w6a_ww → w6l_ww) over the
* fixture's package graph — per-package compile, archive, reverse-topo
* link — and we run the result, comparing the exit code to the fixture's
* declared expectation. This is the bootstrap-grade signal: it doesn't
* require byte-identity, only that the ww toolchain links the fixture's
* dep stack (sym/typ/ast via the syntax package, in a SEPARATE `.o`) into
* a functionally correct binary. The single-`.s` link the combined path
* used is gone with combined-mode (the syntax symbols live in their own
* `.o` under --sep, not in the root unit). */
static int
probe_ww_links(const char *bin)
{
const char *fixtures[][2] = {
{ "selfhost/test/sym_link.ww", "42" }, /* sym/typ/ast/mem */
{ "selfhost/test/sym_link.ww", "42" }, /* sym/typ/ast via syntax */
{ NULL, NULL },
};
char cwd[1024];
@@ -745,41 +695,18 @@ probe_ww_links(const char *bin)
char cmd[4096];
snprintf(cmd, sizeof cmd, "cp %s/%s %s", cwd, fix, tmpsrc);
runwait(cmd);
/* ww build to get the .combined.ww as a side effect. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s/ww build -I %s/lib/ww -I %s/selfhost/cmd/wcc %s >/dev/null 2>&1",
tmpdir, bin, cwd, cwd, tmpsrc);
if (runwait(cmd) != 0) {
fprintf(stderr, "ww-links FAIL: ww build %s\n", fix);
fail++;
goto cleanup;
}
/* Now compile the combined source via the ww frontend. */
char combinedp[512], wsp[512], wop[512], wexep[512];
snprintf(combinedp, sizeof combinedp, "%s.combined.ww", stem);
snprintf(wsp, sizeof wsp, "%s_w.s", stem);
snprintf(wop, sizeof wop, "%s_w.o", stem);
/* Isolated WW_PKGCACHE: the default out/.pkgcache is shared with
* the other phase-2 gates' sep builds (perturb + race). -o + the
* absolute src/-I paths route every side file into tmpdir, so no
* cwd dependency. */
char wexep[512];
snprintf(wexep, sizeof wexep, "%s_w", stem);
snprintf(cmd, sizeof cmd,
"timeout 180 %s/wwdump_ww -c %s > %s 2>/dev/null", bin, combinedp, wsp);
"WW_PKGCACHE='%s.cache' timeout 180 %s/ww_ww build --sep "
"-o %s -I %s/lib/ww -I %s/selfhost/cmd/wcc %s >/dev/null 2>&1",
stem, bin, wexep, cwd, cwd, tmpsrc);
if (runwait(cmd) != 0) {
fprintf(stderr, "ww-links FAIL: wwdump_ww -c %s\n", fix);
fail++;
goto cleanup;
}
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6a -o %s %s 2>/dev/null",
bin, wop, wsp);
if (runwait(cmd) != 0) {
fprintf(stderr, "ww-links FAIL: w6a %s\n", fix);
fail++;
goto cleanup;
}
char rt[1024];
snprintf(rt, sizeof rt, "%s/../lib/libwwrt.a", bin);
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6l -o %s %s %s 2>/dev/null",
bin, wexep, wop, rt);
if (runwait(cmd) != 0) {
fprintf(stderr, "ww-links FAIL: w6l %s\n", fix);
fprintf(stderr, "ww-links FAIL: ww_ww build --sep %s\n", fix);
fail++;
goto cleanup;
}
@@ -791,8 +718,6 @@ probe_ww_links(const char *bin)
fail++;
}
cleanup:
/* Sweep tmpdir contents, then remove. ww build also drops a
* C-built binary at <stem> — clean it too. */
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
runwait(cmd);
}
@@ -800,23 +725,20 @@ cleanup:
}
/* Probe 6: ww-cgen byte-matches C-cgen on each selfhost fixture's
* RESOLVED unit (imports concatenated — see resolveunit). The driver
* always feeds w6c/wwdump a concatenated unit, so the byte-identity
* gate (rule 10) belongs on that shape rather than the raw file; the
* unit also drags in the imported stdlib (os/strconv/ascii), widening
* the convergence set. When this stays empty the cmp ww2 ww3 ceiling
* becomes feasible.
* RESOLVED unit (sep root unit — see resolveunit). The producer feeds
* w6c/wwdump that self-contained unit, so the byte-identity gate (rule
* 10) belongs on that shape rather than the raw file.
*
* selfhost/cmd/wcc/err.ww is exercised by probe_resolve but not here:
* its resolved unit pulls in lib/fmt, whose `formattable` match the
* ww-stage checker rejects (check.ww casecovers/casevariantin raise
* ck.errs, so wwdump -c bails before cgen) — a cs≠ww match-exhaustive-
* ness divergence, latent for the bootstrap (the compiler's own
* main.combined.ww imports no fmt) and tracked separately. */
* err.ww is included now (it was excluded under combined-mode, where its
* unit inlined lib/fmt's BODY and the ww checker rejected fmt's
* `formattable` match-exhaustiveness): the sep unit inlines only fmt's
* `.wwi` INTERFACE, so the fmt body never reaches the checker and err's
* root cgen converges cs==ww. */
static int
probe_cgen_match(const char *bin)
{
const char *files[] = {
"selfhost/cmd/wcc/err.ww",
"lib/ww/syntax/tok.ww",
"selfhost/test/smoke.ww",
NULL,
@@ -825,9 +747,9 @@ probe_cgen_match(const char *bin)
if (getcwd(cwd, sizeof cwd) == NULL) return -1;
int fail = 0;
for (int i = 0; files[i]; i++) {
char td[64], combined[1024], a[256], b[256], cmd[2048];
char td[64], unit[1024], a[256], b[256], cmd[2048];
if (resolveunit(bin, cwd, files[i], i, td, sizeof td,
combined, sizeof combined) != 0) {
unit, sizeof unit) != 0) {
fprintf(stderr, "cgen-match FAIL: %s — no resolved unit\n",
files[i]);
fail++;
@@ -836,10 +758,10 @@ probe_cgen_match(const char *bin)
snprintf(a, sizeof a, "/tmp/wwd_cm_%d_c", getpid());
snprintf(b, sizeof b, "/tmp/wwd_cm_%d_w", getpid());
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6c %s > %s 2>/dev/null",
bin, combined, a);
bin, unit, a);
runwait(cmd);
snprintf(cmd, sizeof cmd, "timeout 180 %s/wwdump_ww -c %s > %s 2>/dev/null",
bin, combined, b);
bin, unit, b);
runwait(cmd);
char *bc = NULL, *bw = NULL;
size_t nc = 0, nw = 0;
@@ -876,19 +798,26 @@ main(void)
if (probe_ww_compile(bin) != 0) fail++;
if (probe_cgen_match(bin) != 0) fail++;
if (probe_ww_links(bin) != 0) fail++;
if (probe_bootstrap_fixed_point(bin) != 0) fail++;
if (fail) {
fprintf(stderr, "selfhost: %d probe(s) failed\n", fail);
return 1;
}
/* The ww1->ww2->ww3 binary fixed point is no longer reproducible here:
* it self-compiled wwdump as a monolith from main.combined.ww, a model
* combined-mode provided and --sep retires (the sep root unit holds only
* the root body + dep INTERFACE stubs, not a linkable whole program). The
* two axes it covered now live elsewhere: the self-application fixed point
* (iterated self-compile converges, ww2==ww3==ww4) is `make bootstrap`'s
* sep-path gate (migrated E2-C1); the orthogonal wwstage==cstage byte
* identity is 995_self_rebuild, which drives ww_ww --sep over all five
* tools (wwdump included) and byte-compares against the cstage binaries. */
printf("selfhost: codegen ok; smoke=42; wwdump stable; "
"ww lexer matches C on 8 fixtures (-t); "
"ww parser matches C on 32 fixtures (-a); "
"ww checker resolves 3 fixtures' import-concatenated units (-r); "
"ww checker resolves 3 fixtures' sep root units (-r); "
"ww cgen compiles + runs 13 ww programs (incl. compound -= regression); "
"ww cgen byte-matches C on 2 resolved units (tok/smoke); "
"ww cgen builds runnable binaries from sym/typ/ast/mem stack; "
"ww1 -> ww2 -> ww3 fixed-point reached: ww2.s == ww3.s, ww2 == ww3 byte-identical\n");
"ww cgen byte-matches C on 3 sep root units (err/tok/smoke); "
"ww toolchain sep-builds + runs the syntax dep stack (sym_link=42)\n");
return 0;
}

View File

@@ -120,41 +120,6 @@ files_eq(const char *a, const char *b)
return eq ? 0 : 1;
}
/* Tier-C oracle helper (rob-c6-spec §2 / amendment-B): a sep-built w6c at
* `sepw6c` must EMIT byte-identical asm to the combined-built `w6c_ww` on
* `target`. (We assert OUTPUT equivalence, never `cmp` the tool binaries —
* sep vs combined differ by a constant link-layout delta.) Returns 0 on
* byte-identical .s, non-zero otherwise. */
static int
emit_eq(const char *sepw6c, const char *w6c_ww, const char *target,
const char *label)
{
char a[64], b[64], cmd[4096];
snprintf(a, sizeof a, "/tmp/wwc6tc_%d_sep.s", getpid());
snprintf(b, sizeof b, "/tmp/wwc6tc_%d_comb.s", getpid());
snprintf(cmd, sizeof cmd, "timeout 240 %s -o %s %s 2>/dev/null",
sepw6c, a, target);
if (runwait(cmd) != 0) {
fprintf(stderr, "Tier-C FAIL: sep-w6c emit errored on %s\n", label);
unlink(a);
return 1;
}
snprintf(cmd, sizeof cmd, "timeout 240 %s -o %s %s 2>/dev/null",
w6c_ww, b, target);
if (runwait(cmd) != 0) {
fprintf(stderr, "Tier-C FAIL: combined-w6c_ww emit errored on %s\n",
label);
unlink(a); unlink(b);
return 1;
}
int rc = files_eq(a, b);
if (rc != 0)
fprintf(stderr, "Tier-C FAIL: %s — sep-out != combined-out "
"(M4 output-equivalence broken)\n", label);
unlink(a); unlink(b);
return rc == 0 ? 0 : 1;
}
/* cs==ww over a sep-build's per-package artifacts: every .s/.o/.wwi the
* cstage driver produced in `csdir` must be byte-identical to the wwstage
* driver's same-named file in `wwdir` (rule 10; the .wwi interface files
@@ -309,17 +274,6 @@ main(void)
{ NULL, NULL },
};
/* Source-tree corpus: the same .combined.ww files the bootstrap
* fixed point chews on. Confirms w6c_ww handles realistic inputs,
* not just hand-tailored ones. */
const char *combined_rel[] = {
"selfhost/cmd/wwdump/main.combined.ww",
"selfhost/cmd/w6a/main.combined.ww",
"selfhost/cmd/w6l/main.combined.ww",
"selfhost/cmd/ww/main.combined.ww",
NULL,
};
int fail = 0, n = 0;
for (int i = 0; progs[i].label; i++) {
@@ -330,12 +284,6 @@ main(void)
unlink(src);
n++;
}
for (int i = 0; combined_rel[i]; i++) {
char p[2048];
snprintf(p, sizeof p, "%s/%s", cwd, combined_rel[i]);
if (diff_one(bin, combined_rel[i], p) != 0) fail++;
n++;
}
/* #50: the check pass is wired into both wwdump_ww -c and
* w6c_ww in front of cgen. Pre-#50, a hard type error parsed
@@ -376,22 +324,19 @@ main(void)
n++;
}
/* ---- Tier-C capstone (#46 c6, rob-c6-spec §2 / amendment-B) ----------
* Fold the dual-path soak into this bootstrap oracle: a w6c built by
* SEPARATE compilation must EMIT byte-identical .s to the combined-built
* w6c_ww on every real bootstrap input, and both driver stages must
* sep-produce byte-identical per-package .s/.o/.wwi (cs==ww on the real
* tool's sep artifacts). This is the load-bearing M4 proof — the
* combined-out==sep-out leg the bootstrap fixed point alone cannot reach.
* We assert OBSERVABLE OUTPUT, never `cmp` the tool binaries (sep vs
* combined differ by a constant link-layout delta). COLD (pid-keyed
* scratch, wiped); heavy (≈ one bootstrap leg) → this gate is phase-2. */
/* ---- Tier-C capstone (#46 c6, rob-c6-spec §2 / amendment-B; M4 #89) ---
* The load-bearing M4 oracle: build w6c by SEPARATE compilation under
* BOTH driver stages and prove they sep-produce byte-identical per-package
* .s/.o/.wwi (cs==ww on the real tool's sep artifacts, rule 10). The
* combined corpus + the sep-out==combined-out leg are gone — combined-mode
* is being retired (E3 flip), so combined.ww is no longer fed as compiler
* INPUT; the per-pkg cs==ww comparison is the surviving live oracle. COLD
* (pid-keyed scratch, wiped); heavy (≈ one bootstrap leg) → phase-2. */
{
char inc[4096], cmd[16384];
snprintf(inc, sizeof inc,
"-I %s/lib -I %s/lib/ww -I %s/selfhost/cmd/wcc", cwd, cwd, cwd);
char w6c_ww[2048], root[2048];
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
char root[2048];
snprintf(root, sizeof root, "%s/selfhost/cmd/w6c/main.ww", cwd);
struct { const char *drv, *tag; char prog[2048]; int ok; }
@@ -415,29 +360,6 @@ main(void)
n++;
}
/* OUTPUT equivalence on every real bootstrap input: each built
* sep-w6c vs the combined w6c_ww (the M4 combined-out==sep-out bar;
* cs==ww follows since both sep stages match the same reference). */
const char *targ[] = {
"selfhost/cmd/w6c/main.combined.ww",
"selfhost/cmd/wwdump/main.combined.ww",
"selfhost/cmd/w6a/main.combined.ww",
"selfhost/cmd/w6l/main.combined.ww",
"selfhost/cmd/ww/main.combined.ww",
NULL,
};
for (int s = 0; s < 2; s++) {
if (!stg[s].ok) continue;
for (int i = 0; targ[i]; i++) {
char t[2048], label[256];
snprintf(t, sizeof t, "%s/%s", cwd, targ[i]);
snprintf(label, sizeof label, "sep-%s emit %s",
stg[s].tag, targ[i]);
if (emit_eq(stg[s].prog, w6c_ww, t, label) != 0) fail++;
n++;
}
}
/* cs==ww on the real tool's sep .s/.o/.wwi (rule 10). */
if (stg[0].ok && stg[1].ok) {
char csdir[2176], wwdir[2176];
@@ -458,9 +380,8 @@ main(void)
fprintf(stderr, "w6c_ww: %d/%d diff(s) failed\n", fail, n);
return 1;
}
printf("w6c_ww: byte-identical to wwdump_ww -c on %d corpus inputs "
"(in-source + selfhost combined.ww) + Tier-C: sep-built w6c emits "
"== combined w6c_ww on all bootstrap inputs, cs==ww sep .s/.o/.wwi\n",
printf("w6c_ww: byte-identical to wwdump_ww -c on %d in-source corpus "
"inputs + Tier-C: cs==ww sep .s/.o/.wwi on the real w6c build\n",
n);
return 0;
}