w6c: resolve ptr-to-array and slice-element aggregate sources (task #6 residue)

The two loud siblings filed in d3822d77: (a) an auto-deref *[N]T
indexed base (hs[k].result) failed cgplaceaddr's N_INDEX arm, which
knew only TY_SLICE/TY_ARRAY bases — add the one-pointer hop (the
(*hs)[k] form made implicit; load shape is the slice .ptr word's);
(b) a bare slice-element aggregate source (use(sl[k])) fell off
aggarg_srcaddr's ident-array-only N_INDEX arm into the #271 loud
stop — route the miss through the same cgplaceaddr fallback the
N_DOT arm uses. Both stages, byte-identical (probe matrix: let-copy,
field-assign, call-arg, return, indexed-store all IDENT).

After this, every ADDRESSABLE aggregate source resolves: ident
(local/module-let), deref, dot-chain, and index over array/slice/
ptr-array spines recurse through cgplaceaddr; the remaining loud
paths are rvalue sources (#40 family) and the #274 const-def arg,
both documented divergences. 8 rows added to idxdot_aggcopy_test.
This commit is contained in:
2026-08-08 19:08:19 +09:00
parent cf69cf2f06
commit 84206ff4ed
3 changed files with 120 additions and 11 deletions

View File

@@ -2313,7 +2313,10 @@ aggarg_srcaddr(Cg *c, Node *src, int dst, Local *locals)
ins2(c, A_MOVQ, areg(D_AX), areg(dst));
return 1;
}
return 0;
/* task #6 sibling: slice-element / non-ident-array base
* (use(sl[k])) — the same C4/#40 place-resolver fallback
* as the N_DOT arm; the missed walk is emission-free. */
return cgplaceaddr(c, src, dst, locals);
}
return 0;
}
@@ -2451,7 +2454,16 @@ cgplaceaddr(Cg *c, Node *n, int dst_reg, Local *locals)
* dispatch first), so their asm is untouched. */
Type *bu = type_chase_named(base->type);
if (bu == NULL) return 0;
if (bu->kind != TY_SLICE && bu->kind != TY_ARRAY)
/* Auto-deref: a *[N]T indexed base takes one pointer hop —
* the (*hs)[k] form made implicit (checker already stamps
* the element type). Load shape is the slice .ptr word's. */
int viaptr = 0;
if (bu->kind == TY_PTR) {
Type *p = type_chase_named(bu->sub);
if (p && p->kind == TY_ARRAY)
viaptr = 1;
}
if (!viaptr && bu->kind != TY_SLICE && bu->kind != TY_ARRAY)
return 0;
Type *et = type_chase_named(n->type);
if (et == NULL) return 0;
@@ -2465,8 +2477,8 @@ cgplaceaddr(Cg *c, Node *n, int dst_reg, Local *locals)
if (!cgplaceaddr(c, base, dst_reg, locals)) return 0;
/* A slice place holds the {ptr,len,cap} header — the
* element base is its .ptr word; an array place IS the
* element storage. */
if (bu->kind == TY_SLICE)
* element storage; a *[N]T place holds the array address. */
if (bu->kind == TY_SLICE || viaptr)
ins2(c, A_MOVQ, amem(dst_reg, 0), areg(dst_reg));
ins1(c, A_POPQ, areg(D_AX));
ins2(c, A_ADDQ, areg(D_AX), areg(dst_reg));