wwstage: C-FFI variadic call codegen parity with cstage (#10)
Mirror cstage's C-variadic call handling in the ww self-host: parse a bare `...` param (decl.ww), skip param-keyed desugar for it to avoid a nil-deref (check.ww), and emit AL = XMM-reg count plus CVTSS2SD promotion of f32 args in the variadic tail (cgenutil.ww, cgenexpr.ww). Closes the cat-A wwstage silent miscompile (AL=0, unpromoted f32 tail). Parse/check/cgen are one atomic align-up (parse alone miscompiles, so not bisect-splittable). 989_ffivariadic now runs dual-stage (cstage ww + wwstage ww_ww), 12/12; w6c==w6c_ww byte-identical. Byte-id alone is blind here (the bootstrap calls no float-bearing C variadic), so the ww_ww runtime rows are the real net.
This commit is contained in:
@@ -13,8 +13,9 @@
|
||||
* RUNTIME gate (byte-id can never see AL correctness): each row builds a ww
|
||||
* caller that calls the C fixture `double fixture(long n, ...)` (a
|
||||
* va_arg(double) summer, test/wcc/data/ffivariadic/fixture.c, linked from
|
||||
* libffifix.a) and asserts the returned sum. cstage `ww` ONLY — wwstage AL
|
||||
* is C2.
|
||||
* libffifix.a) and asserts the returned sum. Runs on BOTH the cstage `ww`
|
||||
* and wwstage `ww_ww` drivers (C2): AL is byte-id-blind, so a wwstage fi /
|
||||
* f32-promotion divergence is caught only by a wrong runtime sum here.
|
||||
*
|
||||
* NON-VACUITY DEVIATION (reported to lead): the spec's `fixture(2,1.0,2.0)`
|
||||
* is VACUOUS on this box — with AL=0 the two skipped xmm slots happen to
|
||||
@@ -174,22 +175,45 @@ main(void)
|
||||
bin = absbin;
|
||||
}
|
||||
|
||||
char cdrv[1024], libdir[1024];
|
||||
char cdrv[1024], wdrv[1024], libdir[1024];
|
||||
snprintf(cdrv, sizeof cdrv, "%s/ww", bin);
|
||||
snprintf(wdrv, sizeof wdrv, "%s/ww_ww", bin);
|
||||
/* libffifix.a lives beside $(BIN) under $(OUT)/ffivariadic — the
|
||||
* Makefile builds it there as a prereq of this test binary. */
|
||||
snprintf(libdir, sizeof libdir, "%s/../ffivariadic", bin);
|
||||
|
||||
/* C2: run each row on BOTH the cstage `ww` and the wwstage `ww_ww`
|
||||
* driver. AL correctness is byte-id-blind, so a wwstage fi/promotion
|
||||
* divergence is invisible to the 990-997 gates but caught here as a
|
||||
* wrong sum (nonzero exit). wwstage is access-gated like the other
|
||||
* dual-stage runtime tests (989_chainidx_run) so a cstage-only tree
|
||||
* still runs the cstage rows. */
|
||||
struct { const char *name; const char *drv; int gated; }
|
||||
drivers[] = {
|
||||
{ "cstage", cdrv, 0 },
|
||||
{ "wwstage", wdrv, 1 },
|
||||
{ NULL, NULL, 0 },
|
||||
};
|
||||
|
||||
int n = (int)(sizeof rows / sizeof rows[0]);
|
||||
int total = 0, fail = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int got = run_build(cdrv, libdir, &rows[i], i);
|
||||
if (got != rows[i].want_exit) {
|
||||
fprintf(stderr, "ffivariadic[%s]: exit=%d want=%d\n",
|
||||
rows[i].label, got, rows[i].want_exit);
|
||||
fail++;
|
||||
for (int d = 0; drivers[d].name; d++) {
|
||||
if (drivers[d].gated && access(drivers[d].drv, X_OK) != 0) {
|
||||
fprintf(stderr, "ffivariadic: skip %s (no %s)\n",
|
||||
drivers[d].name, drivers[d].drv);
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
total++;
|
||||
int got = run_build(drivers[d].drv, libdir, &rows[i], i);
|
||||
if (got != rows[i].want_exit) {
|
||||
fprintf(stderr,
|
||||
"ffivariadic[%s][%s]: exit=%d want=%d\n",
|
||||
drivers[d].name, rows[i].label, got,
|
||||
rows[i].want_exit);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user