wcc: tagged float-variant return packs float bits via X0-spill (#157)
The N_RETURN tagged-pack scalar-variant arm did MOVQ AX,DX, but a float variant's value is in X0 not AX -> packed stale int (broke stof64/stof32 return (f64|invalid|overflow)). Fix: float variant bridges X0->DX via a stack slot (SUBQ $8,SP; MOVQ $0,(SP); MOVSS|MOVSD X0,(SP); MOVQ (SP),DX; ADDQ $8,SP), gated type_isfloat/exprfloatkind. No MOVQ-xmm->gp form exists, hence the spill (715-class, cgreturn-register-pack twin of 715's store-to-slot). Zero-slot-first -> deterministic f32 high-4. AX-independent -> also resolves the multi-variant cs!=ww. Bootstrap-NEUTRAL (compiler has no float-tagged-return). Test 707 +3 rows (f64/f32/multi, slot+8 bit-exact; f32 no-f32-arg to isolate #143). Make test 184/184 incl 990-997 byte-id.
This commit is contained in:
@@ -7716,6 +7716,35 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
||||
areg(D_CX));
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
areg(D_DX));
|
||||
} else if (type_isfloat(vt)) {
|
||||
/* #157: float variant. cgexpr left
|
||||
* the value in X0, not AX; there is
|
||||
* no MOVQ-xmm->gp encoding, so bridge
|
||||
* X0->DX through a stack slot (same
|
||||
* SUBQ/MOVSD/ADDQ idiom as the arg-
|
||||
* push at cgen.c:5367). Zero the slot
|
||||
* first so the f32 case (MOVSS writes
|
||||
* only the low 4 bytes) leaves a
|
||||
* deterministic high-4 — cs==ww byte-
|
||||
* id, matching f64's MOVSD which fills
|
||||
* all 8. The AX-independent spill also
|
||||
* removes the stale-AX cs!=ww on
|
||||
* multi-variant returns. */
|
||||
int isf32 = type_isf32(vt);
|
||||
ins2(c, A_SUBQ, aimm(8), areg(D_SP));
|
||||
ins2(c, A_MOVQ, aimm(0),
|
||||
amem(D_SP, 0));
|
||||
ins2(c, isf32 ? A_MOVSS : A_MOVSD,
|
||||
areg(D_X0), amem(D_SP, 0));
|
||||
ins2(c, A_MOVQ, amem(D_SP, 0),
|
||||
areg(D_DX));
|
||||
ins2(c, A_ADDQ, aimm(8), areg(D_SP));
|
||||
if (rsz > 16)
|
||||
ins2(c, A_MOVQ, aimm(0),
|
||||
areg(D_CX));
|
||||
if (rsz > 24)
|
||||
ins2(c, A_MOVQ, aimm(0),
|
||||
areg(D_R8));
|
||||
} else {
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
areg(D_DX));
|
||||
|
||||
Reference in New Issue
Block a user