selfhost/cmd+test: run check before cgen in wwstage drivers
w6c_ww and wwdump_ww (-c mode) silently passed source into cgen without type-checking it; any type error flowed through as broken asm with exit 0. Mirror cstage cmd/w6c/main.c:73-75: between the parse-error gate and cgeninit, install typesinit + checkinit + checkfile + `if (ck.errs > 0) return 1;`. Cgen path unchanged — drivers own check, cgen owns emit (checkfile not idempotent due to installdecl scopedefine). The wire-up was blocked by five latent check.ww divergences from cstage, all landed first: cross-module type refs (#51), enum-int reinterprets (#52), per-block scoping (#53), nominal-first tagged-variant inclusion (#55), and same-module N_IDENT callee preference (#56). With those clear, the broader exercise of check across every selfhost driver reaches 131/131 first try. 994_w6c_ww grows by one row: a trivially-wrong `let x: i32 = "hello";` smoke pins both stages to exit-non-zero. Pre-#50 it emitted 202 bytes of broken asm with exit=0. Unblocks #42 (size/align/offset wwstage intercepts) and the audit-§1.8 UP-polarity refactor (node.type_ population can now land in the same check pass we just wired up).
This commit is contained in:
@@ -248,6 +248,45 @@ main(void)
|
||||
n++;
|
||||
}
|
||||
|
||||
/* #50: the check pass is wired into both wwdump_ww -c and
|
||||
* w6c_ww in front of cgen. Pre-#50, a hard type error parsed
|
||||
* cleanly and reached cgen, which would emit asm with a zero
|
||||
* exit (silent miscompile). Pin the rejection by giving each
|
||||
* driver a trivially-broken file and demanding non-zero exit. */
|
||||
struct { const char *label; const char *src; } bad[] = {
|
||||
{ "let_str_to_i32",
|
||||
"package main;\n"
|
||||
"fn main() i32 = {\n"
|
||||
" let x: i32 = \"hello\";\n"
|
||||
" return x;\n"
|
||||
"};\n" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
for (int i = 0; bad[i].label; i++) {
|
||||
char src[64], wcmd[2048], dcmd[2048], s[64];
|
||||
snprintf(src, sizeof src, "/tmp/wwc6_bad_%d_%d.ww", getpid(), i);
|
||||
snprintf(s, sizeof s, "/tmp/wwc6_bad_%d_%d.s", getpid(), i);
|
||||
if (write_file(src, bad[i].src) != 0) { fail++; n++; continue; }
|
||||
snprintf(wcmd, sizeof wcmd,
|
||||
"%s/w6c_ww -o %s %s >/dev/null 2>&1", bin, s, src);
|
||||
snprintf(dcmd, sizeof dcmd,
|
||||
"%s/wwdump_ww -c %s >%s 2>/dev/null", bin, src, s);
|
||||
if (runwait(wcmd) == 0) {
|
||||
fprintf(stderr,
|
||||
"w6c_ww FAIL: %s slipped past check (silent miscompile)\n",
|
||||
bad[i].label);
|
||||
fail++;
|
||||
}
|
||||
if (runwait(dcmd) == 0) {
|
||||
fprintf(stderr,
|
||||
"wwdump_ww -c FAIL: %s slipped past check (silent miscompile)\n",
|
||||
bad[i].label);
|
||||
fail++;
|
||||
}
|
||||
unlink(src); unlink(s);
|
||||
n++;
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fprintf(stderr, "w6c_ww: %d/%d diff(s) failed\n", fail, n);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user