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:
2026-05-26 14:46:01 +09:00
parent 0917fee48d
commit 7d7ed964b0
6 changed files with 188 additions and 19 deletions

View File

@@ -4206,6 +4206,24 @@ fn cgassign(c: *cgen, n: *node) void = {
emitline("\tMOVQ\tCX, 16(BX)\n");
return;
};
// float element → store FROM X0 (MOVSS/MOVSD): cgexpr
// left the value in X0. X0 survives the index/base
// eval only for literal/local-var indices; a call-
// index (a[geti()]=v) clobbers X0 and loses the value
// — this path does not spill X0 across the eval,
// unlike the *p=v float deref store. Deferred to #125.
// For f32 the #104 CVTSD2SS narrowing only touches X0,
// so the AX store below would write raw double low-
// bits, garbage for f32 (#122, mirrors cstage cgen.c
// arr[i]= float store).
if (isfloattype(c, elemtn)) {
let fmov: str = "MOVSD";
if (isf32type(c, elemtn)) { fmov = "MOVSS"; };
emitline("\t");
emitline(fmov);
emitline("\tX0, (BX)\n");
return;
};
let isop: str = tnodestoreop(c, elemtn, esz);
emitline("\t");
emitline(isop);