cgen: B5-c4 #93 deref-index pointee chase — the one spurious MOVQ, #263-polarity

Trace at the c3 tip: cs-vs-ww diff on l2_local/kb5_def93 = exactly ONE
line, a spurious `MOVQ (AX), AX`. The deciding site is the cgexpr
N_UN(STAR) pointee classify (`ru`): the single peel left a 2-LEVEL
alias pointee TY_NAMED, the ARRAY skip (#61-C — an array value IS its
address, #270-1a) missed, and the scalar load pulled a[0]'s VALUE as
the index base — wild pointer, SIGSEGV 139 on cs. KEN #263-POLARITY:
cs is the WRONG side; ww chases and is the runtime-correct reference —
cs converges on WW's asm. Single-site grant: the one `ru` computation
(shared by the FN/ARRAY/TAGGED skip predicates) → type_chase_named.
Raw `->under` in cgen.c 59→58. #93 CLOSES.

TRAIN INVARIANT holds at the tip: cs-only; _ww binaries bit-identical
to the bcd948d baseline md5s across all four commits. cs movers vs the
c3 tip bounded to EXACTLY the deref-index shapes: l2_local, kb4_x93,
kb5_def93. Zero ww movers. Detector pinned: kb4_xampdef STAYS 139/139
(#94, out-of-train — `&D[i]` indexed def base, a different site).

Graduations (cs SEGV-139 / ww 0, BYTE-DIVERGE → 0/0 BYTE-ID):
g93_l2_local (the banked rob spelling), g93_def (kb5_def93, the
natural `(*p)[2]` def twin). g93_1lvl_ctl (1-level control) held 0/0
byte-id throughout.

944_alias_cgen_b5_run 28→31 rows (84 checks); 944 family green;
sizelint 0.
This commit is contained in:
2026-06-06 02:26:29 +09:00
parent 140755d221
commit 837fdb4753
2 changed files with 52 additions and 3 deletions

View File

@@ -4305,10 +4305,14 @@ cgexpr(Cg *c, Node *n, Local *locals)
* leaves AX = p's value. The scalar load
* below pulled a[0]'s VALUE and `(*p)[i]`
* then dereferenced it as the index base —
* a wild pointer, SIGSEGV on both stages. */
* a wild pointer, SIGSEGV on both stages.
* #93: the single peel left a 2-LEVEL alias
* pointee NAMED — the ARRAY skip missed and
* the scalar load fired (one spurious
* MOVQ (AX),AX, SEGV); ww chases and is the
* runtime-correct reference (#263 polarity). */
Type *rt = n->type;
Type *ru = (rt && rt->kind == TY_NAMED)
? rt->under : rt;
Type *ru = type_chase_named(rt);
if (ru && (ru->kind == TY_FN
|| ru->kind == TY_ARRAY))
break;