diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 731ea942..6cbde21f 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -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; diff --git a/test/wcc/944_alias_cgen_b5_run.c b/test/wcc/944_alias_cgen_b5_run.c index 58f72f01..f12be296 100644 --- a/test/wcc/944_alias_cgen_b5_run.c +++ b/test/wcc/944_alias_cgen_b5_run.c @@ -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