test: retarget Pattern-A combined-feed gates to sep .sepwork layout (M4 E3, #94)

94a of the C-mig2 split (rob rule-11): 13 Pattern-A gates that fed a
.combined.ww to w6c/w6c_ww now drive two --sep builds (ww / ww_ww) and
byte-diff the concatenated per-package .sepwork/*.s, mirroring #93's
convention. Lands pre-flip while combined.ww still exists as the
reversible safety net. Test-only; all 5 binary pins HOLD.

989_enumcap_run deferred to 94b (its decisive assertion is a combined.ww
content diff, not a .s diff).
This commit is contained in:
2026-06-18 16:44:41 +09:00
parent 7b6f24adea
commit bbd2ad390a
14 changed files with 377 additions and 391 deletions

View File

@@ -1830,7 +1830,7 @@ $(BIN)/test_type_value_shadow_run: test/wcc/788_type_value_shadow_run.c \
# fixtures in a private mktemp dir — not a selfhost-driver test.
$(BIN)/test_xmod_alias_struct_collide_run: test/wcc/784_xmod_alias_struct_collide_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
@@ -1841,7 +1841,7 @@ $(BIN)/test_xmod_alias_struct_collide_run: test/wcc/784_xmod_alias_struct_collid
# Builds its own 2-module fixtures in a private mktemp dir.
$(BIN)/test_xmod_variant_match: test/wcc/787_xmod_variant_match.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
@@ -1854,7 +1854,8 @@ $(BIN)/test_xmod_variant_match: test/wcc/787_xmod_variant_match.c \
# Builds its own 2-module fixtures in a private mktemp dir.
$(BIN)/test_xmod_qualstructlit_run: test/wcc/848_xmod_qualstructlit_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww $(BIN)/wwdump $(BIN)/wwdump_ww \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(BIN)/wwdump $(BIN)/wwdump_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
@@ -1868,7 +1869,7 @@ $(BIN)/test_xmod_qualstructlit_run: test/wcc/848_xmod_qualstructlit_run.c \
# discriminator. Self-contained single-file probe.
$(BIN)/test_spread_variant_match: test/wcc/792_spread_variant_match.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
@@ -1885,7 +1886,7 @@ $(BIN)/test_widen_pad_zero_run: test/wcc/793_widen_pad_zero_run.c \
# 2-module fixtures in a private mktemp dir.
$(BIN)/test_xmod_ident_prefer: test/wcc/794_xmod_ident_prefer.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/w6c_ww \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
@@ -2950,7 +2951,9 @@ $(BIN)/test_dyn_ww: test/wcc/996_dyn_ww.c $(BIN)/ww $(BIN)/w6l $(BIN)/w6l_ww \
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_attest_record: test/wcc/911_attest_record.c $(BIN)/ww $(BIN)/w6c \
$(BIN)/w6c_ww $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN)
$(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# C2b — #6 @test drop/keep/link via direct w6c/w6c_ww on import-free fixtures
@@ -3351,7 +3354,8 @@ $(BIN)/test_structlit_arrfield_run: test/wcc/949_structlit_arrfield_run.c \
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_defdim_struct_run: test/wcc/951_defdim_struct_run.c \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<

View File

@@ -239,9 +239,10 @@ static const struct scenario scenarios[] = {
};
static int
run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
run_scenario(const char *bin, const char *cdrv, const char *wdrv,
const struct scenario *sc)
{
(void)bin;
/* Private fixture dir — #215: srcd is this dir (not shared /tmp),
* so the driver's srcd-first import search can't pick up a
* polluting same-name file. mkdtemp gives a unique path. */
@@ -263,9 +264,11 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
fclose(f);
}
/* cstage driver build + run: pins runtime. */
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build -I %s %s/main.ww",
dir, bin, dir, dir);
/* #94 sep layout: cstage --sep build + run pins runtime; pin
* WW_PKGCACHE under the scratch dir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s -o %s/main %s/main.ww",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "784[%s]: cstage build failed\n", sc->label);
rc = -1; goto done;
@@ -278,23 +281,24 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
rc = -1;
}
/* Byte-id net (the #223 discriminator): raw w6c vs w6c_ww on the
* driver-produced combined.ww. Pre-fix the dispatcher diverges. */
char cs_s[1024], ws_s[1024], comb[1024];
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, cs_s, comb);
/* Byte-id net (the #223 discriminator): the wwstage driver's --sep
* build emits per-package w6c_ww asm; pre-fix the dispatcher diverges.
* The root + each imported pkg compile to separate <stem>.sepwork/<pkg>.s;
* concat (sorted glob, identical set both stages) for the compare. */
char cs_s[1024], ws_s[1024];
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s -o %s/mainww %s/main.ww",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "784[%s]: w6c on combined failed\n", sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "784[%s]: w6c_ww on combined failed\n",
sc->label);
fprintf(stderr, "784[%s]: ww_ww build failed\n", sc->label);
rc = -1; goto done;
}
snprintf(cs_s, sizeof cs_s, "%s/all_cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/all_ww.s", dir);
snprintf(cmd, sizeof cmd, "cat %s/main.sepwork/*.s > %s 2>/dev/null",
dir, cs_s); if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/mainww.sepwork/*.s > %s 2>/dev/null",
dir, ws_s); if (system(cmd)) {}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr, "784[%s]: cs.s/ww.s DIFFER (rule-10 byte-id "
"violation — #223 regression)\n", sc->label);
@@ -321,11 +325,11 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "784: w6c_ww missing — cannot run the cs==ww "
char cdrv[2100], wdrv[2100];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "784: ww_ww missing — cannot run the cs==ww "
"byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -333,7 +337,7 @@ main(void)
int n = (int)(sizeof scenarios / sizeof scenarios[0]);
int fail = 0;
for (int i = 0; i < n; i++) {
if (run_scenario(bin, w6c, w6c_ww, &scenarios[i]) != 0)
if (run_scenario(bin, cdrv, wdrv, &scenarios[i]) != 0)
fail++;
}

View File

@@ -223,9 +223,10 @@ static const struct scenario scenarios[] = {
};
static int
run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
run_scenario(const char *bin, const char *cdrv, const char *wdrv,
const struct scenario *sc)
{
(void)bin;
char dir[] = "/tmp/ww787_XXXXXX";
if (mkdtemp(dir) == NULL) {
fprintf(stderr, "787[%s]: mkdtemp failed\n", sc->label);
@@ -244,48 +245,37 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
fclose(f);
}
char comb[1024];
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
if (sc->expect_reject) {
/* The driver build MUST fail (cstage's checker rejects the
* foreign-qualifier variant), but expand() still writes the
* combined unit before the checker runs — so re-check it with
* BOTH backends and require BOTH to reject. w6c_ww accepting
/* #94 sep layout: there is no combined unit to re-check. The
* checker reject now fires inside each driver's --sep w6c pass,
* so BOTH driver builds MUST fail. w6c_ww (via ww_ww) accepting
* here is the #13 false-ACCEPT regression. */
char xs[1024];
snprintf(xs, sizeof xs, "%s/x.s", dir);
snprintf(cmd, sizeof cmd,
"cd %s && %s/ww build -I %s %s/main.ww >/dev/null 2>&1",
dir, bin, dir, dir);
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s "
"-o %s/main %s/main.ww >/dev/null 2>&1",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) == 0) {
fprintf(stderr, "787[%s]: cstage build SUCCEEDED, "
"expected reject\n", sc->label);
rc = -1; goto done;
}
if (access(comb, 0) != 0) {
fprintf(stderr, "787[%s]: no combined.ww to re-check\n",
sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, xs, comb);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s "
"-o %s/mainww %s/main.ww >/dev/null 2>&1",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) == 0) {
fprintf(stderr, "787[%s]: w6c ACCEPTED foreign variant, "
"expected reject\n", sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, xs, comb);
if (runwait(cmd) == 0) {
fprintf(stderr, "787[%s]: w6c_ww ACCEPTED foreign variant "
fprintf(stderr, "787[%s]: ww_ww ACCEPTED foreign variant "
"(#13 false-accept), expected reject\n", sc->label);
rc = -1; goto done;
}
goto done;
}
/* cstage driver build + run: pins runtime routing. */
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build -I %s %s/main.ww",
dir, bin, dir, dir);
/* cstage driver --sep build + run: pins runtime routing. Pin
* WW_PKGCACHE under the scratch dir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s -o %s/main %s/main.ww",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "787[%s]: cstage build failed\n", sc->label);
rc = -1; goto done;
@@ -298,24 +288,27 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
rc = -1;
}
/* The #13 discriminator: raw w6c_ww on the driver-produced
* combined.ww. Pre-fix the wwstage checker REJECTED the
* cross-module variant arms (non-zero exit here). Post-fix it
* accepts AND is byte-id with cstage's w6c. */
char cs_s[1024], ws_s[1024];
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, cs_s, comb);
/* The #13 discriminator: the wwstage driver's --sep build runs the
* wwstage checker over the same units. Pre-fix it REJECTED the
* cross-module variant arms (build fails); post-fix it accepts AND
* its per-package w6c_ww asm is byte-id with cstage's. The root +
* each imported pkg compile to separate <stem>.sepwork/<pkg>.s;
* concat (sorted glob, identical set both stages) for the compare. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s -o %s/mainww %s/main.ww",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "787[%s]: w6c on combined failed\n", sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "787[%s]: w6c_ww on combined failed "
fprintf(stderr, "787[%s]: ww_ww build failed "
"(#13 cross-module variant reject?)\n", sc->label);
rc = -1; goto done;
}
char cs_s[1024], ws_s[1024];
snprintf(cs_s, sizeof cs_s, "%s/all_cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/all_ww.s", dir);
snprintf(cmd, sizeof cmd, "cat %s/main.sepwork/*.s > %s 2>/dev/null",
dir, cs_s); if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/mainww.sepwork/*.s > %s 2>/dev/null",
dir, ws_s); if (system(cmd)) {}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr, "787[%s]: cs.s/ww.s DIFFER (rule-10 byte-id "
"violation)\n", sc->label);
@@ -341,11 +334,11 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "787: w6c_ww missing — cannot run the cs==ww "
char cdrv[2100], wdrv[2100];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "787: ww_ww missing — cannot run the cs==ww "
"byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -353,7 +346,7 @@ main(void)
int n = (int)(sizeof scenarios / sizeof scenarios[0]);
int fail = 0;
for (int i = 0; i < n; i++) {
if (run_scenario(bin, w6c, w6c_ww, &scenarios[i]) != 0)
if (run_scenario(bin, cdrv, wdrv, &scenarios[i]) != 0)
fail++;
}

View File

@@ -96,11 +96,11 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "792: w6c_ww missing — cannot run the cs==ww "
char cdrv[2100], wdrv[2100];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "792: ww_ww missing — cannot run the cs==ww "
"byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -108,7 +108,7 @@ main(void)
char dir[] = "/tmp/ww792_XXXXXX";
if (mkdtemp(dir) == NULL) { fprintf(stderr, "792: mkdtemp\n"); return 1; }
char path[1024], cmd[4096], comb[1024], cs_s[1024], ws_s[1024];
char path[1024], cmd[4096], cs_s[1024], ws_s[1024];
int rc = 0;
snprintf(path, sizeof path, "%s/main.ww", dir);
@@ -117,33 +117,29 @@ main(void)
fputs(SRC, f);
fclose(f);
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
/* #94: sep layout. The cstage driver's --sep build emits the root
* unit's asm to <stem>.sepwork/__root.s via its internal w6c; pin
* WW_PKGCACHE under the scratch dir so out/.pkgcache is untouched. */
snprintf(cs_s, sizeof cs_s, "%s/main.sepwork/__root.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/mainww.sepwork/__root.s", dir);
/* cstage driver build: produces the combined.ww + must accept. */
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build -I %s %s/main.ww",
dir, bin, dir, dir);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s -o %s/main %s/main.ww",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "792: cstage build failed\n");
rc = 1; goto done;
}
if (access(comb, 0) != 0) {
fprintf(stderr, "792: no combined.ww produced\n");
fprintf(stderr, "792: cstage sep build failed\n");
rc = 1; goto done;
}
/* The #209 discriminator: raw w6c_ww on the combined. Pre-fix the
* wwstage checker REJECTED the spread-union match arms (non-zero
* exit). Post-fix it accepts AND is byte-id with cstage's w6c. */
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, cs_s, comb);
/* The #209 discriminator: the wwstage driver's --sep build runs the
* wwstage checker over the same root unit. Pre-fix it REJECTED the
* spread-union match arms (build fails); post-fix it accepts AND its
* w6c_ww-emitted __root.s is byte-id with the cstage __root.s. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s -o %s/mainww %s/main.ww",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "792: w6c on combined failed\n");
rc = 1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "792: w6c_ww on combined failed "
fprintf(stderr, "792: wwstage sep build failed "
"(#209 spread-union match reject?)\n");
rc = 1; goto done;
}

View File

@@ -96,11 +96,11 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "794: w6c_ww missing — cannot run the wwstage "
char cdrv[2100], wdrv[2100];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "794: ww_ww missing — cannot run the wwstage "
"accept gate (the whole point of this test)\n");
return 1;
}
@@ -123,9 +123,14 @@ main(void)
fclose(f);
}
/* cstage driver build (prefer is correct) emits the combined unit. */
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build -I %s %s/main.ww",
dir, bin, dir, dir);
/* #94 sep layout: cstage's --sep build (prefer is correct) compiles
* the units and links the binary; pin WW_PKGCACHE under the scratch
* dir so out/.pkgcache is untouched. NO cs==ww byte-id here — the #55
* checker fix has an open cgen-side bare-leaf sibling that diverges the
* asm independently; the sound discriminator is the wwstage ACCEPT. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s -o %s/main %s/main.ww",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "794: cstage build failed\n");
rc = 1; goto done;
@@ -138,29 +143,16 @@ main(void)
rc = 1; goto done;
}
char comb[1024];
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
if (access(comb, 0) != 0) {
fprintf(stderr, "794: no combined.ww emitted\n");
rc = 1; goto done;
}
/* Sanity: cstage's own backend re-accepts its combined. */
char cs_s[1024], ws_s[1024];
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, cs_s, comb);
/* The #55 discriminator: the wwstage driver's --sep build runs the
* wwstage checker over the same units and must ACCEPT. PRE-fix it
* rejected (bare `v` -> main.v: i64 -> return mismatch); POST-fix it
* prefers curmod=aa -> aa.v: i32 and accepts. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s -o %s/mainww %s/main.ww "
">/dev/null 2>&1",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "794: w6c on combined failed\n");
rc = 1; goto done;
}
/* The #55 discriminator: w6c_ww must ACCEPT the combined unit.
* PRE-fix it rejected (bare `v` -> main.v: i64 -> return mismatch);
* POST-fix it prefers curmod=aa -> aa.v: i32 and accepts. */
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "794: w6c_ww REJECTED the combined (#55: bare "
fprintf(stderr, "794: ww_ww REJECTED the units (#55: bare "
"value-ident resolved the wrong module's same-leaf symbol)\n");
rc = 1; goto done;
}

View File

@@ -268,51 +268,55 @@ run_row(const char *driver, const char *cwd, const struct row *r, int seq)
return rc;
}
/* asm_byte_identical — build combined.ww via the cstage driver (needs
* the -I lib fmt import resolution that raw w6c can't do), then compile
* that combined.ww with both w6c and w6c_ww and diff the asm. Proves no
* cs!=ww tag/render divergence on the widened union. */
/* asm_byte_identical — #94 sep layout: the cstage driver's --sep build
* (which needs -I lib for fmt import resolution that raw w6c can't do)
* emits per-package w6c asm to <stem>_c.sepwork/, and the wwstage driver's
* --sep build emits per-package w6c_ww asm to <stem>_w.sepwork/. Concat
* (sorted glob, identical package set) and diff — proves no cs!=ww
* tag/render divergence on the widened union. */
static int
asm_byte_identical(const char *bin, const char *cdrv, const char *cwd,
asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
const struct row *r, int seq)
{
char tmpdir[256], base[64], src[512], combined[640], cs[640], ws[640];
char tmpdir[256], base[64], src[512], cs[640], ws[640];
char cmd[2048];
snprintf(tmpdir, sizeof tmpdir, "/tmp/fic_%d_b_%d", getpid(), seq);
snprintf(base, sizeof base, "main815b");
snprintf(src, sizeof src, "%s/%s.ww", tmpdir, base);
snprintf(combined, sizeof combined, "%s/%s.combined.ww", tmpdir, base);
snprintf(cs, sizeof cs, "%s/%s_c.s", tmpdir, base);
snprintf(ws, sizeof ws, "%s/%s_w.s", tmpdir, base);
snprintf(cs, sizeof cs, "%s/all_cs.s", tmpdir);
snprintf(ws, sizeof ws, "%s/all_ww.s", tmpdir);
mkdir(tmpdir, 0755);
if (write_source(src, r->src) != 0) { cleanup_tmp(tmpdir, base); return -1; }
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, cdrv, cwd, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "fmt_int_run[byteid][%s]: combined.ww build failed\n",
r->label);
cleanup_tmp(tmpdir, base);
if (write_source(src, r->src) != 0) {
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
if (system(cmd)) {}
return -1;
}
int rc = 0;
snprintf(cmd, sizeof cmd, "%s/w6c -o %s %s 2>/dev/null", bin, cs, combined);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c timeout 180 %s build --sep -I %s/lib "
"-o %s/%s_c %s 2>/dev/null", tmpdir, tmpdir, cdrv, cwd, tmpdir, base, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "fmt_int_run[byteid][%s]: w6c errored\n", r->label);
fprintf(stderr, "fmt_int_run[byteid][%s]: cstage sep build failed\n",
r->label);
rc = -1;
}
if (rc == 0) {
snprintf(cmd, sizeof cmd, "%s/w6c_ww -o %s %s 2>/dev/null",
bin, ws, combined);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w timeout 180 %s build --sep "
"-I %s/lib -o %s/%s_w %s 2>/dev/null",
tmpdir, tmpdir, wdrv, cwd, tmpdir, base, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "fmt_int_run[byteid][%s]: w6c_ww errored\n",
r->label);
fprintf(stderr, "fmt_int_run[byteid][%s]: wwstage sep build "
"failed\n", r->label);
rc = -1;
}
}
if (rc == 0) {
snprintf(cmd, sizeof cmd, "cat %s/%s_c.sepwork/*.s > %s 2>/dev/null",
tmpdir, base, cs); if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/%s_w.sepwork/*.s > %s 2>/dev/null",
tmpdir, base, ws); if (system(cmd)) {}
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");
if (!fc || !fw) {
@@ -333,8 +337,8 @@ asm_byte_identical(const char *bin, const char *cdrv, const char *cwd,
r->label);
}
unlink(cs); unlink(ws);
cleanup_tmp(tmpdir, base);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
if (system(cmd)) {}
return rc;
}
@@ -382,7 +386,7 @@ main(void)
if (wwpresent) {
for (int i = 0; i < n; i++) {
total++;
if (asm_byte_identical(bin, cdrv, cwd, &rows[i], seq++) != 0)
if (asm_byte_identical(cdrv, wdrv, cwd, &rows[i], seq++) != 0)
fail++;
}
} else {

View File

@@ -290,9 +290,10 @@ static const struct scenario scenarios[] = {
};
static int
run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
run_scenario(const char *bin, const char *cdrv, const char *wdrv,
const struct scenario *sc)
{
(void)bin;
char dir[] = "/tmp/ww848_XXXXXX";
if (mkdtemp(dir) == NULL) {
fprintf(stderr, "848[%s]: mkdtemp failed\n", sc->label);
@@ -311,12 +312,11 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
fclose(f);
}
char comb[1024];
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
/* cstage driver build + run: pins parse + runtime field values. */
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build -I %s %s/main.ww",
dir, bin, dir, dir);
/* #94 sep layout: cstage --sep build + run pins parse + runtime field
* values; pin WW_PKGCACHE under the scratch dir. */
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s build --sep -I %s -o %s/main %s/main.ww",
dir, dir, cdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "848[%s]: cstage build failed "
"(qualified struct literal parse reject?)\n", sc->label);
@@ -330,22 +330,25 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
rc = -1;
}
/* rule-10 discriminator: raw w6c vs w6c_ww on the driver-produced
* combined.ww must be byte-identical .s. */
/* rule-10 discriminator: the wwstage driver's --sep build emits
* per-package w6c_ww asm that must be byte-identical to cstage's. The
* root + each imported pkg compile to separate <stem>.sepwork/<pkg>.s;
* concat (sorted glob, identical set both stages) for the compare. */
char cs_s[1024], ws_s[1024];
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, cs_s, comb);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s build --sep -I %s -o %s/mainww %s/main.ww",
dir, dir, wdrv, dir, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "848[%s]: w6c on combined failed\n", sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "848[%s]: w6c_ww on combined failed "
fprintf(stderr, "848[%s]: ww_ww build failed "
"(qualified struct literal parse reject?)\n", sc->label);
rc = -1; goto done;
}
snprintf(cs_s, sizeof cs_s, "%s/all_cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/all_ww.s", dir);
snprintf(cmd, sizeof cmd, "cat %s/main.sepwork/*.s > %s 2>/dev/null",
dir, cs_s); if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/mainww.sepwork/*.s > %s 2>/dev/null",
dir, ws_s); if (system(cmd)) {}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr, "848[%s]: cs.s/ww.s DIFFER (rule-10 byte-id "
"violation)\n", sc->label);
@@ -371,13 +374,13 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100], wwdump[2100], wwdump_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
char cdrv[2100], wdrv[2100], wwdump[2100], wwdump_ww[2100];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
snprintf(wwdump, sizeof wwdump, "%s/wwdump", bin);
snprintf(wwdump_ww, sizeof wwdump_ww, "%s/wwdump_ww", bin);
if (access(w6c_ww, X_OK) != 0 || access(wwdump_ww, X_OK) != 0) {
fprintf(stderr, "848: w6c_ww/wwdump_ww missing — cannot run the "
if (access(wdrv, X_OK) != 0 || access(wwdump_ww, X_OK) != 0) {
fprintf(stderr, "848: ww_ww/wwdump_ww missing — cannot run the "
"cs==ww byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -386,7 +389,7 @@ main(void)
int na = (int)(sizeof ast_cases / sizeof ast_cases[0]);
int fail = 0;
for (int i = 0; i < n; i++) {
if (run_scenario(bin, w6c, w6c_ww, &scenarios[i]) != 0)
if (run_scenario(bin, cdrv, wdrv, &scenarios[i]) != 0)
fail++;
}
for (int i = 0; i < na; i++) {

View File

@@ -120,26 +120,35 @@ static int
byteid(const char *bin)
{
int pid = getpid();
char stem[256], comb[256], cs[256], ws[256], cmd[4096];
snprintf(stem, sizeof stem, "/tmp/at911_bid_%d", pid);
snprintf(comb, sizeof comb, "%s.combined.ww", stem);
snprintf(cs, sizeof cs, "/tmp/at911_bid_c_%d.s", pid);
snprintf(ws, sizeof ws, "/tmp/at911_bid_w_%d.s", pid);
char stemc[256], stemw[256], cs[256], ws[256], cmd[4096];
snprintf(stemc, sizeof stemc, "/tmp/at911_bid_c_%d", pid);
snprintf(stemw, sizeof stemw, "/tmp/at911_bid_w_%d", pid);
snprintf(cs, sizeof cs, "/tmp/at911_bid_cs_%d.s", pid);
snprintf(ws, sizeof ws, "/tmp/at911_bid_ws_%d.s", pid);
/* `ww test -c -o <stem>` (compile-only) writes a lib/test-inclusive
* combined beside -o without running the harness. */
/* #94 sep layout: `ww test -c --sep -o <stem>` carries -T to the root
* so w6c synthesizes the test table + fork loop, and emits per-package
* asm to <stem>.sepwork/ (compile-only, no harness run; WW_PKGCACHE
* pinned to /tmp). The cstage build (w6c) and wwstage build (w6c_ww)
* must produce byte-identical asm across all packages. */
snprintf(cmd, sizeof cmd,
"%s/ww test -c -o %s test/wcc/data/attest_record.ww > /dev/null 2>&1",
bin, stem);
runwait(cmd);
if (access(comb, 0) != 0) {
fprintf(stderr, "911 FAIL: ww test -c produced no %s\n", comb);
"WW_PKGCACHE=/tmp/at911_pkgc_c_%d %s/ww test -c --sep -o %s "
"test/wcc/data/attest_record.ww > /dev/null 2>&1", pid, bin, stemc);
if (runwait(cmd) != 0) {
fprintf(stderr, "911 FAIL: cstage ww test -c --sep\n");
return 1;
}
snprintf(cmd, sizeof cmd, "%s/w6c -T %s -o %s 2>/dev/null", bin, comb, cs);
if (runwait(cmd) != 0) { fprintf(stderr, "911 FAIL: w6c -T (byteid)\n"); return 1; }
snprintf(cmd, sizeof cmd, "%s/w6c_ww -T %s -o %s 2>/dev/null", bin, comb, ws);
if (runwait(cmd) != 0) { fprintf(stderr, "911 FAIL: w6c_ww -T (byteid)\n"); return 1; }
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE=/tmp/at911_pkgc_w_%d %s/ww_ww test -c --sep -o %s "
"test/wcc/data/attest_record.ww > /dev/null 2>&1", pid, bin, stemw);
if (runwait(cmd) != 0) {
fprintf(stderr, "911 FAIL: wwstage ww_ww test -c --sep\n");
return 1;
}
snprintf(cmd, sizeof cmd, "cat %s.sepwork/*.s > %s 2>/dev/null", stemc, cs);
if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s.sepwork/*.s > %s 2>/dev/null", stemw, ws);
if (system(cmd)) {}
char bc[262144], bw[262144];
int rc = 0;
@@ -150,10 +159,11 @@ byteid(const char *bin)
fprintf(stderr, "911 FAIL: -T asm differs between stages\n");
rc = 1;
}
unlink(comb); unlink(cs); unlink(ws);
snprintf(cmd, sizeof cmd, "%s.s", stem); unlink(cmd);
snprintf(cmd, sizeof cmd, "%s.o", stem); unlink(cmd);
unlink(stem);
unlink(cs); unlink(ws);
snprintf(cmd, sizeof cmd, "rm -rf %s.sepwork %s.sepwork %s %s "
"/tmp/at911_pkgc_c_%d /tmp/at911_pkgc_w_%d",
stemc, stemw, stemc, stemw, pid, pid);
if (system(cmd)) {}
return rc;
}

View File

@@ -135,20 +135,23 @@ static const struct row rows[] = {
0 },
};
/* Compile the combined.ww (left next to the source by `ww build`) with
* both compilers and assert byte-identical asm. Returns 0 ok, 1 differ,
* -1 harness error. */
/* #94 sep layout: concat the per-package asm the cstage sep build emitted
* (<dir>/gsret_c_<i>.sepwork) and the wwstage sep build emitted
* (<dir>/gsret_w_<i>.sepwork), then assert byte-identical. Returns 0 ok,
* 1 differ, -1 harness error. */
static int
byteid(const char *bin, const char *combined, const char *dir, int i)
byteid(const char *dir, int i)
{
char cs[256], ws[256], cmd[1024];
snprintf(cs, sizeof cs, "%s/bid_cs_%d.s", dir, i);
snprintf(ws, sizeof ws, "%s/bid_ww_%d.s", dir, i);
snprintf(cmd, sizeof cmd, "%s/w6c %s > %s", bin, combined, cs);
if (runwait(cmd) != 0) return -1;
snprintf(cmd, sizeof cmd, "%s/w6c_ww %s > %s", bin, combined, ws);
if (runwait(cmd) != 0) return -1;
snprintf(cmd, sizeof cmd, "cat %s/gsret_c_%d.sepwork/*.s > %s 2>/dev/null",
dir, i, cs);
if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/gsret_w_%d.sepwork/*.s > %s 2>/dev/null",
dir, i, ws);
if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cmp -s %s %s", cs, ws);
int rc = runwait(cmd);
@@ -156,12 +159,12 @@ byteid(const char *bin, const char *combined, const char *dir, int i)
return rc == 0 ? 0 : 1;
}
/* Build `r` with `driver` in `dir`, run the binary, return its exit
* code (or -1 on build failure). `combined_out` receives the path of
* the generated <stem>.combined.ww. */
/* Build `r` with `driver` via `--sep -o <dir>/<stem>` (per-package asm in
* <dir>/<stem>.sepwork/), run the binary, return its exit code (or -1 on
* build failure). `cachetag` keys a private WW_PKGCACHE. */
static int
run_driver(const char *driver, const struct row *r, const char *dir,
int i, char *combined_out, size_t combined_sz)
int i, const char *stem, const char *cachetag)
{
char src[256], cmd[1024];
snprintf(src, sizeof src, "%s/gsret_%d.ww", dir, i);
@@ -171,7 +174,9 @@ run_driver(const char *driver, const struct row *r, const char *dir,
fputs(r->src, f);
fclose(f);
snprintf(cmd, sizeof cmd, "cd %s && %s build %s", dir, driver, src);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_%s %s build --sep -o %s/%s %s",
dir, dir, cachetag, driver, dir, stem, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: build via %s failed\n",
r->label, driver);
@@ -179,10 +184,7 @@ run_driver(const char *driver, const struct row *r, const char *dir,
}
char outbin[256];
snprintf(outbin, sizeof outbin, "%s/gsret_%d", dir, i);
if (combined_out)
snprintf(combined_out, combined_sz,
"%s/gsret_%d.combined.ww", dir, i);
snprintf(outbin, sizeof outbin, "%s/%s", dir, stem);
return runwait(outbin);
}
@@ -217,12 +219,8 @@ main(void)
int total = 0, fail = 0;
for (int i = 0; i < n; i++) {
char combined[300];
combined[0] = '\0';
/* cstage: build + run + capture combined.ww path. */
int gc = run_driver(cdrv, &rows[i], dir, i,
combined, sizeof combined);
/* cstage: --sep build + run → <dir>/gsret_c_<i>.sepwork/. */
int gc = run_driver(cdrv, &rows[i], dir, i, "gsret_c", "c");
total++;
if (gc != rows[i].want) {
fprintf(stderr, "global_sret_run[cstage][%s]: "
@@ -231,21 +229,9 @@ main(void)
fail++;
}
/* byte-id (rule 10): cs.s == ww.s on the same combined.ww. */
if (have_wwc && combined[0]) {
total++;
int bid = byteid(bin, combined, dir, i);
if (bid != 0) {
fprintf(stderr, "global_sret_run[byteid][%s]: "
"%s\n", rows[i].label,
bid == 1 ? "cs.s != ww.s" : "harness error");
fail++;
}
}
/* wwstage: build + run. */
/* wwstage: --sep build + run → <dir>/gsret_w_<i>.sepwork/. */
if (have_ww) {
int gw = run_driver(wdrv, &rows[i], dir, i, NULL, 0);
int gw = run_driver(wdrv, &rows[i], dir, i, "gsret_w", "w");
total++;
if (gw != rows[i].want) {
fprintf(stderr, "global_sret_run[wwstage][%s]: "
@@ -253,14 +239,29 @@ main(void)
rows[i].want);
fail++;
}
/* byte-id (rule 10): the per-package w6c asm (cstage sep
* build) == the w6c_ww asm (wwstage sep build). */
if (have_wwc) {
total++;
int bid = byteid(dir, i);
if (bid != 0) {
fprintf(stderr, "global_sret_run[byteid][%s]: "
"%s\n", rows[i].label,
bid == 1 ? "cs.s != ww.s"
: "harness error");
fail++;
}
}
}
char p[256];
char p[640];
snprintf(p, sizeof p, "%s/gsret_%d.ww", dir, i); unlink(p);
snprintf(p, sizeof p, "%s/gsret_%d", dir, i); unlink(p);
snprintf(p, sizeof p, "%s/gsret_%d.combined.ww", dir, i); unlink(p);
snprintf(p, sizeof p, "%s/gsret_%d.s", dir, i); unlink(p);
snprintf(p, sizeof p, "%s/gsret_%d.o", dir, i); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/gsret_c_%d.sepwork "
"%s/gsret_w_%d.sepwork %s/gsret_c_%d %s/gsret_w_%d "
"%s/pkgc_c %s/pkgc_w", dir, i, dir, i, dir, i, dir, i,
dir, dir);
if (system(p)) {}
}
rmdir(dir);

View File

@@ -164,16 +164,19 @@ static const struct scenario scenarios[] = {
{ "nonfn_dotted_table", nonfn_dotted_files, K_BUILDERR, 0 },
};
/* Build via `driver` in the fixture dir; returns the driver's build rc and
* (for K_RUN) runs the produced binary, comparing exit to want_exit. */
/* Build `driver build --sep -o <dir>/<stem>` in the fixture dir; returns
* the driver's build rc and (for K_RUN) runs the produced binary, comparing
* exit to want_exit. #94: the per-package asm lands in <dir>/<stem>.sepwork/
* (cachetag keys a private WW_PKGCACHE so out/.pkgcache is untouched). */
static int
build_run(const char *dir, const char *driver, const struct scenario *sc)
build_run(const char *dir, const char *driver, const struct scenario *sc,
const char *stem, const char *cachetag)
{
char cmd[4096], path[1024];
snprintf(cmd, sizeof cmd,
"cd %s && rm -f main main.s main.o main.combined.ww && "
"%s build -I %s %s/main.ww >/dev/null 2>%s/err",
dir, driver, dir, dir, dir);
"cd %s && WW_PKGCACHE=%s/pkgc_%s %s build --sep -I %s -o %s/%s "
"%s/main.ww >/dev/null 2>%s/err",
dir, dir, cachetag, driver, dir, dir, stem, dir, dir);
int brc = runwait(cmd);
if (sc->kind == K_BUILDERR) {
if (brc == 0) {
@@ -187,7 +190,7 @@ build_run(const char *dir, const char *driver, const struct scenario *sc)
fprintf(stderr, "949[%s]: %s build failed\n", sc->label, driver);
return -1;
}
snprintf(path, sizeof path, "%s/main", dir);
snprintf(path, sizeof path, "%s/%s", dir, stem);
int got = runwait(path);
if (got != sc->want_exit) {
fprintf(stderr, "949[%s]: %s exit %d, want %d\n",
@@ -198,8 +201,7 @@ build_run(const char *dir, const char *driver, const struct scenario *sc)
}
static int
run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
const struct scenario *sc)
run_scenario(const char *bin, const struct scenario *sc)
{
char dir[] = "/tmp/ww949_XXXXXX";
if (mkdtemp(dir) == NULL) {
@@ -207,7 +209,7 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
return -1;
}
char path[1024], cmd[4096], wwdrv[2200];
char path[1024], cmd[4096], csdrv[2200], wwdrv[2200];
int rc = 0;
for (int i = 0; sc->files[i].name; i++) {
@@ -219,50 +221,30 @@ run_scenario(const char *bin, const char *w6c, const char *w6c_ww,
fclose(f);
}
/* cstage driver build (+run for K_RUN). */
{
char csdrv[2200];
snprintf(csdrv, sizeof csdrv, "%s/ww", bin);
if (build_run(dir, csdrv, sc) != 0) { rc = -1; goto done; }
}
/* cstage driver --sep build (+run for K_RUN) → <dir>/main_c.sepwork/. */
snprintf(csdrv, sizeof csdrv, "%s/ww", bin);
if (build_run(dir, csdrv, sc, "main_c", "c") != 0) { rc = -1; goto done; }
/* wwstage driver build (+run for K_RUN) — race-free in the private
* mktemp dir. Direct proof the wwstage emits a runnable binary. */
/* wwstage driver --sep build (+run for K_RUN) — race-free in the
* private mktemp dir. Direct proof the wwstage emits a runnable
* binary. Distinct stem so its sepwork doesn't clobber cstage's. */
snprintf(wwdrv, sizeof wwdrv, "%s/ww_ww", bin);
if (build_run(dir, wwdrv, sc) != 0) { rc = -1; goto done; }
if (build_run(dir, wwdrv, sc, "main_w", "w") != 0) { rc = -1; goto done; }
if (sc->kind == K_BUILDERR) goto done;
/* Byte-id net (#263 — the wwstage-correctness proof on a gate-blind
* align-BOTH fix): raw w6c vs w6c_ww on the cstage-driver combined. */
* align-BOTH fix): the per-package w6c-emitted .s (cstage sep build)
* vs w6c_ww-emitted .s (wwstage sep build) must be byte-identical.
* Concat each stem's per-package sepwork asm (sorted glob = same set). */
{
char cs_s[1024], ws_s[1024], comb[1024];
/* regen the combined via the cstage driver (deterministic). */
snprintf(cmd, sizeof cmd,
"cd %s && %s/ww build -I %s %s/main.ww >/dev/null 2>&1",
dir, bin, dir, dir);
if (runwait(cmd) != 0) {
fprintf(stderr, "949[%s]: combined regen failed\n",
sc->label);
rc = -1; goto done;
}
snprintf(comb, sizeof comb, "%s/main.combined.ww", dir);
snprintf(cs_s, sizeof cs_s, "%s/cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", dir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c, cs_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "949[%s]: w6c on combined failed\n",
sc->label);
rc = -1; goto done;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c_ww, ws_s, comb);
if (runwait(cmd) != 0) {
fprintf(stderr, "949[%s]: w6c_ww on combined failed\n",
sc->label);
rc = -1; goto done;
}
char cs_s[1024], ws_s[1024];
snprintf(cs_s, sizeof cs_s, "%s/all_cs.s", dir);
snprintf(ws_s, sizeof ws_s, "%s/all_ww.s", dir);
snprintf(cmd, sizeof cmd, "cat %s/main_c.sepwork/*.s > %s 2>/dev/null",
dir, cs_s); if (system(cmd)) {}
snprintf(cmd, sizeof cmd, "cat %s/main_w.sepwork/*.s > %s 2>/dev/null",
dir, ws_s); if (system(cmd)) {}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr, "949[%s]: cs.s/ww.s DIFFER (rule-10 "
"byte-id violation)\n", sc->label);
@@ -289,11 +271,10 @@ main(void)
bin = absbin;
}
char w6c[2100], w6c_ww[2100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "949: w6c_ww missing — cannot run the cs==ww "
char wdrv[2100];
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "949: ww_ww missing — cannot run the cs==ww "
"byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -301,7 +282,7 @@ main(void)
int n = (int)(sizeof scenarios / sizeof scenarios[0]);
int fail = 0;
for (int i = 0; i < n; i++) {
if (run_scenario(bin, w6c, w6c_ww, &scenarios[i]) != 0)
if (run_scenario(bin, &scenarios[i]) != 0)
fail++;
}

View File

@@ -149,11 +149,10 @@ main(void)
bin = absbin;
}
char w6c[1100], w6c_ww[1100];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
if (access(w6c_ww, X_OK) != 0) {
fprintf(stderr, "defdim_struct: w6c_ww missing — cannot run "
char wdrv[1100];
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
if (access(wdrv, X_OK) != 0) {
fprintf(stderr, "defdim_struct: ww_ww missing — cannot run "
"the cs==ww byte-id gate (the whole point of this test)\n");
return 1;
}
@@ -172,17 +171,6 @@ main(void)
getpid(), i);
mkdir(tmpdir, 0755);
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build %s",
tmpdir, bin, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: cstage build failed\n",
rows[i].label);
fail++;
unlink(src); rmdir(tmpdir);
continue;
}
char base[64];
const char *b = strrchr(src, '/');
b = b ? b + 1 : src;
@@ -190,21 +178,30 @@ main(void)
char *dot = strrchr(base, '.');
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
char outbin[160], combined[96], arto[96], arts[96];
/* `ww build` writes the runnable binary into the build cwd
* (tmpdir) but its intermediates — the concatenated module
* source .combined.ww, plus .o/.s — next to the SOURCE. The
* byte-id leg compiles that combined form, not the raw src:
* w6c does no import resolution, so the cross-module row's
* `import os` only folds once concatenated. A same-module row
* combines to itself, so the one path serves every row. */
snprintf(outbin, sizeof outbin, "%s/%s", tmpdir, base);
snprintf(combined, sizeof combined,
"/tmp/wwdds_%d_%d.combined.ww", getpid(), i);
snprintf(arto, sizeof arto, "/tmp/wwdds_%d_%d.o", getpid(), i);
snprintf(arts, sizeof arts, "/tmp/wwdds_%d_%d.s", getpid(), i);
/* #94 sep layout: each driver's --sep build emits the runnable
* binary at <stem> + per-package asm under <stem>.sepwork/.
* Distinct stems so the wwstage sepwork doesn't clobber cstage's;
* pin WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. A
* cross-module row's `import os` resolves per-package, a same-
* module row is just __root — both compare via the sorted glob. */
char cmd[2048], stem_c[160], stem_w[160];
snprintf(stem_c, sizeof stem_c, "%s/%s_c", tmpdir, base);
snprintf(stem_w, sizeof stem_w, "%s/%s_w", tmpdir, base);
int got = runwait(outbin);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_c %s/ww build --sep -o %s %s",
tmpdir, tmpdir, bin, stem_c, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: cstage build failed\n",
rows[i].label);
fail++;
unlink(src);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
if (system(cmd)) {}
continue;
}
int got = runwait(stem_c);
if (got != rows[i].want_exit) {
fprintf(stderr, "row[%s]: cstage exit %d, want %d\n",
rows[i].label, got, rows[i].want_exit);
@@ -217,19 +214,21 @@ main(void)
snprintf(ws_s, sizeof ws_s, "/tmp/wwdds_%d_%d_ww.s",
getpid(), i);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c, cs_s, combined);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc_w %s/ww_ww build --sep -o %s %s "
">/dev/null 2>&1", tmpdir, tmpdir, bin, stem_w, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c failed\n", rows[i].label);
fprintf(stderr, "row[%s]: ww_ww build failed\n",
rows[i].label);
fail++;
} else {
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c_ww, ws_s, combined);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c_ww failed\n",
rows[i].label);
fail++;
} else if (slurp_eq(cs_s, ws_s) != 0) {
snprintf(cmd, sizeof cmd,
"cat %s.sepwork/*.s > %s 2>/dev/null", stem_c, cs_s);
if (system(cmd)) {}
snprintf(cmd, sizeof cmd,
"cat %s.sepwork/*.s > %s 2>/dev/null", stem_w, ws_s);
if (system(cmd)) {}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr,
"row[%s]: cstage/wwstage .s DIFFER "
"(rule-10 byte-id violation)\n",
@@ -238,8 +237,8 @@ main(void)
}
}
unlink(outbin); rmdir(tmpdir);
unlink(combined); unlink(arto); unlink(arts);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
if (system(cmd)) {}
unlink(src); unlink(cs_s); unlink(ws_s);
}

View File

@@ -294,18 +294,19 @@ static const struct trow trows[] = {
"@test fn checkfoo() void = { return; };\n" },
};
/* tbundle_reject — bundle `src` via `drv test -c`, then `comp -T` the
* combined unit; the compile must exit nonzero. Returns 0 on the
* expected reject. */
/* tbundle_reject — #94 sep layout: `<drv> test --sep` carries -T into the
* root unit's w6c pass, where the __wwtests reservation / call-arg
* typecheck must loud-reject, so the driver build must exit nonzero.
* `stage` is the cs/ww label; `drv` is the matching driver (ww / ww_ww).
* Returns 0 on the expected reject. */
static int
tbundle_reject(const char *bin, const char *comp, const char *drv,
tbundle_reject(const char *bin, const char *stage, const char *drv,
const struct trow *t, int i)
{
int pid = getpid();
char src[128], stem[128], comb[160], cmd[4096];
snprintf(src, sizeof src, "/tmp/catt_%s_%d_%d.ww", comp, pid, i);
snprintf(stem, sizeof stem, "/tmp/catt_%s_%d_%d", comp, pid, i);
snprintf(comb, sizeof comb, "%s.combined.ww", stem);
char src[160], stem[160], cmd[4096];
snprintf(src, sizeof src, "/tmp/catt_%s_%d_%d.ww", stage, pid, i);
snprintf(stem, sizeof stem, "/tmp/catt_%s_%d_%d", stage, pid, i);
FILE *f = fopen(src, "wb");
if (!f) return -1;
@@ -313,27 +314,17 @@ tbundle_reject(const char *bin, const char *comp, const char *drv,
fclose(f);
snprintf(cmd, sizeof cmd,
"%s/%s test -c -o %s %s > /dev/null 2>&1", bin, drv, stem, src);
runwait(cmd);
if (access(comb, 0) != 0) {
fprintf(stderr, "callarg_typecheck[%s][%s]: %s produced no %s\n",
comp, t->label, drv, comb);
unlink(src);
return -1;
}
snprintf(cmd, sizeof cmd, "%s/%s -T %s -o /dev/null 2>/dev/null",
bin, comp, comb);
"WW_PKGCACHE=%s.pkgc %s/%s test --sep -o %s %s > /dev/null 2>&1",
stem, bin, drv, stem, src);
int rc = runwait(cmd);
unlink(src); unlink(comb);
char tmp[200];
snprintf(tmp, sizeof tmp, "%s.s", stem); unlink(tmp);
snprintf(tmp, sizeof tmp, "%s.o", stem); unlink(tmp);
unlink(stem);
unlink(src);
snprintf(cmd, sizeof cmd, "rm -rf %s %s.sepwork %s.pkgc",
stem, stem, stem);
if (system(cmd)) {}
if (rc == 0) {
fprintf(stderr, "callarg_typecheck[%s][%s]: %s -T accepted "
"(expected a loud reject)\n", comp, t->label, comp);
fprintf(stderr, "callarg_typecheck[%s][%s]: %s test --sep "
"accepted (expected a loud reject)\n", stage, t->label, drv);
return -1;
}
return 0;
@@ -444,10 +435,9 @@ main(void)
bin = absbin;
}
char cdrv[1024], wdrv[1024], wcomp[1024];
char cdrv[1024], wdrv[1024];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
snprintf(wcomp, sizeof wcomp, "%s/w6c_ww", bin);
struct { const char *name; const char *drv; int gated; }
drivers[] = {
@@ -488,17 +478,17 @@ main(void)
}
}
/* -T faces: comp ∈ {w6c (cstage), w6c_ww (wwstage)}; bundle is built
* by the cstage driver (compiler-neutral). wwstage gated. */
/* -T faces: the reject fires inside each driver's --sep w6c/-T pass
* (cstage via ww, wwstage via ww_ww). wwstage gated on ww_ww. */
for (int i = 0; i < tn; i++) {
total++;
if (tbundle_reject(bin, "w6c", "ww", &trows[i], i) != 0)
if (tbundle_reject(bin, "cstage", "ww", &trows[i], i) != 0)
fail++;
}
if (access(wcomp, X_OK) == 0) {
if (access(wdrv, X_OK) == 0) {
for (int i = 0; i < tn; i++) {
total++;
if (tbundle_reject(bin, "w6c_ww", "ww", &trows[i],
if (tbundle_reject(bin, "wwstage", "ww_ww", &trows[i],
10 + i) != 0)
fail++;
}
@@ -513,7 +503,7 @@ main(void)
" built ok, expected reject\n");
fail++;
}
if (access(wcomp, X_OK) == 0) { /* wwstage gated (ww_ww present) */
if (access(wdrv, X_OK) == 0) { /* wwstage gated (ww_ww present) */
total++;
if (multimod_build_fail(wdrv, COLLIDE_SHAPE_MISMATCH, 0, 2) != 0) {
fprintf(stderr, "callarg_typecheck[wwstage]"

View File

@@ -139,10 +139,15 @@ run_build(const char *driver, const struct row *r, int i)
return -2;
if (write_file(dir, "main.ww", r->root) != 0) return -2;
/* cd into the build dir so the source-dir-first search path finds the
* sibling package tree (mirrors Hare's CWD == module-dir). */
snprintf(cmd, sizeof cmd, "cd '%s' && %s build main.ww 2>/dev/null",
dir, driver);
/* #94 sep layout: cd into the build dir so the source-dir-first search
* path finds the sibling package tree (mirrors Hare's CWD ==
* module-dir); --sep emits per-package units to main.sepwork/ and links
* the runnable binary at main. Pin WW_PKGCACHE under the temp dir so
* out/.pkgcache is untouched. #99 (imported-pkg `fn main` mangle under
* sep) is what makes the imported_main row link here. */
snprintf(cmd, sizeof cmd,
"cd '%s' && WW_PKGCACHE='%s/pkgc' %s build --sep -o main main.ww "
"2>/dev/null", dir, dir, driver);
int brc = runwait(cmd);
int got = -1;

View File

@@ -122,19 +122,23 @@ positive(const char *bin, const char *cwd, const char *pkg, int idx)
goto out;
}
/* Drive the package file as the build target → its decls are the
* PRIMARY module (imported==0) of the resolved unit; the producer's
* primary filter then yields exactly this package's interface. The
* library has no main, so the build's link step fails — the
* `.combined.ww` is written before codegen (cf 989_lib_byteid), and
* only it matters here, so the exit code is deliberately ignored. */
/* #94 sep layout: drive the package file as the --sep build target →
* its decls are the PRIMARY module of the resolved ROOT unit, which the
* producer's primary filter narrows to exactly this package's
* interface. The root unit's amalgamated source is composed at
* <stem>.sepwork/__root.unit.ww BEFORE codegen; the library has no
* main so the link step fails, but the unit (the only thing that
* matters here) is already written, so the exit code is deliberately
* ignored. WW_PKGCACHE is pinned under td so out/.pkgcache is
* untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s/ww build -I %s/lib %s.ww >/dev/null 2>&1",
td, bin, cwd, pkg);
"cd %s && WW_PKGCACHE=%s/pkgc timeout 180 %s/ww build --sep "
"-I %s/lib -o %s/%s %s.ww >/dev/null 2>&1",
td, td, bin, cwd, td, pkg, pkg);
runwait(cmd);
char comb[1100], cs[1100], ws[1100];
snprintf(comb, sizeof comb, "%s/%s.combined.ww", td, pkg);
snprintf(comb, sizeof comb, "%s/%s.sepwork/__root.unit.ww", td, pkg);
snprintf(cs, sizeof cs, "%s/cs.wwi", td);
snprintf(ws, sizeof ws, "%s/ww.wwi", td);
if (access(comb, 0) != 0) {