w6c+w6c_ww: (*p)[i] deref base materializes the array ADDRESS (#61 C)

Both stages SEGV'd identically (byte-id-blind): cgun's TK_STAR emitted
a scalar MOVQ (AX),AX for an array pointee, so the index consumed
a[0]'s VALUE as its base — a wild deref. An array value IS its address
everywhere in this cgen (#270-1a), so the ARRAY pointee now takes the
same skip as the #185 *fn deref in both stages: `*p` leaves AX = p's
value, and every consumer that materializes a complex index base via
cgexpr(base) — N_INDEX read fallback, cgassign store/compound, TK_AMP,
N_SLICE — gets the array address from the one deref choke-point.

wwstage additionally joins the N_UN-TK_STAR base to the stamped-tinfo
esz arms (cgindex / cgassign store + compound / TK_AMP &(*p)[i]) where
cstage reads base->type uniformly: without it, esz fell to the 8B
default and a narrow element would mis-stride the moment the base
started materializing (cs!=ww only reachable post-choke-point-fix,
which is why it rides this commit).

949_ptrarr_index_run grows the deref_* rows: read (8B/4B/param-base),
write (8B / 1B+neighbor-guards), compound — runtime + byte-id, the only
nets that can see a both-stages-identical miscompile.
This commit is contained in:
2026-06-04 22:08:11 +09:00
parent eea3e197c2
commit 33ec0fb1ac
5 changed files with 169 additions and 20 deletions

View File

@@ -3976,11 +3976,19 @@ cgexpr(Cg *c, Node *n, Local *locals)
* load the first instruction word and CALL
* would segfault on that junk. Mirror
* ref/harec/src/check.c expr_call's
* STORAGE_POINTER→STORAGE_FUNCTION skip. */
* STORAGE_POINTER→STORAGE_FUNCTION skip.
* #61 C: same skip for an ARRAY pointee — an
* array value IS its address everywhere in
* this cgen (#270-1a), so `*p` on `*[N]T`
* 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. */
Type *rt = n->type;
Type *ru = (rt && rt->kind == TY_NAMED)
? rt->under : rt;
if (ru && ru->kind == TY_FN)
if (ru && (ru->kind == TY_FN
|| ru->kind == TY_ARRAY))
break;
}
/* f64/f32 result rides X0 (SSE), not AX — an integer