cgen: f64-typed int-literal + tuple-field materialize in X0 (both stages, #103)

Two sites, same class: an f64 value failing to reach XMM (X0) before an
SSE op. Both gate-blind — cstage and wwstage emitted the same wrong asm —
so the fix touches both stages identically.

FACE X — a no-decimal float-typed integer literal (`0f64`, `8f64`) is an
N_INTLIT carrying float TYPE. The integer-immediate path stranded it in
AX, so `n == 0f64` compared a stale X0 (true for all n) and
`(8f64 * 10.0): i32` read garbage. Route the float-typed N_INTLIT through
the float-constant-in-X0 emit (cgen.c cgexpr_float, factored from
N_FLOATLIT; cgenexpr.ww cgfloatbits). The wwstage also needs the
exprfloatkind N_INTLIT arm so the downstream f64->i32 cast emits
CVTTSD2SI not MOVSXD — cstage reads the checker-stamped type directly,
so this is the same #101 structural-vs-stamped asymmetry.

FACE Z — a tuple positional f64 field read (`r.0`, r:(f64,i64)) loaded
via the integer op into AX, so `r.0 == 0.0` was wrongly true. Add a
fld_isfloat branch -> MOVSD/MOVSS into X0 (cgen.c:5910 tuple arm;
cgenexpr.ww tuple arm), mirroring the struct-field float load at
cgen.c:1462,1838 (the #96 pattern).
This commit is contained in:
2026-05-25 15:26:43 +09:00
parent e784968dd8
commit c9e39c6782
3 changed files with 92 additions and 21 deletions

View File

@@ -1847,6 +1847,18 @@ export fn exprfloatkind(c: *cgen, n: *node) i32 = {
if (n == nil) { return 0; };
let k: nkind = n.kind;
if (k == nkind.N_FLOATLIT) { return 2; };
if (k == nkind.N_INTLIT) {
// A float-typed integer literal (`8f64`/`0f32`) now
// materialises in X0 (#103 FACE X), so the cast / spill /
// arith-recursion sides must classify it as float — else
// `(8f64 * 10.0): i32` recurses to this N_INTLIT lhs and
// falls through to integer, emitting MOVSXD not CVTTSD2SI
// (the #101 structural-vs-stamped asymmetry). cstage reads
// the checker-stamped type via node_isfloat directly.
if (isf32type(c, n)) { return 1; };
if (isfloattype(c, n)) { return 2; };
return 0;
};
if (k == nkind.N_CAST) {
if (isf32type(c, n.rhs)) { return 1; };
if (isfloattype(c, n.rhs)) { return 2; };