wwdump's -c/-r modes emitted output from a garbage parse silently. Gate on the parse-error count first (the w6c main gate, main.ww:162); wwstage-only — the C wwdump has no -c/-r modes.
140 lines
4.1 KiB
C
140 lines
4.1 KiB
C
/*
|
|
* 989_wwdumpgate_run (#52, F15 c4) — wwdump_ww's `-c` and `-r` arms must gate
|
|
* on parse-stage errors instead of silently emitting on a broken AST.
|
|
*
|
|
* THE BUG (wwstage wwdump_ww only, cat-A silent wrong output under rc=0): the
|
|
* `-c` codegen arm ran checkfile+cgfile with NO parse-error gate — ps.errs
|
|
* was never read — so a parse-errored decl was silently dropped from the AST
|
|
* and the rest of the file compiled to asm with exit 0 (and `-c` IS the 994
|
|
* byte-identity probe, so the gate tool itself could ship wrong asm silently).
|
|
* The `-r` resolve report arm was likewise ungated. THE FIX: add the
|
|
* `l.errs>0 || ps.errs>0` gate after parsefile in both arms, mirroring the
|
|
* w6c compiler gate (selfhost/cmd/w6c/main.ww:162 / cmd/w6c/main.c).
|
|
*
|
|
* WWSTAGE-ONLY: the C wwdump (cstage) implements only -t/-a, not -c/-r — the
|
|
* codegen/resolve dump arms are a wwstage-wwdump_ww feature, so there is no
|
|
* cstage -c/-r twin to diff against; the gate reference is the w6c compiler.
|
|
*
|
|
* row | mode | input | result
|
|
* -------+------+---------------+----------------------------------
|
|
* bad_c | -c | parse error | rc != 0, zero asm bytes
|
|
* bad_r | -r | parse error | rc != 0
|
|
* ok_c | -c | valid file | rc == 0, asm emitted (control)
|
|
*
|
|
* bad_c / bad_r were RED pre-c4 (rc=0 with truncated asm / a resolve report).
|
|
* ok_c pins the healthy emission path unperturbed.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
|
|
static int
|
|
runwait(const char *cmd)
|
|
{
|
|
int rc = system(cmd);
|
|
if (rc == -1) return -1;
|
|
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
|
return -1;
|
|
}
|
|
|
|
static const char *BAD =
|
|
"package main;\n\n"
|
|
"export fn main(argc: i32, argv: **u8) i32 = {\n\treturn 0;\n};\n\n"
|
|
"fn broken( {\n";
|
|
static const char *OK =
|
|
"package main;\nexport fn main() i32 = { return 0; };\n";
|
|
|
|
/* Run `<tool> <mode> <src>` capturing asm on stdout; returns rc, sets
|
|
* *asmbytes to the stdout byte count when non-NULL. */
|
|
static int
|
|
run_dump(const char *tool, const char *mode, const char *src, long *asmbytes)
|
|
{
|
|
char outp[128], cmd[1024];
|
|
snprintf(outp, sizeof outp, "/tmp/wwdg_%d_out", getpid());
|
|
snprintf(cmd, sizeof cmd, "%s %s %s > %s 2>/dev/null",
|
|
tool, mode, src, outp);
|
|
int rc = runwait(cmd);
|
|
if (asmbytes) {
|
|
FILE *f = fopen(outp, "rb");
|
|
long n = 0;
|
|
if (f) { fseek(f, 0, SEEK_END); n = ftell(f); fclose(f); }
|
|
*asmbytes = n;
|
|
}
|
|
unlink(outp);
|
|
return rc;
|
|
}
|
|
|
|
static int
|
|
write_file(const char *path, const char *body)
|
|
{
|
|
FILE *f = fopen(path, "wb");
|
|
if (!f) return -1;
|
|
fputs(body, f);
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
const char *bin = getenv("BIN");
|
|
if (!bin) bin = "out/bin";
|
|
char absbin[1024];
|
|
if (bin[0] != '/') {
|
|
char cwd[1024];
|
|
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
|
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
|
|
bin = absbin;
|
|
}
|
|
|
|
char wtool[1024];
|
|
snprintf(wtool, sizeof wtool, "%s/wwdump_ww", bin);
|
|
if (access(wtool, X_OK) != 0) {
|
|
/* wwdump_ww is the unit under test; absence is a wiring fault. */
|
|
fprintf(stderr, "wwdumpgate: missing %s\n", wtool);
|
|
return 1;
|
|
}
|
|
|
|
char badp[64], okp[64];
|
|
snprintf(badp, sizeof badp, "/tmp/wwdg_bad_%d.ww", getpid());
|
|
snprintf(okp, sizeof okp, "/tmp/wwdg_ok_%d.ww", getpid());
|
|
if (write_file(badp, BAD) || write_file(okp, OK)) return 1;
|
|
|
|
int fail = 0, total = 0;
|
|
long ab;
|
|
|
|
/* bad_c: loud, zero asm */
|
|
total++;
|
|
if (run_dump(wtool, "-c", badp, &ab) == 0 || ab != 0) {
|
|
fprintf(stderr, "wwdumpgate[bad_c]: emitted asm with rc=0 on "
|
|
"parse-errored input (#52); asm=%ld\n", ab);
|
|
fail++;
|
|
}
|
|
|
|
/* bad_r: loud */
|
|
total++;
|
|
if (run_dump(wtool, "-r", badp, NULL) == 0) {
|
|
fprintf(stderr, "wwdumpgate[bad_r]: resolve report with rc=0 on "
|
|
"parse-errored input (#52)\n");
|
|
fail++;
|
|
}
|
|
|
|
/* ok_c control: rc=0 with asm */
|
|
total++;
|
|
if (run_dump(wtool, "-c", okp, &ab) != 0 || ab <= 0) {
|
|
fprintf(stderr, "wwdumpgate[ok_c]: healthy file rejected/no asm "
|
|
"(asm=%ld)\n", ab);
|
|
fail++;
|
|
}
|
|
|
|
unlink(badp); unlink(okp);
|
|
|
|
if (fail) {
|
|
fprintf(stderr, "wwdumpgate_run: %d/%d check(s) failed\n", fail, total);
|
|
return 1;
|
|
}
|
|
printf("wwdumpgate_run: %d/%d ok\n", total, total);
|
|
return 0;
|
|
}
|