wcc: f32 array-element store from X0 (#122)
Float array-element stores (array-literal init, [v...] repeat-fill, and arr[i]=v) now route from X0 via MOVSS/MOVSD in both stages; the AX path stored the raw double low-bits, garbage for f32 (f64 worked by accident). A clobbering call-index (a[geti()]=v) loses the X0 value — deferred to #125.
This commit is contained in:
@@ -21,13 +21,16 @@
|
||||
*
|
||||
* Each row carries (a) a cstage `ww build` + run asserting the exit
|
||||
* code, and (b) a w6c vs w6c_ww `.s` cmp (rule-10 byte-id). A row whose
|
||||
* want_exit is RUN_SKIP runs only the byte-id leg: the f32 row exercises
|
||||
* the f32 LOAD + cs==ww but its runtime VALUE is blocked by a SEPARATE,
|
||||
* pre-existing bug — the f32 array-element STORE writes AX (the raw
|
||||
* double low-bits) instead of the CVTSD2SS-narrowed X0 single, so every
|
||||
* f32 array slot reads back 0.0f. That store-side twin is filed
|
||||
* separately (#119-store); this probe still proves the f32 LOAD shape +
|
||||
* cs==ww byte-identity.
|
||||
* want_exit is RUN_SKIP runs only the byte-id leg.
|
||||
*
|
||||
* #122 fixes the store-side twin the #119 commit deferred: the f32
|
||||
* array-element STORE wrote AX (the raw double low-bits) instead of the
|
||||
* CVTSD2SS-narrowed X0 single, so every f32 array slot read back garbage.
|
||||
* Both the array-literal-init store (cgen.c:6889 / cgenstmt:949) and the
|
||||
* arr[i]= index store (cgen.c:3818 / cgenexpr:4209) now route FROM X0 via
|
||||
* MOVSS/MOVSD, mirroring the scalar float store. The f32 rows below now
|
||||
* assert the runtime VALUE (not byte-id only) and add an arr[i]= store
|
||||
* plus a [v...] repeat-fill init (a distinct cgen arm #122 also fixed).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -75,17 +78,42 @@ static const struct row rows[] = {
|
||||
" if (a[2] != 9.0) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* f32 element load (MOVSS into X0) + add, suffixed literals so
|
||||
* fold-1 narrows them. BYTE-ID ONLY: the runtime value is blocked by
|
||||
* the f32 array-element STORE bug (#119-store), so we assert only
|
||||
* that both stages emit the same (correct-load) asm. */
|
||||
{ "f32_arith_byteid",
|
||||
/* f32 array-literal-init store + element load + add: suffixed
|
||||
* literals so fold-1 narrows them. Pre-#122 the init store wrote
|
||||
* MOVL AX (raw double low-bits) so the slots read garbage; #122
|
||||
* routes the store from X0 via MOVSS, so 1.5 + 2.5 == 4.0. */
|
||||
{ "f32_arith",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let b: [2]f32 = [1.5f32, 2.5f32];\n"
|
||||
" if ((b[0] + b[1]): f64 != 4.0) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", RUN_SKIP },
|
||||
"};\n", 0 },
|
||||
/* f32 arr[i]= index store (#122): assign each slot, read back.
|
||||
* The index-store path popped the value to AX and wrote MOVL (raw
|
||||
* double low-bits, garbage for f32); #122 stores from X0 via MOVSS.
|
||||
* The [0.0f32,0.0f32] init also exercises the array-lit store. */
|
||||
{ "f32_index_store",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let b: [2]f32 = [0.0f32, 0.0f32];\n"
|
||||
" b[0] = 1.5f32;\n"
|
||||
" b[1] = 2.5f32;\n"
|
||||
" if ((b[0] + b[1]): f64 != 4.0) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* f32 [v...] repeat-fill init store (#122): the repeat marker
|
||||
* fills every slot from the last element's X0 single; pre-#122 the
|
||||
* fill wrote MOVL AX (raw double low-bits) per slot so each read
|
||||
* back garbage. Distinct cgen arm from the per-element list store.
|
||||
* 1.5 * 3 == 4.5 (exact in IEEE). */
|
||||
{ "f32_repeat_fill",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let c: [3]f32 = [1.5f32...];\n"
|
||||
" if ((c[0] + c[1] + c[2]): f64 != 4.5) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user