w6c+wwstage: emit global str/slice len via .len field load (#231)
len(str-or-slice-global) was wrong in both stages, differently. cstage's len() arm did a BP-relative slot load; localfind returns 0 for a global, so it emitted `MOVQ 8(BP),AX` — a bogus stack slot. wwstage's arm only handled locals; a global fell through to cgexpr, which loads the whole header and leaves AX=.ptr, not .len. Both stages now emit the global .len load — LEAQ name(SB),CX; MOVQ 8(CX),AX (.len field; header is ptr@0/len@8/cap@16). The LEAQ symbol routes through the post-#1 value mangle (cstage mahint c->cur_mod, wwstage emitsymnamehint c.curmod), not a raw name, so a private same-module same-leaf str global can't re-open the #1 collision. The local-str case is unchanged (control). Slice-global rows wait on #233 (cstage rejects `let g: []u8 = [...]` init); the str global proves the path. Byte-id-blind, so a committed runtime + cs==ww test (797) is the net.
This commit is contained in:
@@ -5216,7 +5216,23 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
if (u && (u->kind == TY_SLICE || u->kind == TY_STR)
|
||||
&& a->kind == N_IDENT) {
|
||||
int off = localfind(locals, a->str);
|
||||
ins2(c, A_MOVQ, amem(D_BP, off + 8), areg(D_AX));
|
||||
if (off == 0 && let_islet(a->str)) {
|
||||
/* #231: str/slice GLOBAL — the .len word
|
||||
* lives at the global's address+8, not a
|
||||
* BP-relative slot (off==0 → MOVQ 8(BP)
|
||||
* read a bogus stack slot). Route through
|
||||
* the post-#1 value mangle so a private
|
||||
* same-module same-leaf global isn't
|
||||
* mis-resolved. */
|
||||
ins2(c, A_LEAQ,
|
||||
mahint(c, a->str, c->cur_mod),
|
||||
areg(D_CX));
|
||||
ins2(c, A_MOVQ, amem(D_CX, 8),
|
||||
areg(D_AX));
|
||||
} else {
|
||||
ins2(c, A_MOVQ, amem(D_BP, off + 8),
|
||||
areg(D_AX));
|
||||
}
|
||||
} else if (u && u->kind == TY_ARRAY) {
|
||||
ins2(c, A_MOVQ, aimm((long long)u->alen), areg(D_AX));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user