wcc: chained-dot str leaf loads the cap word, both stages
A str field reached through a chained dot (o.i.s) emitted two loads (ptr, len) and stored a stale CX as the cap — both stages, at any non-zero chain depth. Emit the full header at the chained-dot leaf. Review item #29. Both stages move in one commit: one emission contract; splitting would leave the byte-id gates red between the halves.
This commit is contained in:
@@ -4351,40 +4351,17 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (typeisstr(leaftype)) {
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(rootoff: i64);
|
||||
emitline("(BP), CX\n");
|
||||
} else {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, rootname);
|
||||
emitline("(SB), CX\n");
|
||||
};
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(totaloff: i64, "CX");
|
||||
emitline(", AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((totaloff + 8): i64, "CX");
|
||||
emitline(", BX\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((rootoff + totaloff): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((rootoff + totaloff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
};
|
||||
return;
|
||||
};
|
||||
if (typeisslice(leaftype)) {
|
||||
// Slice leaf: load all three header words into
|
||||
// (AX=ptr, BX=len, CX=cap). For the viacx path
|
||||
// (global or `*T` root) CX is the base; load
|
||||
// .cap LAST so the base survives the earlier
|
||||
// reads. For BP-rooted locals the registers
|
||||
// don't alias so order is free.
|
||||
if (typeisstr(leaftype) || typeisslice(leaftype)) {
|
||||
// str/slice leaf: load all three header words into
|
||||
// (AX=ptr, BX=len, CX=cap). str IS []u8 — the same 24B
|
||||
// {ptr,len,cap} header. #29: the str leaf used to load
|
||||
// only ptr+len here (cap dropped → a junk strlit before
|
||||
// the chain left CX stale); merged into the slice arm so
|
||||
// both load the full triple, both stages (#263). For the
|
||||
// viacx path (global or `*T` root) CX is the base; load
|
||||
// .cap LAST so the base survives the earlier reads. For
|
||||
// BP-rooted locals the registers do not alias so order is
|
||||
// free.
|
||||
if (viacx) {
|
||||
if (ptrroot) {
|
||||
emitline("\tMOVQ\t");
|
||||
|
||||
Reference in New Issue
Block a user