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;

View File

@@ -99,6 +99,16 @@
* | live-truncation seed) | 0/0
* g89_ret_named_ctl | bare NAMED struct return control — |
* | held 0/0 byte-id throughout | 0/0
* ---- c4 (#93: deref-index pointee chase, #263-polarity) --------
* g93_l2_local | `(*p)[2]` over *arr2 (arr2=arr= |
* | [3]int) — cs emitted ONE spurious |
* | MOVQ (AX),AX (pointee ARRAY skip |
* | missed at 2 levels), SEGV 139; ww |
* | was the runtime-correct side | 0/0
* g93_def | def twin: `(*p)[2]` over &D, D a |
* | 2-lvl alias def array (kb5_def93) | 0/0
* g93_1lvl_ctl | 1-level pointee control — held 0/0 |
* | byte-id throughout | 0/0
*
* K_RUN rows build+run BOTH drivers (cs exit==cswant, ww exit==wwwant)
* and assert cstage/wwstage asm byte-id. K_RUN_NOID asserts both run
@@ -618,6 +628,41 @@ static const struct row rows[] = {
" };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
/* ---- c4: #93 — the N_UN(STAR) pointee classify single-peeled,
* so a 2-level alias ARRAY pointee missed the array skip (an
* array value IS its address, #270-1a) and the scalar load
* pulled a[0]'s VALUE as the index base — ONE spurious
* MOVQ (AX),AX, SIGSEGV on cs. ww chases (the runtime-correct
* reference, #263 polarity): cs converges on WW's asm. */
{ "g93_l2_local",
"package main;\n"
"type arr = [3]int;\n"
"type arr2 = arr;\n"
"export fn main() i32 = {\n"
" let a: arr2 = [1000: int, 2000: int, 3000: int];\n"
" let p: *arr2 = &a;\n"
" if ((*p)[2] != 3000) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g93_def",
"package main;\n"
"type arr0 = [3]i64;\n"
"type arr = arr0;\n"
"def D: arr = [18i64, 29i64, 40i64];\n"
"export fn main() i32 = {\n"
" let p: *arr = &D;\n"
" if ((*p)[2] != 40i64) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
{ "g93_1lvl_ctl",
"package main;\n"
"type arr = [3]int;\n"
"export fn main() i32 = {\n"
" let a: arr = [1000: int, 2000: int, 3000: int];\n"
" let p: *arr = &a;\n"
" if ((*p)[2] != 3000) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_RUN, NULL },
};
static int