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:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user