cgen: unify cstage slice-let onto shared 3-word store path
Delete the vestigial inline slice-let builder in N_LET; a
`let s: []T = buf[lo:hi]` now routes through cgexpr's N_SLICE path
plus the generic 3-word store -- exactly as cstage's own str-let and
the wwstage already do. cap is unchanged (still hi-lo); the
cap = base_cap-lo fix is the following commit.
The builder duplicated cgexpr's N_SLICE base/hi dispatch and was a
strict subset of it, so for local bases the deletion is value-neutral
(ptr=base+lo, len=hi-lo, cap=hi-lo); only the routing bytes move,
aligning cstage down to the leaner wwstage and closing find-4
(rule-10). Verified byte-identical cs==ww across the slice-let matrix
{array,slice}x{local,global}x{hi-default,hi-explicit}.
Also fixes a cstage miscompile: the builder loaded a global-base
sub-slice via localfind->0 + BP-relative (no let_islet/masym), so a
`let s = G[lo:hi]` over a global array or slice G emitted
LEAQ/MOVQ 0(BP) garbage instead of the symbol address. Routing
through the global-aware shared path makes these correct
(ken-confirmed broken->correct).
This commit is contained in:
@@ -6566,60 +6566,14 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame)
|
|||||||
cg_widen_tagged_store(c, locals, lu, n->rhs, D_BP, off, sz);
|
cg_widen_tagged_store(c, locals, lu, n->rhs, D_BP, off, sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* slice expression initialiser: build a {ptr, len, cap} header
|
/* Every slice initialiser routes here — fn-return, slice
|
||||||
* referring to the source. Element size assumed to be 1
|
* ident, slice param, and sub-slice `buf[lo:hi]`. cgexpr
|
||||||
* (u8) for now; real element-size scaling is a future TODO. */
|
* leaves (AX=ptr, BX=len, CX=cap); store all three. The
|
||||||
if (n->rhs && n->rhs->kind == N_SLICE && lu
|
* sub-slice case once had a vestigial inline builder that
|
||||||
&& lu->kind == TY_SLICE) {
|
* duplicated cgexpr's N_SLICE path and mishandled global
|
||||||
Node *base = n->rhs->lhs;
|
* bases; dropping it aligns cstage onto wwstage's shared
|
||||||
Node *lo = n->rhs->rhs;
|
* store path (find-4). Runs after the alloc specialisation
|
||||||
Node *hi = n->rhs->cond;
|
* above so that keeps its direct {ptr,0,n} shape. */
|
||||||
Type *bt = base ? base->type : NULL;
|
|
||||||
Type *bu = (bt && bt->kind == TY_NAMED) ? bt->under : bt;
|
|
||||||
/* load base address */
|
|
||||||
if (base->kind == N_IDENT) {
|
|
||||||
int boff = localfind(*locals, base->str);
|
|
||||||
if (bu && bu->kind == TY_ARRAY) {
|
|
||||||
ins2(c, A_LEAQ, amem(D_BP, boff), areg(D_AX));
|
|
||||||
} else {
|
|
||||||
/* slice/str/ptr: load .ptr */
|
|
||||||
ins2(c, A_MOVQ, amem(D_BP, boff), areg(D_AX));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cgexpr(c, base, *locals);
|
|
||||||
}
|
|
||||||
ins1(c, A_PUSHQ, areg(D_AX)); /* save base addr */
|
|
||||||
/* lo (default 0) */
|
|
||||||
if (lo) cgexpr(c, lo, *locals);
|
|
||||||
else cgexpr_int(c, 0);
|
|
||||||
ins1(c, A_PUSHQ, areg(D_AX)); /* save lo */
|
|
||||||
/* hi (default base length) */
|
|
||||||
if (hi) {
|
|
||||||
cgexpr(c, hi, *locals);
|
|
||||||
} else if (bu && bu->kind == TY_ARRAY) {
|
|
||||||
cgexpr_int(c, (long long)bu->alen);
|
|
||||||
} else if (base->kind == N_IDENT && bu &&
|
|
||||||
(bu->kind == TY_SLICE || bu->kind == TY_STR)) {
|
|
||||||
int boff = localfind(*locals, base->str);
|
|
||||||
ins2(c, A_MOVQ, amem(D_BP, boff + 8), areg(D_AX));
|
|
||||||
} else {
|
|
||||||
cgexpr_int(c, 0);
|
|
||||||
}
|
|
||||||
ins2(c, A_MOVQ, areg(D_AX), areg(D_BX)); /* BX = hi */
|
|
||||||
ins1(c, A_POPQ, areg(D_CX)); /* CX = lo */
|
|
||||||
ins1(c, A_POPQ, areg(D_AX)); /* AX = base */
|
|
||||||
ins2(c, A_ADDQ, areg(D_CX), areg(D_AX)); /* AX = base+lo */
|
|
||||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, off + 0));
|
|
||||||
ins2(c, A_SUBQ, areg(D_CX), areg(D_BX)); /* BX = hi-lo */
|
|
||||||
ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, off + 8));
|
|
||||||
ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, off + 16));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Generic slice rhs (e.g. fn returning []u8, slice ident,
|
|
||||||
* slice-typed param). cgexpr leaves (AX=ptr, BX=len, CX=
|
|
||||||
* cap); store all three into the local slot. Runs after
|
|
||||||
* the alloc and N_SLICE specialisations above so they keep
|
|
||||||
* their direct-store shape. */
|
|
||||||
if (n->rhs && lu && lu->kind == TY_SLICE && sz == 24) {
|
if (n->rhs && lu && lu->kind == TY_SLICE && sz == 24) {
|
||||||
cgexpr(c, n->rhs, *locals);
|
cgexpr(c, n->rhs, *locals);
|
||||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, off + 0));
|
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, off + 0));
|
||||||
|
|||||||
Reference in New Issue
Block a user