w6c+cgen: len() over indexed str/slice element extracts .len (fix #19)
`len(xs[i])` over a [N]str/[]str (and []T slice) element returned the element's .ptr, not its length, on BOTH stages (shared gap, not rule-10): the len() builtin had no N_INDEX arm, so it fell to the bare-cgexpr fallback, where the N_INDEX str/slice load (cgslicehdr) leaves AX=.ptr, BX=.len, CX=.cap — and len() returned AX (the ptr) as the length. Add an N_INDEX arm gated on a (TY_SLICE||TY_STR) element in both stages: cgexpr the element, then MOVQ BX,AX to shuffle the len word into the result reg — the same shape as the #14 .len pseudo-field fix. Byte-id neutral (no bootstrap source uses len(indexed-element)); regenerated w6c + wwdump combined.ww. New 802_lenidx_run pins runtime + cs==ww.
This commit is contained in:
@@ -23887,6 +23887,21 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// #19: len() of an INDEXED str/slice element
|
||||
// (`len(xs[i])`). The N_INDEX str/slice load
|
||||
// leaves AX=.ptr, BX=.len, CX=.cap — the bare
|
||||
// cgexpr fallback below returned AX (the ptr)
|
||||
// AS the length. Shuffle BX (the len word)
|
||||
// into AX, the same MOVQ BX,AX shape as the
|
||||
// #14 .len pseudo-field fix. Same family as
|
||||
// #18 (shared cstage==wwstage gap, not rule-10).
|
||||
if ((u.kind == tykind.TY_SLICE
|
||||
|| u.kind == tykind.TY_STR)
|
||||
&& a.kind == nkind.N_INDEX) {
|
||||
cgexpr(c, a);
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
return;
|
||||
};
|
||||
if (u.kind == tykind.TY_ARRAY) {
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(u.alen: i64);
|
||||
|
||||
@@ -4180,6 +4180,21 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// #19: len() of an INDEXED str/slice element
|
||||
// (`len(xs[i])`). The N_INDEX str/slice load
|
||||
// leaves AX=.ptr, BX=.len, CX=.cap — the bare
|
||||
// cgexpr fallback below returned AX (the ptr)
|
||||
// AS the length. Shuffle BX (the len word)
|
||||
// into AX, the same MOVQ BX,AX shape as the
|
||||
// #14 .len pseudo-field fix. Same family as
|
||||
// #18 (shared cstage==wwstage gap, not rule-10).
|
||||
if ((u.kind == tykind.TY_SLICE
|
||||
|| u.kind == tykind.TY_STR)
|
||||
&& a.kind == nkind.N_INDEX) {
|
||||
cgexpr(c, a);
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
return;
|
||||
};
|
||||
if (u.kind == tykind.TY_ARRAY) {
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(u.alen: i64);
|
||||
|
||||
@@ -23887,6 +23887,21 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// #19: len() of an INDEXED str/slice element
|
||||
// (`len(xs[i])`). The N_INDEX str/slice load
|
||||
// leaves AX=.ptr, BX=.len, CX=.cap — the bare
|
||||
// cgexpr fallback below returned AX (the ptr)
|
||||
// AS the length. Shuffle BX (the len word)
|
||||
// into AX, the same MOVQ BX,AX shape as the
|
||||
// #14 .len pseudo-field fix. Same family as
|
||||
// #18 (shared cstage==wwstage gap, not rule-10).
|
||||
if ((u.kind == tykind.TY_SLICE
|
||||
|| u.kind == tykind.TY_STR)
|
||||
&& a.kind == nkind.N_INDEX) {
|
||||
cgexpr(c, a);
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
return;
|
||||
};
|
||||
if (u.kind == tykind.TY_ARRAY) {
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(u.alen: i64);
|
||||
|
||||
Reference in New Issue
Block a user