wcc: retire exprfloatkind, read the checker stamp directly
exprfloatkind was wwstage cgen's structural float-classifier — a workaround for the checker stamp being untrustworthy. With the previous commit arming the asserttyped bail, every checked value-node is now stamped (or cited-exempt), so its job collapses to a 2-liner reading n.type_ — the same path cstage cgen has always taken. Retire it: inline the stamp-read at its eight sites (cgcast, cgun, cgbin lhs+rhs, cgcall pop, pushargsrev, cgwidentaggedstorebp, cgreturn x2 collapsed), delete the wrapper, and delete the two residual sibling-evidence loud-aborts (cgbin float-arith, cgwidentaggedstorebp float-arm) — their operands are real source value-exprs the armed bail now stamps, so the guards can never fire. One synth-post-checker value-node remained outside the bail's reach: the variadic-slice descriptor pushed in pushargsrev/cgcall (cgenexpr.ww). Stamp it at synthesis with the variadic param's []T slice tinfo so the inlined reads see a stamped node, no nil special-case. Byte-id-neutral by design (slice tinfo and nil both read non-float); 990-997 confirm. Closes the bail-rearm arc — wwstage now reads the same float-class SSoT cstage does, the gate-blind float-classification family is closed, and the build+test corpus is asserttyped-clean by construction.
This commit is contained in:
@@ -478,7 +478,12 @@ fn pushargsrev(c: *cgen, arg: *node, param: *node) i32 = {
|
||||
// X0 via SUBQ+MOVSD so cgcall's pop side can drain into the
|
||||
// XMM stream (X0..X7). f32 still occupies 8B on the stack —
|
||||
// the MOVSS load on the pop side touches only the low 4.
|
||||
let fk: i32 = exprfloatkind(c, arg);
|
||||
let fk: i32 = 0;
|
||||
if (arg != nil) {
|
||||
let at: *tinfo = arg.type_: *tinfo;
|
||||
if (typeisf32(at)) { fk = 1; }
|
||||
else { if (typeisfloat(at)) { fk = 2; }; };
|
||||
};
|
||||
if (fk != 0) {
|
||||
cgexpr(c, arg);
|
||||
let mov: str = "MOVSD";
|
||||
@@ -2070,39 +2075,6 @@ export fn isf32type(c: *cgen, t: *node) bool = {
|
||||
return typeisf32(t.type_: *tinfo);
|
||||
};
|
||||
|
||||
// exprfloatkind — classify an expression's value-class for cgen's
|
||||
// float-vs-integer dispatch. Returns 0 integer-like/unknown, 1 f32,
|
||||
// 2 f64. Reads the checker-stamped type (n.type_) directly — the
|
||||
// single source of truth shared with cstage (cmd/wcc/cgen.c
|
||||
// node_isfloat / type_isf32). Cite typ.ww:437,350 for the TY_NAMED-
|
||||
// peeling float predicates; rule 13 routes through the type table.
|
||||
//
|
||||
// #121 (Package B) — the COLLAPSE. The wwstage previously mirrored
|
||||
// each cgen-shape arm structurally (N_FLOATLIT/N_INTLIT/N_CAST/N_INDEX/
|
||||
// N_IDENT/N_UN/N_BIN/N_CALL/N_DOT — fanned out across isf32type,
|
||||
// localfindnode, c.lets, fnretlookupmod): a gate-blind divergence net
|
||||
// surfaced by the residual sibling-evidence guards below now that the
|
||||
// stamp is the SSoT. The TRANSIENT bridge that proved this safe (commits
|
||||
// 1c4cea4 + 1865+ this file at HEAD-1) is deleted; the corpus-wide
|
||||
// no-float-miss evidence from commit 2's make-test-green licenses the
|
||||
// flip + delete. Stamp coverage prereqs landed at 98e1665 (N_IDENT-
|
||||
// callee destructure stamp) and historically across A.6.x.
|
||||
//
|
||||
// PRECONDITION (enforced by the residual sibling-evidence guards at
|
||||
// cgbin float-arith + cgwidentaggedstore float arm — see those sites):
|
||||
// any operand whose float-ness drives downstream MOVSD/MOVSS/CVT* MUST
|
||||
// carry a non-nil n.type_ stamp. Unstamped float nodes (a future
|
||||
// `let (frac, exp) = math.frexpf64(x);` once N_DOT-callee destructure
|
||||
// stamping lands — #16/#17) would silently misclassify integer here
|
||||
// and break in the consumer; the guards turn that into a loud abort.
|
||||
export fn exprfloatkind(c: *cgen, n: *node) i32 = {
|
||||
if (n == nil) { return 0; };
|
||||
let t: *tinfo = n.type_: *tinfo;
|
||||
if (typeisf32(t)) { return 1; };
|
||||
if (typeisfloat(t)) { return 2; };
|
||||
return 0;
|
||||
};
|
||||
|
||||
// isnullabletype — `(*T | void)` one-word fold per Hare's
|
||||
// `(*T | null)` semantics. Cite cstage cgen.c:396 `type_isnullable`;
|
||||
// the .nullable flag lands on tinfo at check.ww:1309-1318 when the
|
||||
@@ -2861,38 +2833,22 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s
|
||||
// by coincidence (TK_FLOAT lowering loads the f64 bit pattern into AX
|
||||
// before MOVSD'ing into X0); every runtime f64 shape (cast, call,
|
||||
// unary, ident, struct-field load) needs the explicit MOVSD path.
|
||||
// Mirror of cstage cg_widen_tagged_store's float arm. Wwstage has no
|
||||
// checker so we classify via exprfloatkind (same shape used by cgcast)
|
||||
// and resolve the variant tag by name directly — rhstargetname has no
|
||||
// N_FLOATLIT / N_CALL / N_DOT branch and would fall through to the
|
||||
// str-shape fallback that picks tag 0 for an `(i64 | f64)` union.
|
||||
let fkind: i32 = exprfloatkind(c, src);
|
||||
// Mirror of cstage cg_widen_tagged_store's float arm. Classify off
|
||||
// the checker stamp (src.type_) — the SSoT cstage reads via
|
||||
// node_isfloat / type_isf32 — and resolve the variant tag by name
|
||||
// directly: rhstargetname has no N_FLOATLIT / N_CALL / N_DOT branch
|
||||
// and would fall through to the str-shape fallback that picks tag 0
|
||||
// for an `(i64 | f64)` union. The armed asserttyped bail (check.ww)
|
||||
// guarantees src carries a non-nil stamp, so the sibling-evidence
|
||||
// loud-abort that used to pin "the float arm requires a stamped
|
||||
// value" is dead and removed.
|
||||
let fkind: i32 = 0;
|
||||
if (src != nil) {
|
||||
let srct: *tinfo = src.type_: *tinfo;
|
||||
if (typeisf32(srct)) { fkind = 1; }
|
||||
else { if (typeisfloat(srct)) { fkind = 2; }; };
|
||||
};
|
||||
if (fkind != 0) {
|
||||
// #121 (Package B) RESIDUAL sibling-evidence guard, pin form.
|
||||
// Post-collapse exprfloatkind reads src.type_; fkind!=0 here
|
||||
// implies src.type_!=nil — making this assertion structurally
|
||||
// unreachable today. It is RETAINED on purpose to PIN the
|
||||
// contract: "the float arm requires a stamped value." If a
|
||||
// future change replaces exprfloatkind with a non-stamp-driven
|
||||
// classifier (or adds a float-store dispatch path that doesn't
|
||||
// pre-read the stamp), this guard catches the regression. Loud-
|
||||
// abort idiom mirrors cgbin's twin above + cgenstmt.ww:1405/
|
||||
// 1475 + asserttyped file:line at check.ww:3340-3344.
|
||||
if (src != nil) { if (src.type_ == nil) {
|
||||
let msg: str = "cgwidentaggedstore float-arm: src unstamped (#121 sibling-evidence) at ";
|
||||
os.write(2, msg.ptr, msg.len: u64);
|
||||
if (src.file.len > 0) {
|
||||
os.write(2, src.file.ptr, src.file.len: u64);
|
||||
os.write(2, ":".ptr, 1u64);
|
||||
let ls: str = strconv.i32tos(src.line, strconv.base.DEC);
|
||||
os.write(2, ls.ptr, ls.len: u64);
|
||||
os.write(2, " ".ptr, 1u64);
|
||||
};
|
||||
let kn: str = nkname(src.kind);
|
||||
os.write(2, kn.ptr, kn.len: u64);
|
||||
os.write(2, "\n".ptr, 1u64);
|
||||
os.exit(1);
|
||||
}; };
|
||||
let fmov: str = "MOVSD";
|
||||
if (fkind == 1) { fmov = "MOVSS"; };
|
||||
cgexpr(c, src);
|
||||
|
||||
Reference in New Issue
Block a user