w6c_ww: matchscrutt resolves non-ident index bases via stamped type (fix #48)
Pre-#48 wwstage matchscrutt's N_INDEX arm required ibase.kind == N_IDENT; an index over any other base (match (h.xs[i]) = N_INDEX over N_DOT, the regex fold-2a re.insts[i] shape) returned nil, so cgmatch dispatched with scrutt=nil — every case arm's variant index clamped to 0 (CMPQ $0) and @match_spill fell to the 16B default. SILENT cs≠ww runtime-wrong (cstage N_MATCH reads the checker-stamped s->type for every scrutinee shape, cmd/w6c/cgen.c:7510). The non-ident-base arm now returns the scrutinee node itself behind an istaggedtype gate — the stamped-carrier pattern of the #67 N_DOT arm and the #45 cgtypetest fix — so any base shape resolves the element's tagged tinfo for both variant indices and spill sizing. Same-class load half, one commit per the #133-expanded precedent: cgindex's generic-fallback tagged-element load was the only arm missing the slot>24 R8 word (both ident arms and cstage cgen.c:9106-9117 have it), so a >24B-slot element via a non-ident base under-read the cursor and the now-correctly-sized spill stored stale R8. 928_match_nonident_idx_run pins the repro shape (field-base slice index, all variants both polarities), the regex shape (56B-slot inst-like union, payload reads within the 32B cursor per #43), and ident/array/slice ident-base controls — per row cs==ww byte-id + runtime via both drivers. w6c/wwdump combined.ww regen'd via canonical make; selfhost corpus hand-cmp'd cs==ww both stages. Pre-existing siblings surfaced while probing, NOT folded (rule 11), reported for filing: (a) cgindex element classification skips N_CALL bases entirely (mk()[0] — wrong esz + not tagged-classified, cs≠ww, runtime-wrong, also non-match contexts); (b) `as` on a non-ident carrier still clamps the variant to 0 (cgtagvariantidx's N_TTAGGED node gate rejects the stamped carrier; byte-identical to master, the #200 spill fix covered only slot sizing).
This commit is contained in:
@@ -17790,7 +17790,18 @@ fn matchscrutt(c: *cgen, scrut: *node) *node = {
|
||||
if (k == nkind.N_INDEX) {
|
||||
let ibase: *node = scrut.lhs;
|
||||
if (ibase == nil) { return nil; };
|
||||
if (ibase.kind != nkind.N_IDENT) { return nil; };
|
||||
if (ibase.kind != nkind.N_IDENT) {
|
||||
// #48: non-ident index base (s.field[i], call()[i],
|
||||
// nested). Only idents carry a declared tnode to walk,
|
||||
// so resolve from the checker-stamped element tinfo
|
||||
// instead — the #45/#67 stamped-carrier pattern; cgmatch
|
||||
// gates on istaggedtype and reads scrutt.type_ directly.
|
||||
// cstage N_MATCH reads s->type for every scrutinee shape
|
||||
// (cmd/w6c/cgen.c:7510). Pre-#48 this returned nil and
|
||||
// the variant clamped to 0 + @match_spill mis-sized.
|
||||
if (istaggedtype(c, scrut)) { return scrut; };
|
||||
return nil;
|
||||
};
|
||||
let bl: *local = localfindnode(c, ibase.str);
|
||||
let btn: *node = nil;
|
||||
if (bl != nil) { btn = bl.tnode; }
|
||||
@@ -21468,8 +21479,15 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
};
|
||||
if (elem_tagged) {
|
||||
// AX holds the element address. Copy to BX (loading slot+0
|
||||
// into AX clobbers it), then read slot words.
|
||||
// into AX clobbers it), then read slot words. #48: the >24
|
||||
// R8 word was missing ONLY in this fallback arm (both ident
|
||||
// arms have it) — a >24B-slot element via a non-ident base
|
||||
// under-read the cursor and the match spill stored stale R8.
|
||||
// Mirrors cstage cgen.c:9106-9117.
|
||||
emitline("\tMOVQ\tAX, BX\n");
|
||||
if (elem_slot_sz > 24) {
|
||||
emitline("\tMOVQ\t24(BX), R8\n");
|
||||
};
|
||||
if (elem_slot_sz > 16) {
|
||||
emitline("\tMOVQ\t16(BX), CX\n");
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user