cgen: default the hi bound of a slice/str-field slice, both stages
x.slicefield[:] / x.strfield[2:] emitted MOVQ $0 for the omitted hi
bound on BOTH stages (N_IDENT-gated dispatch; symmetric, so byte
identity never caught it) in all four sites: cgexpr N_SLICE + pushargs
(cstage), cgslice + pushargsrev (wwstage). The new arm re-evaluates
the pure field read for its {ptr,len,cap} header and takes .len,
covering local, viaptr, dot-chain, (*p), arr[i], and global inners.
Call inners still loud-reject upstream. Sibling of the #252/#257
array-field arms.
This commit is contained in:
@@ -10112,6 +10112,14 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
} else {
|
||||
ins2(c, A_MOVQ, amem(D_BP, boff + 8), areg(D_AX));
|
||||
}
|
||||
} else if (base->kind == N_DOT && bu &&
|
||||
(bu->kind == TY_SLICE || bu->kind == TY_STR)) {
|
||||
/* slice/str FIELD base — the arg twin
|
||||
* of the cgexpr N_SLICE default-hi
|
||||
* arm above; same re-eval-for-header
|
||||
* rationale. */
|
||||
cgexpr(c, base, locals);
|
||||
ins2(c, A_MOVQ, areg(D_BX), areg(D_AX));
|
||||
} else {
|
||||
cgexpr_int(c, 0);
|
||||
}
|
||||
@@ -13242,6 +13250,18 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
ins2(c, A_MOVQ, amem(D_BP, boff + 8),
|
||||
areg(D_AX));
|
||||
}
|
||||
} else if (base && base->kind == N_DOT && bu &&
|
||||
(bu->kind == TY_SLICE || bu->kind == TY_STR)) {
|
||||
/* slice/str FIELD base (#252's slice twin): the old
|
||||
* fall-through emitted $0 — a silent 0/negative len on
|
||||
* BOTH stages, byteid-blind. Re-evaluate the field
|
||||
* read for its header (a pure place: call inners
|
||||
* loud-reject upstream; cgexpr's N_DOT slice/str arms
|
||||
* leave AX=ptr, BX=len, CX=cap for every supported
|
||||
* inner — ident, chain, (*p), arr[i]) and take .len.
|
||||
* All scratch regs are dead at the hi step. */
|
||||
cgexpr(c, base, locals);
|
||||
ins2(c, A_MOVQ, areg(D_BX), areg(D_AX));
|
||||
} else {
|
||||
cgexpr_int(c, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user