test: revive 749 callsite byte-id via explicit w6c -o, was silently skipped (#13)

749's cstage-vs-wwstage callsite byte-id compare read back <src>.s, but
separate-compile emits the root .s to <ostem>.sepwork/__root.s, so the read
returned NULL and the `if(cs_asm && ws_asm)` guard left the compare silently
skipped -- green but unverified, the same blind-spot class as the #9/#10/#11
producer bugs.

Switch to the canonical explicit-emit idiom (siblings 925/926/949): emit
each stage's .s directly with `w6c -o <tmpdir>/cs.s` / `w6c_ww -o
<tmpdir>/ws.s`, then read both and run the existing helper_callsite() window
compare. The .s files live inside the driver's rm -rf'd tmpdir (w6c emits no
.sepwork); runtime parity blocks unchanged.

The compare now genuinely fires (749's internal subtest count 6->9) and
passes -- cs and ww callsite windows are byte-identical, no rule-10
divergence was hiding behind the skip. make test: all 402 passed.
This commit is contained in:
2026-06-22 23:57:50 +09:00
parent 81ebaf7bfa
commit 2e07e3bfe7

View File

@@ -142,8 +142,8 @@ exec_bin(const char *bin)
return runwait(bin);
}
/* read_file slurps the .s file produced alongside the driver build,
* returning a malloc'd buffer (NUL-terminated) or NULL on error. */
/* read_file slurps a file whole, returning a malloc'd buffer
* (NUL-terminated) or NULL on error. */
static char *
read_file(const char *path, size_t *outsz)
{
@@ -195,10 +195,13 @@ main(void)
bin = absbin;
}
char cdrv[640], wdrv[640];
char cdrv[640], wdrv[640], cw6[640], ww6[640];
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
snprintf(cw6, sizeof cw6, "%s/w6c", bin);
snprintf(ww6, sizeof ww6, "%s/w6c_ww", bin);
int have_ww = (access(wdrv, X_OK) == 0);
int have_w6cww = (access(ww6, X_OK) == 0);
int n = (int)(sizeof rows / sizeof rows[0]);
int total = 0, fail = 0;
@@ -220,19 +223,6 @@ main(void)
fputs(r->src, f);
fclose(f);
char outasm[160];
/* DEAD readback (task #13): separate-compile now lands the .s
* at <outbin>.sepwork/__root.s, not <src>.s, so read_file below
* returns NULL and the byte-id phase silently skips. */
snprintf(outasm, sizeof outasm, "%s", src);
char *dot2 = strrchr(outasm, '.');
if (dot2 && strcmp(dot2, ".ww") == 0) {
strcpy(dot2, ".s");
}
char *cs_asm = NULL;
size_t cs_n = 0;
/* Runtime parity (cstage). */
total++;
if (build_with(cdrv, src, outbin) != 0) {
@@ -248,13 +238,10 @@ main(void)
r->label, got, r->want_cs);
fail++;
}
cs_asm = read_file(outasm, &cs_n);
}
unlink(outbin);
/* Runtime parity (wwstage). */
char *ws_asm = NULL;
size_t ws_n = 0;
if (have_ww) {
total++;
if (build_with(wdrv, src, outbin) != 0) {
@@ -270,14 +257,30 @@ main(void)
r->label, got, r->want_ws);
fail++;
}
ws_asm = read_file(outasm, &ws_n);
}
unlink(outbin);
}
/* Byte-id of the helper(needles[i]) callsite window. Only
* the first row has a main.helper call; rows 2/3 also have
* one but a simpler shape — match them all for symmetry. */
/* Byte-id of the helper(needles[i]) callsite window. Emit
* each stage's .s explicitly to a known path inside tmpdir
* (w6c emits no .sepwork, so no leak) and compare. Only the
* first row has a main.helper call; rows 2/3 also have one
* but a simpler shape — match them all for symmetry. */
char *cs_asm = NULL, *ws_asm = NULL;
size_t cs_n = 0, ws_n = 0;
if (have_w6cww) {
char css[160], wss[160], emit[1100];
snprintf(css, sizeof css, "%s/cs.s", tmpdir);
snprintf(wss, sizeof wss, "%s/ws.s", tmpdir);
snprintf(emit, sizeof emit, "%s -o %s %s 2>/dev/null",
cw6, css, src);
if (runwait(emit) == 0)
cs_asm = read_file(css, &cs_n);
snprintf(emit, sizeof emit, "%s -o %s %s 2>/dev/null",
ww6, wss, src);
if (runwait(emit) == 0)
ws_asm = read_file(wss, &ws_n);
}
if (cs_asm && ws_asm) {
total++;
const char *cs_site = helper_callsite(cs_asm);