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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user