wcc/ww: tagged-element classify keys on the stamp, not a base whitelist

cgindex's tagged-element classification whitelisted base node kinds;
call- and slice-based tagged elements fell off the list and dropped
the payload words (review finding #23). Classify by the stamped
element type. 989_taggedidx_run pins cs==ww (red 2/6 pre-fix).
This commit is contained in:
2026-06-12 00:17:55 +09:00
parent 0625af1309
commit 47b971330b
5 changed files with 256 additions and 36 deletions

View File

@@ -24669,18 +24669,22 @@ fn cgindex(c: *cgen, n: *node) void = {
elemisstr = isstrtype(c, etn);
elemisslice = isslicetype(c, etn);
};
// N_DOT / N_INDEX base (`x.o[i]`, chained `m[i][j]`): the
// element tinfo is n.type_ (the checker-stamped indexresult),
// same source the esz/str/slice/float flags read above. Mirror
// cstage cgen.c:8101 `esubu->kind == TY_TAGGED` — classified for
// ANY base, NOT gated on N_IDENT, and NOT excluding the nullable
// fold (slot_sz=8 degrades the copy arm to one MOVQ, matching
// cstage's fallback `MOVQ AX,BX; MOVQ (BX),AX`). #261: without
// this an N_DOT-base tagged element fell to the scalar
// loadopsz path and silently dropped the tag/payload-high word.
// N_UN deref base joins for the same reason (#61 C).
if (base.kind == nkind.N_DOT || base.kind == nkind.N_INDEX
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
// Any NON-ident base (`x.o[i]`, chained `m[i][j]`, `(*p)[i]`,
// call `f()[i]`, slice `s[a:b][i]`, typeassert …): the element
// tinfo is n.type_ (the checker-stamped indexresult), same source
// the esz/str/slice/float flags read above. Mirror cstage
// cgen.c:8101 `esubu->kind == TY_TAGGED` — classified for ANY
// base, NOT gated on a base-kind whitelist, and NOT excluding the
// nullable fold (slot_sz=8 degrades the copy arm to one MOVQ,
// matching cstage's fallback `MOVQ AX,BX; MOVQ (BX),AX`).
// #261: without the classify an N_DOT-base tagged element fell to
// the scalar loadopsz path and dropped the tag/payload-high word;
// #23 (F7-c6): the prior N_DOT/N_INDEX/N_UN whitelist still missed
// an N_CALL / N_SLICE base (`f()[i]` / `s[a:b][i]`) → lone
// `MOVQ (AX),AX` (tag only) vs cstage's full 4-word cursor
// (cs rc=50 / ww rc=40). Dropping the whitelist for the stamp read
// closes the base-kind class by construction.
if (base.kind != nkind.N_IDENT) {
let dt: *tinfo = n.type_: *tinfo;
if (dt != nil) {
if (typeistagged(dt)) {