test: retarget Pattern-B gates to sep .sepwork layout; 915 off private global (M4 E3, #93)

The driver flip moves build artifacts from next-to-source <stem>.s to a
.sepwork/ scratch dir. 29 Pattern-B gates now build `ww build --sep -o <stem>`
and read <stem>.sepwork/__root.s (multi-package gates concat all
<stem>.sepwork/*.s, since cross-package labels live in per-package .s).
All intermediates redirect to /tmp (WW_PKGCACHE + -o), so the corpus runs
parallel-safe with no source-tree pollution. Tests pass now (--sep is live)
and survive the flip.

915 additionally retargeted off strconv's PRIVATE left_shift_table (a let,
not export) — which separate compilation correctly hides — onto a test-local
package that exports its own probe table (#96). The combined path only linked
it via a single-unit private leak; encapsulation is now honored under sep.

Test-only; all 5 *_ww binaries HOLD. 989_m1mangle_run deferred (blocked by
#99, imported-package fn main mangling under sep).
This commit is contained in:
2026-06-18 11:12:04 +09:00
parent 24ca570a7e
commit eb6083e54a
30 changed files with 583 additions and 324 deletions

View File

@@ -232,8 +232,12 @@ run_row(const char *driver, const struct row *r, int idx, const char *tag)
}
char cmd[2048];
/* #93 sep layout: emit asm to <entry-stem>.sepwork/<pkg>.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && %s build %s >/dev/null 2>&1", tmpdir, driver, r->entry);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc %s build --sep "
"-o \"${b%%.ww}\" \"$b\" >/dev/null 2>&1",
tmpdir, r->entry, tmpdir, driver);
if (runwait(cmd) != 0) {
fprintf(stderr,
"mklabel_modscoped[%s][%s]: build failed\n",
@@ -255,17 +259,26 @@ run_row(const char *driver, const struct row *r, int idx, const char *tag)
fail++;
}
/* Required-substring check on the emitted .s. */
char entry_s[512];
snprintf(entry_s, sizeof entry_s, "%s/%s", tmpdir, r->entry);
char *d2 = strrchr(entry_s, '.');
if (d2 && strcmp(d2, ".ww") == 0) { strcpy(d2, ".s"); }
/* Required-substring check on the emitted .s. #93: root + every
* imported pkg now compile to separate <stem>.sepwork/<pkg>.s; the
* cross-module label substrings (mod1.x / strings.x) live in the
* per-package files, so concat ALL of them (sorted glob) — a single
* __root.s read would FALSE-FAIL the multi-package rows. */
char stem[512];
snprintf(stem, sizeof stem, "%s/%s", tmpdir, r->entry);
char *d2 = strrchr(stem, '.');
if (d2 && strcmp(d2, ".ww") == 0) *d2 = '\0';
char alls[600], catcmd[1200];
snprintf(alls, sizeof alls, "%s/all.s", tmpdir);
snprintf(catcmd, sizeof catcmd, "cat %s.sepwork/*.s > %s 2>/dev/null",
stem, alls);
(void)runwait(catcmd);
size_t sz = 0;
char *asm_buf = slurp(entry_s, &sz);
char *asm_buf = slurp(alls, &sz);
if (!asm_buf) {
fprintf(stderr,
"mklabel_modscoped[%s][%s]: cannot read %s\n",
tag, r->label, entry_s);
tag, r->label, alls);
fail++;
} else {
for (int k = 0; k < r->n_required; k++) {
@@ -273,7 +286,7 @@ run_row(const char *driver, const struct row *r, int idx, const char *tag)
fprintf(stderr,
"mklabel_modscoped[%s][%s]: missing label "
"substring \"%s\" in %s\n",
tag, r->label, r->required[k], entry_s);
tag, r->label, r->required[k], alls);
fail++;
}
}

View File

@@ -199,8 +199,10 @@ cleanup_sources(const struct row *r, const char *tmpdir, const char *base)
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p) != 0) { /* best-effort */ }
if (r->modname != NULL) {
char moddir[256];
snprintf(moddir, sizeof moddir, "%s/%s", tmpdir, r->modname);
@@ -215,9 +217,17 @@ cleanup_sources(const struct row *r, const char *tmpdir, const char *base)
static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s (the post-flip layout); WW_PKGCACHE is
* pinned under tmpdir so the shared out/.pkgcache is untouched and
* the cache dies with the tmpdir. */
char stem[512], cmd[1280];
snprintf(stem, sizeof stem, "%s", src);
char *dot = strrchr(stem, '.');
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep -o %s %s "
"2>/dev/null", tmpdir, tmpdir, driver, stem, src);
return runwait(cmd);
}
@@ -266,7 +276,7 @@ check_leaq(const char *driver, const struct row *r, int seq)
return -1;
int rc = -1;
if (build_via_driver(driver, tmpdir, src) == 0) {
snprintf(asmf, sizeof asmf, "%s/%s.s", tmpdir, base);
snprintf(asmf, sizeof asmf, "%s/%s.sepwork/__root.s", tmpdir, base);
if (file_contains(asmf, r->expected_leaq)) rc = 0;
}
cleanup_sources(r, tmpdir, base);
@@ -284,7 +294,7 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
return -1;
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
/* Build a parallel tree for wwstage so we don't clobber the
* cstage .s. ww_ww writes intermediates next to the .ww source
@@ -296,7 +306,7 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
cleanup_sources(r, tdw, base);
goto out;
}
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -142,10 +142,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -153,8 +155,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -198,12 +204,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main766.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -192,10 +192,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -203,8 +205,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -246,12 +252,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main767.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -201,10 +201,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -212,8 +214,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -255,12 +261,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main769.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -214,7 +214,9 @@ cleanup_tmp(const struct row *r, const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
/* #93: the sep scratch + tmpdir-pinned pkgcache + concat scratch. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc %s/all_cs.s %s/all_ww.s",
tmpdir, base, tmpdir, tmpdir, tmpdir); if (system(p)) {}
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
@@ -233,9 +235,13 @@ cleanup_tmp(const struct row *r, const char *tmpdir, const char *base)
static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/<pkg>.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
char cmd[1280];
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -277,12 +283,21 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_sources(r, tdc, src) != 0) { cleanup_tmp(r, tdc, base); cleanup_tmp(r, tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
/* #93: root + each imported pkg now compile to separate
* <base>.sepwork/<pkg>.s; concat (sorted glob, identical set both
* stages) for the full-asm byte-id compare. */
snprintf(cs, sizeof cs, "%s/all_cs.s", tdc);
{ char cc[1280]; snprintf(cc, sizeof cc,
"cat %s/%s.sepwork/*.s > %s 2>/dev/null", tdc, base, cs);
if (system(cc)) {} }
snprintf(src, sizeof src, "%s/main770.ww", tdw);
if (write_sources(r, tdw, src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/all_ww.s", tdw);
{ char cc[1280]; snprintf(cc, sizeof cc,
"cat %s/%s.sepwork/*.s > %s 2>/dev/null", tdw, base, ws);
if (system(cc)) {} }
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -161,10 +161,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -172,8 +174,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -221,12 +227,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main771.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -190,10 +190,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -201,8 +203,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -241,12 +247,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -166,10 +166,12 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -177,8 +179,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -220,12 +226,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main773.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -177,7 +177,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[512];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
@@ -187,9 +188,13 @@ cleanup_tmp(const char *tmpdir, const char *base)
static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
char cmd[1280];
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -236,12 +241,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/main774.ww", tdw);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -253,10 +253,10 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[640];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93 sep layout: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -265,9 +265,14 @@ build_via_driver(const char *driver, const char *tmpdir, const char *cwd,
const char *src)
{
char cmd[2048];
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s; WW_PKGCACHE is pinned under tmpdir so the
* shared out/.pkgcache is untouched and the cache dies with the
* tmpdir. PRESERVES the `-I %s/lib` import-dir flag. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, driver, cwd, src);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-I %s/lib -o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver, cwd);
return runwait(cmd);
}
@@ -309,12 +314,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, cwd, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, cwd, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -277,10 +277,10 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[640];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93 sep layout: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -289,9 +289,14 @@ build_via_driver(const char *driver, const char *tmpdir, const char *cwd,
const char *src)
{
char cmd[2048];
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s; WW_PKGCACHE is pinned under tmpdir so the
* shared out/.pkgcache is untouched and the cache dies with the
* tmpdir. PRESERVES the `-I %s/lib` import-dir flag. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, driver, cwd, src);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-I %s/lib -o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver, cwd);
return runwait(cmd);
}
@@ -333,12 +338,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, cwd, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, cwd, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -252,10 +252,10 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[640];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93 sep layout: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -264,9 +264,14 @@ build_via_driver(const char *driver, const char *tmpdir, const char *cwd,
const char *src)
{
char cmd[2048];
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s; WW_PKGCACHE is pinned under tmpdir so the
* shared out/.pkgcache is untouched and the cache dies with the
* tmpdir. PRESERVES the `-I %s/lib` import-dir flag. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, driver, cwd, src);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-I %s/lib -o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver, cwd);
return runwait(cmd);
}
@@ -310,12 +315,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, cwd, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, cwd, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -433,10 +433,10 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[640];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93 sep layout: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -445,9 +445,14 @@ build_via_driver(const char *driver, const char *tmpdir, const char *cwd,
const char *src)
{
char cmd[2048];
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s; WW_PKGCACHE is pinned under tmpdir so the
* shared out/.pkgcache is untouched and the cache dies with the
* tmpdir. PRESERVES the `-I %s/lib` import-dir flag. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, driver, cwd, src);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-I %s/lib -o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver, cwd);
return runwait(cmd);
}
@@ -489,12 +494,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, cwd, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, cwd, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -108,7 +108,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[1024];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
@@ -119,8 +120,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -163,12 +168,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -206,9 +206,11 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -226,8 +228,14 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: `--sep -o <src-stem>` relocates artifacts to
* <stem>.sepwork/; WW_PKGCACHE is pinned under tmpdir so the shared
* out/.pkgcache is untouched. expect_fail rows still fail: a checker
* error makes w6c return nonzero regardless of artifact placement. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -285,12 +293,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -117,7 +117,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
rmdir(tmpdir);
@@ -137,8 +138,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -181,12 +186,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -117,7 +117,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
rmdir(tmpdir);
@@ -137,8 +138,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -181,12 +186,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -111,9 +111,11 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
/* #93: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -131,8 +133,14 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: `--sep -o <src-stem>` relocates artifacts to
* <stem>.sepwork/; WW_PKGCACHE is pinned under tmpdir so the shared
* out/.pkgcache is untouched. The value_not_type_neg row still fails:
* a checker error makes w6c return nonzero regardless of placement. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -175,12 +183,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -112,7 +112,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
rmdir(tmpdir);
@@ -132,8 +133,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -186,11 +191,11 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");
if (fc && fw) {

View File

@@ -97,7 +97,8 @@ cleanup_tmp(const char *tmpdir, const char *base)
char p[1024];
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
rmdir(tmpdir);
@@ -117,8 +118,12 @@ static int
build_via_driver(const char *driver, const char *tmpdir, const char *src)
{
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && timeout 180 %s build %s 2>/dev/null",
tmpdir, driver, src);
/* #93 sep layout: emit asm to <src-stem>.sepwork/__root.s; pin
* WW_PKGCACHE under tmpdir so out/.pkgcache is untouched. */
snprintf(cmd, sizeof cmd,
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver);
return runwait(cmd);
}
@@ -156,11 +161,11 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const struct row *r,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");
if (fc && fw) {

View File

@@ -231,10 +231,10 @@ cleanup_tmp(const char *tmpdir, const char *base)
{
char p[640];
snprintf(p, sizeof p, "%s/%s.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.s", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.o", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s.combined.ww", tmpdir, base); unlink(p);
snprintf(p, sizeof p, "%s/%s", tmpdir, base); unlink(p);
/* #93 sep layout: the sep scratch dir + the tmpdir-pinned pkgcache. */
snprintf(p, sizeof p, "rm -rf %s/%s.sepwork %s/pkgc", tmpdir, base, tmpdir);
if (system(p)) {} /* best-effort */
rmdir(tmpdir);
}
@@ -243,9 +243,14 @@ build_via_driver(const char *driver, const char *tmpdir, const char *cwd,
const char *src)
{
char cmd[2048];
/* #93 sep layout: `--sep -o <src-stem>` emits the asm to
* <stem>.sepwork/__root.s; WW_PKGCACHE is pinned under tmpdir so the
* shared out/.pkgcache is untouched and the cache dies with the
* tmpdir. PRESERVES the `-I %s/lib` import-dir flag. */
snprintf(cmd, sizeof cmd,
"cd %s && timeout 180 %s build -I %s/lib %s 2>/dev/null",
tmpdir, driver, cwd, src);
"cd %s && b='%s'; WW_PKGCACHE=%s/pkgc timeout 180 %s build --sep "
"-I %s/lib -o \"${b%%.ww}\" \"$b\" 2>/dev/null",
tmpdir, src, tmpdir, driver, cwd);
return runwait(cmd);
}
@@ -287,12 +292,12 @@ asm_byte_identical(const char *cdrv, const char *wdrv, const char *cwd,
if (write_source(src, r->src) != 0) { cleanup_tmp(tdc, base); cleanup_tmp(tdw, base); return -1; }
int rc = -1;
if (build_via_driver(cdrv, tdc, cwd, src) != 0) goto out;
snprintf(cs, sizeof cs, "%s/%s.s", tdc, base);
snprintf(cs, sizeof cs, "%s/%s.sepwork/__root.s", tdc, base);
snprintf(src, sizeof src, "%s/%s.ww", tdw, base);
if (write_source(src, r->src) != 0) goto out;
if (build_via_driver(wdrv, tdw, cwd, src) != 0) goto out;
snprintf(ws, sizeof ws, "%s/%s.s", tdw, base);
snprintf(ws, sizeof ws, "%s/%s.sepwork/__root.s", tdw, base);
FILE *fc = fopen(cs, "rb");
FILE *fw = fopen(ws, "rb");

View File

@@ -32,15 +32,17 @@
* shapes (defensive case; not exercised in committed code per
* design-pass audit) aren't disturbed.
*
* Each row carries (a) cstage `ww build` + run asserting the exit
* code (the cstage-segfault repro now exits cleanly) and (b) a w6c vs
* w6c_ww `.s` cmp (rule-10 byte-id). Imports `strconv` because its
* `let left_shift_table: [65]u16` is the canonical reviewer-stofdata
* probe surface for this bug.
* Each row carries a `ww build` + run asserting the exit code (the
* cstage-segfault repro now exits cleanly). Single-file rows also carry
* a w6c vs w6c_ww `.s` cmp (rule-10 byte-id); the cross-package module
* rows gate on runtime exit here and are byte-id-covered cross-package
* by 994. The probe table is a test-local exported `[8]u16` (package
* wcmodarr — see the #93 retarget note below; it replaced strconv's
* private `let left_shift_table`, which separate compilation correctly
* hides).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -54,55 +56,67 @@ runwait(const char *cmd)
return -1;
}
struct row { const char *label; const char *src; int want_exit; };
struct row {
const char *label;
const char *src; /* main.ww content */
const char *modname; /* exported-probe-table package, or NULL */
const char *modsrc; /* that package's content, or NULL */
int want_exit;
};
/* #93 (915 encapsulation retarget, ken-t): the module rows used to read
* strconv's PRIVATE `let left_shift_table` — which separate compilation
* CORRECTLY hides (the combined path only "worked" because the private
* symbol leaked into one unit). Retargeted to a test-LOCAL package that
* EXPORTS its own probe table: the same cross-package `mod.arr[i]` cgen
* shape (LEAQ base + element-size stride, #128b), encapsulation-faithful
* and sep-linkable. (The deeper checker tighten — loud-reject a cross-pkg
* private ref — is tracked as #45; NOT attempted here.) Table prefix is
* the same u16 sequence strconv used, so the expected exits are unchanged
* (idx0→0, idx2→0x0801&0xFF=1, idx4→0x1006&0xFF=6). */
#define PROBE_MOD \
"export let probe_table: [8]u16 = [0u16, 0x0800u16, 0x0801u16, " \
"0x0803u16, 0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];\n"
static const struct row rows[] = {
/* The reviewer-stofdata probe: indexed read on an imported [N]u16
* at idx=0. Pre-fix cstage segfaulted on nontrivial indices and
* MOVZBQ-loaded the wrong byte; here at idx=0 the wrong-stride
* doesn't matter, so the test exit reflects the load-width fix:
* MOVZWQ now reads the full u16 = 0x0000 → exit 0. */
/* Indexed read on an imported (exported) [N]u16 at idx=0 — load-
* width fix: MOVZWQ reads the full u16 = 0x0000 → exit 0. */
{ "mod_u16_idx0",
"package main;\n"
"import strconv;\n"
"import wcmodarr;\n"
"export fn main() i32 = {\n"
" let v: u32 = (strconv.left_shift_table[0]: u32);\n"
" let v: u32 = (wcmodarr.probe_table[0]: u32);\n"
" return v: i32;\n"
"};\n", 0 },
/* Nontrivial idx: pre-fix segfault repro. table[2] = 0x0801;
"};\n", "wcmodarr", PROBE_MOD, 0 },
/* Nontrivial idx pre-fix segfault repro. table[2] = 0x0801;
* 0x0801 mod 256 = 1. */
{ "mod_u16_idx2",
"package main;\n"
"import strconv;\n"
"import wcmodarr;\n"
"export fn main() i32 = {\n"
" let v: u32 = (strconv.left_shift_table[2]: u32);\n"
" let v: u32 = (wcmodarr.probe_table[2]: u32);\n"
" return v: i32;\n"
"};\n", 1 },
"};\n", "wcmodarr", PROBE_MOD, 1 },
/* Further idx — pins per-element stride. table[4] = 0x1006;
* 0x1006 mod 256 = 6. */
{ "mod_u16_idx4",
"package main;\n"
"import strconv;\n"
"import wcmodarr;\n"
"export fn main() i32 = {\n"
" let v: u32 = (strconv.left_shift_table[4]: u32);\n"
" let v: u32 = (wcmodarr.probe_table[4]: u32);\n"
" return v: i32;\n"
"};\n", 6 },
"};\n", "wcmodarr", PROBE_MOD, 6 },
/* Local-array control: confirms the existing IDENT-base path is
* unchanged by the #128b cgindex edit. Pre-fix already worked; the
* fix is gated by `bt == NULL` so this row's byte-id is
* preserved. */
* unchanged by the #128b cgindex edit. */
{ "local_arr_control",
"package main;\n"
"export fn main() i32 = {\n"
" let a: [4]u16 = [10u16, 20u16, 30u16, 40u16];\n"
" let v: u32 = (a[2]: u32);\n"
" return v: i32;\n"
"};\n", 30 },
/* Same-package access (NOT module-qualified) — pins that the
* existing in-package IDENT path stays unchanged. left_shift_table
* exists in strconv; access from within `package strconv` would be
* IDENT-base. Wrap in a tiny helper here to keep test self-
* contained; uses local table. */
"};\n", NULL, NULL, 30 },
/* Same-package (NOT module-qualified) access — pins the in-package
* IDENT path stays unchanged; uses a local table. */
{ "local_u16_idx_nonzero",
"package main;\n"
"export fn main() i32 = {\n"
@@ -110,8 +124,8 @@ static const struct row rows[] = {
"0x1006u16, 0x1009u16, 0x100Du16, 0x1812u16];\n"
" let v: u32 = (t[2]: u32);\n"
" return v: i32;\n"
"};\n", 1 },
{ NULL, NULL, 0 }
"};\n", NULL, NULL, 1 },
{ NULL, NULL, NULL, NULL, 0 }
};
static int
@@ -155,96 +169,97 @@ main(void)
int n = 0, fail = 0;
for (int i = 0; rows[i].src; i++, n++) {
char src[64];
snprintf(src, sizeof src, "/tmp/wwmoda_%d_%d.ww", getpid(), i);
FILE *f = fopen(src, "wb");
if (f == NULL) { fail++; continue; }
fputs(rows[i].src, f);
fclose(f);
char tmpdir[64];
char tmpdir[96];
snprintf(tmpdir, sizeof tmpdir, "/tmp/wwmoda_%d_d_%d",
getpid(), i);
mkdir(tmpdir, 0755);
char src[160];
snprintf(src, sizeof src, "%s/main915.ww", tmpdir);
FILE *f = fopen(src, "wb");
if (f == NULL) { fail++; rmdir(tmpdir); continue; }
fputs(rows[i].src, f);
fclose(f);
char cmd[2048];
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build %s",
tmpdir, bin, src);
/* Exported-probe-table package lives at <tmpdir>/<mod>/<mod>.ww
* so the sep dep-scan (rooted at the entry's dir) resolves the
* `import <mod>;`. */
if (rows[i].modname != NULL) {
char moddir[224], modf[320];
snprintf(moddir, sizeof moddir, "%s/%s", tmpdir,
rows[i].modname);
mkdir(moddir, 0755);
snprintf(modf, sizeof modf, "%s/%s.ww", moddir,
rows[i].modname);
FILE *mf = fopen(modf, "wb");
if (mf == NULL) {
fail++;
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
(void)runwait(cmd);
continue;
}
fputs(rows[i].modsrc, mf);
fclose(mf);
}
/* #93 sep layout: build via `--sep -o <stem>` (the exported
* probe table links across packages under separate compilation);
* WW_PKGCACHE pinned under tmpdir. */
char stem[200];
snprintf(stem, sizeof stem, "%s/main915", tmpdir);
snprintf(cmd, sizeof cmd,
"cd %s && WW_PKGCACHE=%s/pkgc %s/ww build --sep -o %s %s "
">/dev/null 2>&1", tmpdir, tmpdir, bin, stem, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: cstage build failed\n",
rows[i].label);
fail++;
unlink(src); rmdir(tmpdir);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
(void)runwait(cmd);
continue;
}
char outbin[128];
const char *base = strrchr(src, '/');
base = base ? base + 1 : src;
snprintf(outbin, sizeof outbin, "%s/%s", tmpdir, base);
char *dot = strrchr(outbin, '.');
if (dot && strcmp(dot, ".ww") == 0) *dot = '\0';
int got = runwait(outbin);
int got = runwait(stem);
if (got != rows[i].want_exit) {
fprintf(stderr, "row[%s]: cstage exit %d, want %d\n",
rows[i].label, got, rows[i].want_exit);
fail++;
}
unlink(outbin); rmdir(tmpdir);
/* Byte-id only meaningful when the source compiles standalone
* to a .s. Module-imported rows need the combined.ww shape
* (which `ww build` produces inside tmpdir); we already ran
* that above. For the byte-id leg, point at the combined.ww. */
char combined[160];
snprintf(combined, sizeof combined, "%s/%s.combined.ww",
tmpdir, base);
(void)combined;
/* Both stages emit on the original .ww directly; the
* combined.ww has the same surface for cgen purposes. We use
* the original src for byte-id since w6c/w6c_ww handle the
* import resolution when invoked on the file with -I and the
* lib search. The probe row asserts module-qualified shape
* via direct w6c{,_ww} on the .ww; if the stage can't find
* the import, the build above would have failed first. */
char cs_s[64], ws_s[64];
snprintf(cs_s, sizeof cs_s, "/tmp/wwmoda_%d_%d_cs.s",
getpid(), i);
snprintf(ws_s, sizeof ws_s, "/tmp/wwmoda_%d_%d_ww.s",
getpid(), i);
/* Skip byte-id leg for rows that need imports — w6c/w6c_ww
* standalone won't resolve `import strconv;`. The runtime
* leg above (via `ww build`) IS the byte-id+correctness
* gate for these rows; the full bootstrap byte-id (994) is
* the corpus check. */
int needs_import = (strstr(rows[i].src, "import ") != NULL);
if (!needs_import) {
/* Byte-id leg — bare w6c vs w6c_ww (the compiler binaries, NOT
* the driver, so layout-invariant). Only single-file rows can be
* fed standalone; the module rows' runtime exit IS their gate
* (+ the 994 bootstrap corpus for the cross-stage byte-id). */
if (rows[i].modname == NULL) {
char cs_s[200], ws_s[200];
snprintf(cs_s, sizeof cs_s, "%s/cs.s", tmpdir);
snprintf(ws_s, sizeof ws_s, "%s/ww.s", tmpdir);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c, cs_s, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c failed\n",
rows[i].label);
fail++; unlink(src); continue;
}
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c_ww, ws_s, src);
if (runwait(cmd) != 0) {
fprintf(stderr, "row[%s]: w6c_ww failed\n",
rows[i].label);
fail++; unlink(src); unlink(cs_s); continue;
}
if (slurp_eq(cs_s, ws_s) != 0) {
fprintf(stderr,
"row[%s]: cstage/wwstage .s DIFFER "
"(rule-10 byte-id violation)\n",
rows[i].label);
fail++;
} else {
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null",
w6c_ww, ws_s, src);
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) {
fprintf(stderr,
"row[%s]: cstage/wwstage .s DIFFER "
"(rule-10 byte-id violation)\n",
rows[i].label);
fail++;
}
}
unlink(cs_s); unlink(ws_s);
}
unlink(src);
snprintf(cmd, sizeof cmd, "rm -rf %s", tmpdir);
(void)runwait(cmd);
}
if (fail) {

View File

@@ -174,9 +174,18 @@ main(void)
for (int s = 0; s < 2; s++) {
snprintf(stg[s].prog, sizeof stg[s].prog, "%s/prog.%s", td, stg[s].tag);
snprintf(stg[s].sfile, sizeof stg[s].sfile, "%s/prog.%s.s", td, stg[s].tag);
/* #93 sep layout: `--sep -o <prog>` splits the asm across
* <prog>.sepwork/<pkg>.s — the bare user `TEXT run,` lands in
* __root.s and the imported `TEXT aa.run,` in aa.s. Concat all
* the per-unit .s (sorted glob order is deterministic) into the
* flat <prog>.s the label-count + byte-id checks consume. The
* `-I %s` source path is preserved; WW_PKGCACHE is pinned under
* the tmpdir so the shared out/.pkgcache stays untouched. */
snprintf(cmd, sizeof cmd,
"timeout 240 %s/%s build -o %s -I %s %s >/dev/null 2>&1",
bin, stg[s].drv, stg[s].prog, td, rootww);
"WW_PKGCACHE=%s/pkgc timeout 240 %s/%s build --sep -o %s "
"-I %s %s >/dev/null 2>&1 && cat %s.sepwork/*.s > %s",
td, bin, stg[s].drv, stg[s].prog, td, rootww,
stg[s].prog, stg[s].sfile);
if (runwait(cmd) != 0) {
fprintf(stderr, "84 FAIL: %s build\n", stg[s].drv);
fail++;

View File

@@ -51,13 +51,23 @@ static const struct check checks[] = {
{ "TEXT utf8.runesz,", 0 },
};
/* build_s — build `src` to `<stem>.s` via `driver`; returns 0 on success. */
/* build_s — build `src` via `driver`, leaving the unit asm at `<stem>.s`;
* returns 0 on success.
* #93 sep layout: `--sep -o <stem>` splits the asm across
* <stem>.sepwork/<pkg>.s (root in __root.s, the imported encoding.utf8 in
* encoding.utf8.s). The mangled `encoding.utf8.runesz` definition lives in
* the per-pkg .s and `TEXT main,` in __root.s, so we CONCAT all the
* per-unit .s (sorted glob order is deterministic) into a single <stem>.s
* for the needle scans + the rule-10 cmp downstream. WW_PKGCACHE is pinned
* beside <stem> to leave the shared out/.pkgcache untouched. */
static int
build_s(const char *driver, const char *src, const char *stem)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "%s build -o '%s' '%s' 2>/dev/null",
driver, stem, src);
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE='%s.pkgc' timeout 180 %s build --sep -o '%s' '%s' "
"2>/dev/null && cat '%s.sepwork/'*.s > '%s.s'",
stem, driver, stem, src, stem, stem);
return runwait(cmd);
}
@@ -137,7 +147,8 @@ main(void)
}
char cmd[256];
snprintf(cmd, sizeof cmd, "rm -f '%s' '%s'* '%s'*", src, cstem, wstem);
/* #93: -rf to also drop the per-stem .sepwork scratch + pinned pkgc. */
snprintf(cmd, sizeof cmd, "rm -rf '%s' '%s'* '%s'*", src, cstem, wstem);
runwait(cmd);
if (fail) {

View File

@@ -111,13 +111,17 @@ write_src(const char *path, const struct row *r)
}
/* build_run — build `src` to `<stem>` binary via `driver`, run it; return
* the binary's exit code, or -1 on a build failure. */
* the binary's exit code, or -1 on a build failure.
* #93 sep layout: `--sep -o <stem>` emits per-unit asm under
* <stem>.sepwork/ (root in __root.s, encoding.utf8 in encoding.utf8.s); the
* binary is still <stem>. WW_PKGCACHE is pinned beside <stem>. */
static int
build_run(const char *driver, const char *src, const char *stem)
{
char cmd[1024];
snprintf(cmd, sizeof cmd, "%s build -o '%s' '%s' 2>/dev/null",
driver, stem, src);
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE='%s.pkgc' timeout 180 %s build --sep -o '%s' '%s' "
"2>/dev/null", stem, driver, stem, src);
if (runwait(cmd) != 0) return -1;
return runwait(stem);
}
@@ -172,9 +176,9 @@ main(void)
fail++;
}
char cmd[256];
snprintf(cmd, sizeof cmd, "rm -f '%s' '%s' '%s.s' "
"'%s.o' '%s.combined.ww'", src, stem, stem, stem,
stem);
/* #93: drop the sep scratch + pinned pkgcache too. */
snprintf(cmd, sizeof cmd, "rm -rf '%s' '%s' "
"'%s.sepwork' '%s.pkgc'", src, stem, stem, stem);
runwait(cmd);
}
}
@@ -183,27 +187,38 @@ main(void)
if (access(wdrv, X_OK) == 0) {
total++;
const struct row *r = &rows[n - 1]; /* all_arms */
char csrc[80], cstem[80], cs[96], ws[96], cmd[512];
char csrc[80], cstem[80], cmd[512];
snprintf(csrc, sizeof csrc, "/tmp/m1union_bid_%d.ww", pid);
snprintf(cstem, sizeof cstem, "/tmp/m1union_bid_c_%d", pid);
snprintf(cs, sizeof cs, "%s.s", cstem);
char wstem[80];
snprintf(wstem, sizeof wstem, "/tmp/m1union_bid_w_%d", pid);
snprintf(ws, sizeof ws, "%s.s", wstem);
if (write_src(csrc, r) == 0) {
snprintf(cmd, sizeof cmd, "%s build -o '%s' '%s' "
"2>/dev/null", cdrv, cstem, csrc);
/* #93 sep layout: each stage emits per-unit asm under
* <stem>.sepwork/ (__root.s + encoding.utf8.s); the
* rule-10 byte-id gate becomes a recursive diff of the
* two sepwork trees. */
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE='%s.pkgc' %s build --sep -o '%s' '%s' "
"2>/dev/null", cstem, cdrv, cstem, csrc);
int cb = runwait(cmd);
snprintf(cmd, sizeof cmd, "%s build -o '%s' '%s' "
"2>/dev/null", wdrv, wstem, csrc);
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE='%s.pkgc' %s build --sep -o '%s' '%s' "
"2>/dev/null", wstem, wdrv, wstem, csrc);
int wb = runwait(cmd);
if (cb != 0 || wb != 0) {
fprintf(stderr, "m1union_run: byte-id build "
"failed (cstage=%d wwstage=%d)\n", cb, wb);
fail++;
} else {
snprintf(cmd, sizeof cmd, "cmp -s '%s' '%s'",
cs, ws);
/* Concat each tree's per-unit *.s (sorted glob
* order is deterministic) and cmp — sidesteps a
* stray <pkg>.md5tmp the wwstage drops in the
* sep dir, which a full `diff -r` would flag. */
snprintf(cmd, sizeof cmd,
"cat '%s.sepwork/'*.s > '%s.scat' && "
"cat '%s.sepwork/'*.s > '%s.scat' && "
"cmp -s '%s.scat' '%s.scat'",
cstem, cstem, wstem, wstem, cstem, wstem);
if (runwait(cmd) != 0) {
fprintf(stderr, "m1union_run: cstage.s "
"!= wwstage.s (byte-id break)\n");
@@ -211,7 +226,7 @@ main(void)
}
}
}
snprintf(cmd, sizeof cmd, "rm -f '%s' '%s'* '%s'*", csrc,
snprintf(cmd, sizeof cmd, "rm -rf '%s' '%s'* '%s'*", csrc,
cstem, wstem);
runwait(cmd);
}

View File

@@ -144,8 +144,13 @@ run_build(const char *driver, const struct row *r, int i)
snprintf(dir, sizeof dir, "/tmp/m1usehint_%d_%d", getpid(), i);
if (layout(dir, r) != 0) return -2;
snprintf(cmd, sizeof cmd, "cd '%s' && %s build main.ww 2>/dev/null",
dir, driver);
/* #93 sep layout: `--sep -o main` emits per-unit asm under
* main.sepwork/ (each dir-pkg in its own <pkgpath>.s); binary stays
* <dir>/main. WW_PKGCACHE pinned under <dir>; the whole tree is
* rm -rf'd below, so the scratch dies with it. */
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;
@@ -165,18 +170,29 @@ static int
byteid(const char *cdrv, const char *wdrv, const struct row *r)
{
char dir[64], cmd[2048];
char cs[96], ws[96];
char cstem[80], wstem[80], cs[96], ws[96];
snprintf(dir, sizeof dir, "/tmp/m1usehint_bid_%d", getpid());
if (layout(dir, r) != 0) return -1;
snprintf(cs, sizeof cs, "/tmp/m1usehint_c_%d.s", getpid());
snprintf(ws, sizeof ws, "/tmp/m1usehint_w_%d.s", getpid());
snprintf(cstem, sizeof cstem, "/tmp/m1usehint_c_%d", getpid());
snprintf(wstem, sizeof wstem, "/tmp/m1usehint_w_%d", getpid());
snprintf(cs, sizeof cs, "%s.s", cstem);
snprintf(ws, sizeof ws, "%s.s", wstem);
/* #93 sep layout: each stage emits per-unit asm under <stem>.sepwork/
* (a.math.s, b.math.s, one.s, two.s, __root.s). The rule-10 byte-id
* gate concats each tree's per-unit *.s (sorted glob order is
* deterministic) into a flat <stem>.s and cmps the two. WW_PKGCACHE
* is pinned per-stem so the shared out/.pkgcache stays untouched. */
int rc = -1;
snprintf(cmd, sizeof cmd, "cd '%s' && %s build -o '/tmp/m1usehint_c_%d' "
"main.ww 2>/dev/null", dir, cdrv, getpid());
snprintf(cmd, sizeof cmd,
"cd '%s' && WW_PKGCACHE='%s.pkgc' %s build --sep -o '%s' "
"main.ww 2>/dev/null && cat '%s.sepwork/'*.s > '%s'",
dir, cstem, cdrv, cstem, cstem, cs);
int cb = runwait(cmd);
snprintf(cmd, sizeof cmd, "cd '%s' && %s build -o '/tmp/m1usehint_w_%d' "
"main.ww 2>/dev/null", dir, wdrv, getpid());
snprintf(cmd, sizeof cmd,
"cd '%s' && WW_PKGCACHE='%s.pkgc' %s build --sep -o '%s' "
"main.ww 2>/dev/null && cat '%s.sepwork/'*.s > '%s'",
dir, wstem, wdrv, wstem, wstem, ws);
int wb = runwait(cmd);
if (cb == 0 && wb == 0) {
snprintf(cmd, sizeof cmd, "cmp -s '%s' '%s'", cs, ws);
@@ -185,8 +201,7 @@ byteid(const char *cdrv, const char *wdrv, const struct row *r)
fprintf(stderr, "m1usehint_run: byte-id build failed "
"(cstage=%d wwstage=%d)\n", cb, wb);
}
snprintf(cmd, sizeof cmd, "rm -rf '%s' '/tmp/m1usehint_c_%d'* "
"'/tmp/m1usehint_w_%d'*", dir, getpid(), getpid());
snprintf(cmd, sizeof cmd, "rm -rf '%s' '%s'* '%s'*", dir, cstem, wstem);
runwait(cmd);
return rc;
}

View File

@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <glob.h>
#include <sys/wait.h>
static int
@@ -102,34 +103,64 @@ main(void)
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
const char *files[] = {
/* hand-written runtime — small, covers MOVQ/LEAQ/CALL/SYSCALL/RET. */
"rt/start.s",
"rt/syscall.s",
"rt/abort.s",
"rt/alloc.s",
"rt/streq.s",
/* generated .s from the existing selfhost stack — large,
* exercises every encoding w6c emits (the only way to hit
* the long tail of operand shapes). */
"selfhost/cmd/wwdump/main.s",
"selfhost/cmd/w6l/main.s",
"selfhost/cmd/w6a/main.s",
NULL,
/* #93 sep layout: the selfhost tools no longer leave a single
* next-to-source main.s. Self-build one real tool via `ww build
* --sep` into /tmp and feed EVERY emitted <tool>.sepwork/<pkg>.s as
* the generated-asm corpus — the root tool code plus each dep
* package's .s (richer than the old 3 monolithic main.s). Flip-
* invariant: --sep is live on trunk, default post-flip. */
char stem[256], cmd[4096];
snprintf(stem, sizeof stem, "/tmp/wwa_%d_sh", getpid());
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE=%s.pkgc timeout 400 %s/ww build --sep -o %s "
"%s/selfhost/cmd/w6a >/dev/null 2>&1", stem, bin, stem, cwd);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6a_ww FAIL: cannot sep-build selfhost/cmd/w6a\n");
return 1;
}
/* hand-written runtime — small, covers MOVQ/LEAQ/CALL/SYSCALL/RET;
* exists in-tree regardless of layout (not a casualty). */
const char *rtfiles[] = {
"rt/start.s", "rt/syscall.s", "rt/abort.s",
"rt/alloc.s", "rt/streq.s", NULL,
};
int fail = 0;
int n = 0;
for (int i = 0; files[i]; i++) {
for (int i = 0; rtfiles[i]; i++) {
char p[2048];
snprintf(p, sizeof p, "%s/%s", cwd, files[i]);
snprintf(p, sizeof p, "%s/%s", cwd, rtfiles[i]);
if (diff_one(bin, p) != 0) fail++;
n++;
}
/* generated .s from the real tool's sep build — large, exercises
* every encoding w6c emits (the long tail of operand shapes). */
glob_t g;
char pat[320];
snprintf(pat, sizeof pat, "%s.sepwork/*.s", stem);
if (glob(pat, 0, NULL, &g) == 0) {
for (size_t i = 0; i < g.gl_pathc; i++) {
/* skip empty units (e.g. an import-only rt.s). */
FILE *f = fopen(g.gl_pathv[i], "rb");
long sz = -1;
if (f) { fseek(f, 0, SEEK_END); sz = ftell(f); fclose(f); }
if (sz <= 0) continue;
if (diff_one(bin, g.gl_pathv[i]) != 0) fail++;
n++;
}
globfree(&g);
}
snprintf(cmd, sizeof cmd, "rm -rf %s.sepwork %s.pkgc %s",
stem, stem, stem);
if (system(cmd)) {}
if (fail) {
fprintf(stderr, "w6a_ww: %d/%d diff(s) failed\n", fail, n);
return 1;
}
printf("w6a_ww: byte-identical to C w6a on %d corpus files "
"(rt/*.s + selfhost generated main.s)\n", n);
"(rt/*.s + selfhost/cmd/w6a sep-built .s)\n", n);
return 0;
}

View File

@@ -56,40 +56,57 @@ slurp(const char *path, char **outbuf, size_t *outlen)
return 0;
}
/* link `inputs` (space-separated, the caller's responsibility to quote)
* with both linkers, compare bytes. */
/* #93 sep layout: the flip stops emitting a monolithic <tool>/main.o;
* the linkable unit is now the per-package .o + reverse-topo .a set the
* sep driver assembles (a raw `w6l <root>.o *.a libwwrt.a` from the test
* side fails — `undefined reference` — because it can't reproduce the
* driver's topo order). So isolate the LINKER by driving the sep build's
* own link step twice over identical .o inputs (a shared pkgcache makes
* the second build's package objects a cache hit → only the final link
* re-runs): once with the default C w6l, once with WW_W6L=w6l_ww. Diff
* the two real tool binaries. Exercises the full archive two-pass loader
* + reverse-topo .a resolution — a stronger link than the old single
* main.o. Flip-invariant: --sep is live on trunk, default post-flip. */
static int
diff_one(const char *bin, const char *label, const char *inputs)
build_and_diff(const char *bin, const char *cwd, const char *tool,
const char *cache)
{
char co[64], wo[64], cmd[4096];
snprintf(co, sizeof co, "/tmp/wwl_%d_c", getpid());
snprintf(wo, sizeof wo, "/tmp/wwl_%d_w", getpid());
char cstem[256], wstem[256], cmd[4096];
snprintf(cstem, sizeof cstem, "/tmp/wwl_%d_c", getpid());
snprintf(wstem, sizeof wstem, "/tmp/wwl_%d_w", getpid());
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6l -o %s %s 2>/dev/null", bin, co, inputs);
snprintf(cmd, sizeof cmd,
"WW_PKGCACHE=%s timeout 300 %s/ww build --sep -o %s "
"%s/selfhost/cmd/%s >/dev/null 2>&1", cache, bin, cstem, cwd, tool);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6l_ww FAIL: C w6l errored on %s\n", label);
unlink(co);
fprintf(stderr, "w6l_ww FAIL: C-link sep-build of %s\n", tool);
return -1;
}
snprintf(cmd, sizeof cmd, "timeout 180 %s/w6l_ww -o %s %s 2>/dev/null", bin, wo, inputs);
snprintf(cmd, sizeof cmd,
"WW_W6L=%s/w6l_ww WW_PKGCACHE=%s timeout 300 %s/ww build --sep "
"-o %s %s/selfhost/cmd/%s >/dev/null 2>&1",
bin, cache, bin, wstem, cwd, tool);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6l_ww FAIL: ww w6l errored on %s\n", label);
unlink(co); unlink(wo);
fprintf(stderr, "w6l_ww FAIL: ww-link sep-build of %s\n", tool);
snprintf(cmd, sizeof cmd, "rm -rf %s %s.sepwork", cstem, cstem);
if (system(cmd)) {}
return -1;
}
char *bc = NULL, *bw = NULL;
size_t nc = 0, nw = 0;
int rc = 0;
if (slurp(co, &bc, &nc) < 0 || slurp(wo, &bw, &nw) < 0) {
fprintf(stderr, "w6l_ww FAIL: cannot read output for %s\n", label);
if (slurp(cstem, &bc, &nc) < 0 || slurp(wstem, &bw, &nw) < 0) {
fprintf(stderr, "w6l_ww FAIL: cannot read output for %s\n", tool);
rc = -1;
} else if (nc != nw || memcmp(bc, bw, nc) != 0) {
fprintf(stderr, "w6l_ww FAIL: %s — C %zu vs ww %zu bytes\n",
label, nc, nw);
tool, nc, nw);
rc = -1;
}
free(bc); free(bw);
unlink(co); unlink(wo);
snprintf(cmd, sizeof cmd, "rm -rf %s %s %s.sepwork %s.sepwork",
cstem, wstem, cstem, wstem);
if (system(cmd)) {}
return rc;
}
@@ -102,36 +119,31 @@ main(void)
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
struct {
const char *label;
const char *inputs_fmt; /* %s = cwd */
} cases[] = {
/* Real bootstrap-style links: every selfhost main.o paired
* with libwwrt.a. Exercises both the .o code path and the
* archive two-pass loader (rt_malloc / rt_syscall / rt_abort
* are pulled from libwwrt.a as undefs are encountered). */
{ "wwdump+libwwrt",
"%s/selfhost/cmd/wwdump/main.o %s/out/lib/libwwrt.a" },
{ "w6a+libwwrt",
"%s/selfhost/cmd/w6a/main.o %s/out/lib/libwwrt.a" },
{ "w6l+libwwrt",
"%s/selfhost/cmd/w6l/main.o %s/out/lib/libwwrt.a" },
{ NULL, NULL },
};
/* Real bootstrap-style links: each selfhost tool's full sep build
* (root .o + reverse-topo dep .a set + libwwrt.a). One shared
* pkgcache across all builds so each tool's second (w6l_ww) build
* re-links only. (wwdump is excluded — it imports the compiler-
* internal cmd packages syntax/check/cgen, which don't resolve
* under the lib-path sep dep scan; w6a/w6l are self-contained
* lib-only tools.) */
const char *tools[] = { "w6a", "w6l", NULL };
char cache[256];
snprintf(cache, sizeof cache, "/tmp/wwl_%d_pkgc", getpid());
int fail = 0;
int n = 0;
for (int i = 0; cases[i].label; i++) {
char inputs[2048];
snprintf(inputs, sizeof inputs, cases[i].inputs_fmt, cwd, cwd);
if (diff_one(bin, cases[i].label, inputs) != 0) fail++;
for (int i = 0; tools[i]; i++) {
if (build_and_diff(bin, cwd, tools[i], cache) != 0) fail++;
n++;
}
char rmc[320];
snprintf(rmc, sizeof rmc, "rm -rf %s", cache);
if (system(rmc)) {}
if (fail) {
fprintf(stderr, "w6l_ww: %d/%d diff(s) failed\n", fail, n);
return 1;
}
printf("w6l_ww: byte-identical to C w6l on %d corpus links "
"(.o + libwwrt.a archive resolution)\n", n);
printf("w6l_ww: byte-identical to C w6l on %d selfhost tool links "
"(sep root .o + reverse-topo .a set + libwwrt.a)\n", n);
return 0;
}

View File

@@ -63,14 +63,17 @@ main(void)
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
/* Ensure mandelbrot.o exists. The example's Makefile produces it
* via the C-side `ww build`. Re-run that so the test is
* self-contained. */
char cmd[4096];
/* #93 sep layout: build the example via `ww build --sep` into a
* private /tmp stem (NOT next to the tracked example source), then
* link <stem>.sepwork/__root.o — the self-contained single-package
* object the flip emits in place of the old next-to-source .o. */
char cmd[4096], mbstem[256], mbobj[320];
snprintf(mbstem, sizeof mbstem, "/tmp/wwld_%d_mb", getpid());
snprintf(mbobj, sizeof mbobj, "%s.sepwork/__root.o", mbstem);
snprintf(cmd, sizeof cmd,
"cd %s/examples/mandelbrot && %s/ww build mandelbrot.ww "
"-L /usr/lib -l c >/dev/null 2>&1",
cwd, bin);
"cd %s/examples/mandelbrot && WW_PKGCACHE=%s.pkgc %s/ww build --sep "
"-o %s mandelbrot.ww -L /usr/lib -l c >/dev/null 2>&1",
cwd, mbstem, bin, mbstem);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6l_ww-dyn FAIL: cannot build mandelbrot.o via C driver\n");
return 1;
@@ -82,9 +85,9 @@ main(void)
/* C-side w6l with the dynamic flags. */
snprintf(cmd, sizeof cmd,
"%s/w6l -o %s %s/examples/mandelbrot/mandelbrot.o -L /usr/lib "
"%s/w6l -o %s %s -L /usr/lib "
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
bin, co, cwd, cwd);
bin, co, mbobj, cwd);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6l_ww-dyn FAIL: C w6l errored\n");
unlink(co);
@@ -93,9 +96,9 @@ main(void)
/* ww-side w6l with the same flags. */
snprintf(cmd, sizeof cmd,
"%s/w6l_ww -o %s %s/examples/mandelbrot/mandelbrot.o -L /usr/lib "
"%s/w6l_ww -o %s %s -L /usr/lib "
"-l c %s/out/lib/libwwrt.a 2>/dev/null",
bin, wo, cwd, cwd);
bin, wo, mbobj, cwd);
if (runwait(cmd) != 0) {
fprintf(stderr, "w6l_ww-dyn FAIL: ww w6l errored\n");
unlink(co); unlink(wo);
@@ -119,5 +122,8 @@ main(void)
}
free(bc); free(bw);
unlink(co); unlink(wo);
/* #93: the sep scratch + tmpdir-pinned pkgcache. */
snprintf(cmd, sizeof cmd, "rm -rf %s.sepwork %s.pkgc %s", mbstem, mbstem, mbstem);
if (system(cmd)) {}
return rc;
}