w6c: set variadic-call AL to XMM-reg count, not hardcoded 0 (catB-54 C1)
SysV §3.5.7 requires a variadic call to set AL = number of vector (XMM) regs used for the variable float args; the C callee gates its xmm-save-area stores on `test %al,%al`, so the old hardcoded XORQ AX,AX (AL=0) made va_arg(double) read garbage for any float-bearing C variadic call. Emit MOVQ $fi,AX (fi = the in-scope XMM cursor, ≤8); w6a has no MOVL-immediate encoding so MOVQ is the assemblable form and sets AL=fi identically. fi==0 keeps XORQ → byte-identical to pre-fix for no-float variadic calls. Runtime test 989_ffivariadic links a cc-compiled va_arg(double) fixture (zero relocs/undefined, w6l-linkable) and sweeps N=3/5/8 floats (N=2 is vacuous via stale-stack aliasing). C1 of the C-FFI-variadic align-up (USER ruling); C2 wwstage + C3 bodiless gate follow. ref/qbe/amd64/sysv.c:384. 454 green.
This commit is contained in:
26
test/wcc/data/ffivariadic/fixture.c
Normal file
26
test/wcc/data/ffivariadic/fixture.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* C-FFI variadic test fixture (C1, catB-54). A va_arg(double) summer the
|
||||
* ww caller links against to prove the SysV AL=XMM-count fix: the callee
|
||||
* gates its xmm-save-area stores on `test %al,%al`, so a wrong AL makes
|
||||
* these va_arg(double) reads pull garbage.
|
||||
*
|
||||
* Built self-contained (zero relocs, zero undef syms) so w6l can link it
|
||||
* with no libc — verified via readelf -r / nm. Do not add any call that
|
||||
* pulls in a libc symbol.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
|
||||
double
|
||||
fixture(long n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
double s;
|
||||
long i;
|
||||
|
||||
va_start(ap, n);
|
||||
s = 0;
|
||||
for(i = 0; i < n; i++)
|
||||
s += va_arg(ap, double);
|
||||
va_end(ap);
|
||||
return s;
|
||||
}
|
||||
Reference in New Issue
Block a user