w6c: promote f32 arg to double in C-variadic tail (#14)
C99 6.5.2.2p6 requires float->double promotion for floats in the variadic region of a call; w6c emitted MOVSS (4B), so a C variadic's va_arg(double) read 8B of garbage. Promote at push (CVTSS2SD) so the 8B slot holds a real double, covering the XMM-reg and >8-float spill cases uniformly; fi/AL XMM-count is unchanged. cstage only; the wwstage twin rides C2 (#10), which adds wwstage's C-variadic-call codegen.
This commit is contained in:
@@ -79,6 +79,52 @@ static const struct row rows[] = {
|
||||
" return 1;\n"
|
||||
"};\n",
|
||||
0 },
|
||||
|
||||
/* 3 f32 args (#14): C default arg promotion widens each to f64, so
|
||||
* the callee's va_arg(double) reads 1.5+2.5+3.0 == 7.0. Values are
|
||||
* exact in f32, so the f64 compare is exact. Unpromoted (MOVSS, 4B)
|
||||
* the high 4B of each 8B slot is stale stack, so va_arg(double)
|
||||
* pulls garbage and the sum misses 7.0 — this row FAILS pre-fix. */
|
||||
{ "f32three",
|
||||
"package main;\n"
|
||||
"@symbol(\"fixture\") fn fixture(n: i64, ...) f64;\n"
|
||||
"export fn main() int = {\n"
|
||||
" let r: f64 = fixture(3, 1.5: f32, 2.5: f32, 3.0: f32);\n"
|
||||
" if (r == 7.0) { return 0; };\n"
|
||||
" return 1;\n"
|
||||
"};\n",
|
||||
0 },
|
||||
|
||||
/* Sharper than f32three: 0.1 is INEXACT in f32, so the f32-rounded
|
||||
* value differs from the f64 literal 0.1. The expected side `(x: f64)`
|
||||
* is the SAME f32 var widened at runtime (CVTSS2SD), so equality holds
|
||||
* iff the variadic arg carried the f32-rounded value promoted to f64 —
|
||||
* NOT the original f64 literal and NOT stale-high-bit garbage. Both a
|
||||
* no-promote (MOVSS) and a hypothetical direct-f64 pass would miss it.
|
||||
* Single f32 arg also exercises the fi==1 boundary. */
|
||||
{ "f32inexact",
|
||||
"package main;\n"
|
||||
"@symbol(\"fixture\") fn fixture(n: i64, ...) f64;\n"
|
||||
"export fn main() int = {\n"
|
||||
" let x: f32 = 0.1: f32;\n"
|
||||
" let r: f64 = fixture(1, x);\n"
|
||||
" if (r == (x: f64)) { return 0; };\n"
|
||||
" return 1;\n"
|
||||
"};\n",
|
||||
0 },
|
||||
|
||||
/* Mixed f32 + f64 in one variadic call: only the f32 args (1.5, 3.5)
|
||||
* promote; the f64 arg (2.0) passes at its native width and must NOT be
|
||||
* double-promoted or skewed. 1.5+2.0+3.5 == 7.0, exact in both widths. */
|
||||
{ "f32mixed",
|
||||
"package main;\n"
|
||||
"@symbol(\"fixture\") fn fixture(n: i64, ...) f64;\n"
|
||||
"export fn main() int = {\n"
|
||||
" let r: f64 = fixture(3, 1.5: f32, 2.0, 3.5: f32);\n"
|
||||
" if (r == 7.0) { return 0; };\n"
|
||||
" return 1;\n"
|
||||
"};\n",
|
||||
0 },
|
||||
};
|
||||
|
||||
/* run_build — build+run `src` via cstage `driver`, linking libffifix.a from
|
||||
|
||||
Reference in New Issue
Block a user