wcc/cgen: #21 def-str/slice by-value arg pushes all 3 header words (wwstage)

Recognizer flip: nodeisstr/nodeisslice type-key a def ident (was local-keyed → fell to scalar default PUSHQ, dropped len/cap). Mirrors cstage node_isstr/node_isslice; push/pop stay symmetric via the shared recognizer. wwstage-only; cstage already correct.
This commit is contained in:
2026-06-09 15:33:07 +09:00
parent f767819b41
commit f1cd0a3555
4 changed files with 127 additions and 0 deletions

View File

@@ -1149,6 +1149,19 @@ fn nodeisslice(c: *cgen, n: *node) bool = {
let nm: str = n.str;
let lc: *local = localfindnode(c, nm);
if (lc != nil) { return isslicetype(c, lc.tnode); };
// #21: a module-level `def g: []T` ident is not a frame
// slot (localfindnode→nil), so the local arm above misses
// it and it would fall to the scalar single-PUSHQ default,
// dropping len/cap. cstage's node_isslice is type-keyed
// (cmd/w6c/cgen.c:226-229 type_isslice(n->type)); align
// wwstage UP by reading the checker-stamped .type_ (the def
// decl's str/slice type node, check.ww exprtype N_IDENT
// arm). A def has no DATA symbol — it rides cgident's
// const-fold, so the push site and cgcall's pop sizer flip
// together on this shared recognizer (load-bearing).
if (deflookup(c, nm)) {
return typeisslice(n.type_: *tinfo);
};
return false;
};
if (k == nkind.N_SLICE) { return true; };
@@ -1226,6 +1239,19 @@ fn nodeisstr(c: *cgen, n: *node) bool = {
// MOVQ BX,CX shuffle on returns of str-aliased locals.
if (isstrtype(c, lc.tnode)) { return true; };
};
// #21: a module-level `def s: str` ident is not a frame slot
// (localfindnode→nil), so the local arm above misses it and
// it would fall to the scalar single-PUSHQ default, dropping
// len/cap. cstage's node_isstr is type-keyed (cmd/w6c/
// cgen.c:213-216 type_isstr(n->type)); align wwstage UP by
// reading the checker-stamped .type_ (the def decl's str type
// node, check.ww exprtype N_IDENT arm). A def has no DATA
// symbol — it rides cgident's const-fold (LEAQ _S_n, MOVQ
// $len), so the push site and cgcall's pop sizer flip together
// on this shared recognizer (load-bearing).
if (deflookup(c, nm)) {
return typeisstr(n.type_: *tinfo);
};
return false;
};
if (k == nkind.N_CALL) {