wcc/cgen: #148 slice-global by-value call-arg — name(SB) base for global slice ident, not (BP) garbage (cstage)

The slice-IDENT call-arg fast path pushed the header words off off(BP)
where off=localfind(name); for a module-global slice localfind→0, so it
read saved-BP/RIP/caller garbage instead of name(SB). Add the global
branch (LEAQ name(SB) base, push 16/8/0 off it) mirroring the sibling
N_SLICE arm; local path unchanged. cstage-only: wwstage checker-rejects
the shape (#120), so byte-id-safe and the twin defers to #125. Unblocks
path c2-stack (dot/dotdot are faithful module-global []u8). Sibling
structarg fast-path filed #150.
This commit is contained in:
2026-06-08 10:24:48 +09:00
parent 6e1d958d9b
commit 26d6e2abad
3 changed files with 190 additions and 0 deletions

View File

@@ -9081,6 +9081,21 @@ cgexpr(Cg *c, Node *n, Local *locals)
continue;
if (!widen[i] && node_isslice(args[i]) && args[i]->kind == N_IDENT) {
int off = localfind(locals, args[i]->str);
/* #148: localfind→0 for a module global, but the
* header lives at name(SB), not BP+0. Mirror the
* N_SLICE arm's isglobal dispatch below: LEAQ the
* symbol into a base reg, push 16/8/0 off it. */
if (off == 0 && let_islet(args[i]->str)) {
ins2(c, A_LEAQ, masym(c, args[i]->str),
areg(D_BX));
ins2(c, A_MOVQ, amem(D_BX, 16), areg(D_AX));
ins1(c, A_PUSHQ, areg(D_AX));
ins2(c, A_MOVQ, amem(D_BX, 8), areg(D_AX));
ins1(c, A_PUSHQ, areg(D_AX));
ins2(c, A_MOVQ, amem(D_BX, 0), areg(D_AX));
ins1(c, A_PUSHQ, areg(D_AX));
continue;
}
/* push cap, len, ptr (top) so pops give ptr,len,cap */
ins2(c, A_MOVQ, amem(D_BP, off + 16), areg(D_AX));
ins1(c, A_PUSHQ, areg(D_AX));