cgtypeassert kept scrutoff=0 when the scrutinee wasn't an N_IDENT (direct call result, arr[i], p.field, ?, paren-wrap of any of those), so the tag-load fell on (BP) — the saved-BP word — and the payload- load on +8(BP) — the return address. The wwstage repro returned 220 (garbage from RIP) where cstage returned 42 (impl-e1-resume sibling of #199/#201). Mirror cstage cmd/w6c/cgen.c:6300-6316 N_TYPEASSERT non-IDENT arm. Add an `else` branch after the existing N_IDENT path that resolves the tagged type via matchscrutt, alloc an @asrt_spill slot via matchspillsz/localalloc, cgexpr the LHS, then spill the AX/DX/CX tagged-return-ABI words: AX→+0 (tag), DX→+8 (word0), CX→+16 (word1, guarded on spill > 16). Subsequent tag-check + payload load indexes off the spill like the IDENT path. Helpers reused from cgmatch (cgenexpr.ww:1422-1460). cstage's cgtypeassert omits the cgmatch 4-word R8→+24 spill (rule-10 stage symmetry: rather than diverge into a 32B-payload case the test suite doesn't exercise, mirror cstage exactly and file the cstage omission inline). Filed inline: cstage cgtypeassert needs the same R8→+24 path cgmatch already has (drew's design rationale, blocked by the rule-10 floor today). 772_typeassert_nonident: 7 rows (call_as_size — the repro, call_as_str — CX→+16 spill + BX post-load, call_as_namedvoid — void-variant tag-check fires, payload load is a 0-byte no-op, call_as_fnptr — fn-ptr variant 8B word0, call_as_u8 / call_as_i16 — narrow scalar round-trip via MOVQ + MOVQ confirms no truncation, branched_call_as — runtime-chosen tag). Each row gated on cstage runtime + wwstage runtime + cs.s == ww.s byte-identity.
235 KiB
235 KiB