cgen: key the str/slice arg recognizers off the checker stamp

The wwstage nodeisstr/nodeisslice recognizers were name-keyed for
every non-local shape: an indirect fn-pointer callee ((*f)() — the
errnotest #59.5 divergence, streq receiving a shifted register file)
and module-global let/const idents (path.sepstr — union-widen pushes
zero-filled len/cap) both fell to false while cstage keys off the
checker stamp unconditionally. Both recognizers now fall back to the
stamped n.type_; push and pop sites share them, so the drain stays
balanced by construction. Graduates the #59.5 errnotest pin.
This commit is contained in:
2026-08-08 00:58:04 +09:00
parent 90af21e132
commit c421c2b20a
6 changed files with 103 additions and 7 deletions

View File

@@ -1342,6 +1342,11 @@ fn nodeisslice(c: *cgen, n: *syntax.node) bool = {
if (deflookup(c, nm)) {
return syntax.typeisslice(n.type_: *syntax.tinfo);
};
// #142-adjacent: module-global let/const slice ident — the
// str twin's rationale verbatim (see nodeisstr N_IDENT).
if (isletvar(c, nm)) {
return syntax.typeisslice(n.type_: *syntax.tinfo);
};
return false;
};
if (k == syntax.nkind.N_SLICE) { return true; };
@@ -1376,7 +1381,13 @@ fn nodeisslice(c: *cgen, n: *syntax.node) bool = {
return isslicetype(c, rtyp);
};
};
return false;
// #59.5: a callee that is neither N_IDENT nor N_DOT — an
// indirect call through a fn-pointer VALUE (`(*f)()`,
// N_UN TK_STAR) — used to fall to false, so a slice return
// pushed one word and cgcall's pop sizer under-drained.
// Read the checker stamp (check.ww fn-VALUE callee arm),
// the callee-shape-blind key cstage node_isslice uses.
return syntax.typeisslice(n.type_: *syntax.tinfo);
};
// N_DOT: read the checker-stamped n.type_. Struct field, nested
// dot, value-struct hops, and pseudo-fields (.ptr/.len/.cap) all
@@ -1465,6 +1476,14 @@ fn nodeisstr(c: *cgen, n: *syntax.node) bool = {
if (deflookup(c, nm)) {
return syntax.typeisstr(n.type_: *syntax.tinfo);
};
// #142-adjacent: a module-global let/const str ident (path's
// `const sepstr: str`) is neither a frame slot nor a def; the
// false fall-through sent its union-widen push to the scalar
// arm (len/cap zero-filled). Read the checker stamp, the key
// cstage node_isstr uses unconditionally.
if (isletvar(c, nm)) {
return syntax.typeisstr(n.type_: *syntax.tinfo);
};
return false;
};
if (k == syntax.nkind.N_CALL) {
@@ -1489,7 +1508,9 @@ fn nodeisstr(c: *cgen, n: *syntax.node) bool = {
return isstrtype(c, rtyp);
};
};
return false;
// #59.5: indirect fn-pointer callee (`(*f)()`) — read the
// checker stamp; see the nodeisslice N_CALL twin above.
return syntax.typeisstr(n.type_: *syntax.tinfo);
};
// #46 (F7-c2): `arr[i]` whose element is a str. The prior structural
// walk only recognised N_IDENT and N_DOT bases (idxelemtn off the