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:
@@ -19519,12 +19519,15 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
||||
fi = nil;
|
||||
} else if (callwhole) {
|
||||
fi = nil;
|
||||
} else if (isstrtype(c, fi.tnode)) {
|
||||
} else if (isstrtype(c, fi.tnode) || isslicetype(c, fi.tnode)) {
|
||||
// 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 reloads BX, which
|
||||
// would clobber len) (#1/Phase 3).
|
||||
// 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).
|
||||
cgexpr(c, fieldnode.lhs);
|
||||
if (mode == 0) {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
|
||||
Reference in New Issue
Block a user