w6c+w6c_ww: store full slice header for struct-literal slice fields (fix #24)
cg_structlit_fill / cgstructlitfill had a TY_STR arm that stored all
three header words (ptr@+0, len@+8, cap@+16) but no TY_SLICE arm, so a
slice field in a struct literal `cl{ items = b, n = .. }` fell through to
the generic scalar tail and stored only the ptr word — the field's .len
and .cap read 0. str fields (the same 24B {ptr,len,cap} shape) worked;
slice fields silently dropped two words.
Both stages emitted IDENTICAL wrong asm, so the 990-997 byte-id gate was
green on both-wrong; runtime readback is the only correctness net. Same
is_str/is_slice discrimination gap as #10 part-b, here in the
struct-literal field-init path.
A slice is the same 24B header shape as str, so widen the str arm's
guard to TY_STR || TY_SLICE (cstage) / isstrtype || isslicetype
(wwstage) and let a slice ride the already-correct 3-word store. The
TAGGED arm stays ordered before it, so a nullable/tagged slice
(TY_TAGGED) still routes to the widener, not the 3-word store.
Test 689 (table-driven, runtime readback + dual-stage asm byte-id):
slice .len/.cap/.ptr, a scalar field beside/before the slice, a slice at
a non-zero field offset, two slice fields, and a str field beside a
slice (str-arm regression pin). 33/33 ok.
This commit is contained in:
@@ -2690,8 +2690,10 @@ cg_structlit_fill(Cg *c, Local **locals_p, Type *lu, Node *lit,
|
||||
/* str IS []u8: 3-word field (ptr,len,cap). cgexpr leaves
|
||||
* AX/BX/CX; for non-BP modes the dst base goes in DX to dodge
|
||||
* BX=len / CX=cap (the generic store below reloads BX, which
|
||||
* would clobber len) (#1/Phase 3). */
|
||||
if (fu && fu->kind == TY_STR) {
|
||||
* would clobber len) (#1/Phase 3). A slice is the same 24B
|
||||
* {ptr,len,cap} shape, so it rides this arm; without it the
|
||||
* generic scalar tail stored only the ptr word (#24). */
|
||||
if (fu && (fu->kind == TY_STR || fu->kind == TY_SLICE)) {
|
||||
cgexpr(c, f->lhs, *locals_p);
|
||||
if (mode == DST_BP) {
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
|
||||
Reference in New Issue
Block a user