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

@@ -3815,6 +3815,22 @@ cgexpr(Cg *c, Node *n, Local *locals)
ins2(c, A_MOVQ, areg(D_CX), amem(D_BX, 16));
break;
}
/* float element → store FROM X0 (MOVSS/MOVSD): cgexpr
* leaves a float value in X0, and for f32 the #104
* CVTSD2SS narrowing only touches X0 — the AX path
* below would store the raw double low-bits (garbage
* for f32). Float-ness from esub, mirroring the read
* side at cgen.c:6423 (#122). 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 above. Deferred to
* #125. */
if (type_isfloat(esub)) {
int mov = type_isf32(esub) ? A_MOVSS : A_MOVSD;
ins2(c, mov, areg(D_X0), amem(D_BX, 0));
break;
}
int store_op = fldstoreop(esub, esz);
ins2(c, store_op, areg(D_AX), amem(D_BX, 0));
break;
@@ -6867,6 +6883,11 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
Type *esub = lu->sub;
int esz = esub ? (int)esub->size : 1;
int is_str_el = type_isstr(esub);
/* float element → store FROM X0; the AX path stores
* raw double low-bits, garbage for f32 (#122, twin of
* the arr[i]= store fix and the cgen.c:6423 read). */
int is_float_el = type_isfloat(esub);
int fmov = type_isf32(esub) ? A_MOVSS : A_MOVSD;
int op = A_MOVQ;
if (!is_str_el) {
if (esz == 1) op = A_MOVB;
@@ -6893,6 +6914,9 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
amem(D_BP, base));
ins2(c, A_MOVQ, areg(D_BX),
amem(D_BP, base + 8));
} else if (is_float_el) {
ins2(c, fmov, areg(D_X0),
amem(D_BP, base));
} else {
ins2(c, op, areg(D_AX),
amem(D_BP, base));
@@ -6910,6 +6934,9 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
amem(D_BP, base));
ins2(c, A_MOVQ, areg(D_BX),
amem(D_BP, base + 8));
} else if (is_float_el) {
ins2(c, fmov, areg(D_X0),
amem(D_BP, base));
} else {
ins2(c, op, areg(D_AX),
amem(D_BP, base));