// `&D[i]` over a DEF-array (indexed &-base), migrated from // test/wcc/944_def_amp_idx_run.c (#94). BOTH stages SEGV'd at the TK_AMP // N_INDEX N_IDENT base classify: a def-array base matched neither the local nor // the let leg and fell to a wrong else — cstage zero-based the addend (XORQ // BX,BX → wild ptr) while wwstage value-loaded the symbol (MOVQ name(SB) = D[0], // not its address). DIVERGENT asm, both wild — only a RUNTIME row pins this // class. The fix adds one def-array leg per stage mirroring the working let leg // (cs `def_isarraydef → LEAQ name(SB),BX`; ww `defvartnode`→isglobalarr→LEAQ), // so the existing i*esz scale + ADDQ round-trips; cs/ww now emit byte-identical // LEAQ-SB asm. The `*p` deref is spelled `let v: T = *p;` because `*p: T` parses // as `*(p: T)` (cast binds tighter than prefix-*), a spurious "cannot deref". // // amp_int/amp_u32/amp_arg are the SEGV repros (read the def-array element back // through the taken pointer, narrow esz on amp_u32); ctrl_plain/ctrl_read/ctrl_2d // are the controls the new leg must not perturb (plain &D, indexed read, 2D // &M[1][1]). Distinct def symbol names per shape since they share one module. package def_amp_idx_test; def Dint: [3]int = [1000: int, 2000: int, 3000: int]; def Du32: [3]u32 = [1000: u32, 2000: u32, 3000: u32]; def M2: [2][2]int = [[10: int, 20: int], [30: int, 40: int]]; fn deref_int(p: *int) int = { let v: int = *p; return v; }; @test fn amp_int() void = { let p: *int = &Dint[2]; let v: int = *p; assert(v == 3000); }; @test fn amp_u32() void = { let p: *u32 = &Du32[2]; let v: u32 = *p; assert(v == 3000u32); }; @test fn amp_arg() void = { // &D[2] as a func-arg (context-independent base). assert(deref_int(&Dint[2]) == 3000); }; @test fn ctrl_plain() void = { let p: *[3]int = &Dint; assert((*p)[0] == 1000); }; @test fn ctrl_read() void = { assert(Dint[1] == 2000); }; @test fn ctrl_2d() void = { let q: *int = &M2[1][1]; let v: int = *q; assert(v == 40); };