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);
|
||||
break;
|
||||
}
|
||||
/* slice expression initialiser: build a {ptr, len, cap} header
|
||||
* referring to the source. Element size assumed to be 1
|
||||
* (u8) for now; real element-size scaling is a future TODO. */
|
||||
if (n->rhs && n->rhs->kind == N_SLICE && lu
|
||||
&& lu->kind == TY_SLICE) {
|
||||
Node *base = n->rhs->lhs;
|
||||
Node *lo = n->rhs->rhs;
|
||||
Node *hi = n->rhs->cond;
|
||||
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. */
|
||||
/* Every slice initialiser routes here — fn-return, slice
|
||||
* ident, slice param, and sub-slice `buf[lo:hi]`. cgexpr
|
||||
* leaves (AX=ptr, BX=len, CX=cap); store all three. The
|
||||
* sub-slice case once had a vestigial inline builder that
|
||||
* duplicated cgexpr's N_SLICE path and mishandled global
|
||||
* bases; dropping it aligns cstage onto wwstage's shared
|
||||
* store path (find-4). Runs after the alloc specialisation
|
||||
* above so that keeps its direct {ptr,0,n} shape. */
|
||||
if (n->rhs && lu && lu->kind == TY_SLICE && sz == 24) {
|
||||
cgexpr(c, n->rhs, *locals);
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, off + 0));
|
||||
|
||||
Reference in New Issue
Block a user