wcc/cgen: #135 inferred-float module-global — default untyped_float to f64 (wwstage)

let pi = 3.5; pi * 2.0 (an inferred-type float module-global) was silently
miscompiled by wwstage: untyped_float wasn't defaulted, so letemitsize
sized it 0 -> no DATAW emitted -> the pi load was dropped, X0 kept a stale
spill -> 2.0*2.0 = 4 not 7. cstage became correct via #150-B's sym-repoint
(stamps f64 -> MOVSD), so this aligns wwstage UP, byte-identical.

wwstage-only: cgen.ww defaultinferredlets gains the untyped_float->f64 arm
(mirrors the untyped_int->int arm; the codebase's own #135-deferred
carve-out at cgen.ww:1079-1082, unblocked now that #150-B killed the
rule-10 divergence it feared), and cgenexpr.ww cgident gets a letfloatprim
fallback (the same primitive-TNAME SSoT letemitsize already uses, since a
renamed primitive TNAME carries no tinfo stamp). cstage cgen unchanged
(w6c md5 unchanged). int-inferred globals stay integer.

byte-id 990-997 8/8. test/wcc/824 table-driven. The N_CAST-no-recurse
parity (check.c:1276) is filed separately (#19).
This commit is contained in:
2026-06-08 21:46:14 +09:00
parent ebd5b8014c
commit ef6fcbfc04
6 changed files with 398 additions and 6 deletions

View File

@@ -1125,9 +1125,23 @@ fn cgident(c: *cgen, n: *node) void = {
let lv: *letvar = c.lets;
for (lv != nil) {
if (streq(lv.name, nm)) {
if (isfloattype(c, lv.tnode)) {
// #135: an inferred-float global's tnode is the
// defaultinferredlets-renamed "f64"/"f32" N_TNAME whose
// .type_ is unstamped (cgen can't build tinfo), so the
// isfloattype stamp-read misses it. Fall back to the
// name keyword (the letfloatprim SSoT letemitsize uses)
// so the float load fires for inferred as for explicit.
let isf: bool = isfloattype(c, lv.tnode);
let is32: bool = isf32type(c, lv.tnode);
if (!isf && lv.tnode != nil
&& lv.tnode.kind == nkind.N_TNAME) {
let fsz: i32 = letfloatprim(lv.tnode.str);
if (fsz > 0) { isf = true; };
if (fsz == 4) { is32 = true; };
};
if (isf) {
let mov: str = "MOVSD";
if (isf32type(c, lv.tnode)) { mov = "MOVSS"; };
if (is32) { mov = "MOVSS"; };
emitline("\tLEAQ\t");
emitsymnamehint(c, nm, c.curmod);
emitline("(SB), CX\n");