cgen: str tuple-positional element read -> 3-word -- Phase 2 C4.6 S3 (both stages)
Reading a str-typed tuple element by position (t.N) loaded 2 words (ptr,len), dropping cap -- the C4.6 coda with NO adjacent slice-element arm to mirror. Author the 3-word triple directly to the canonical {ptr,len,cap} ABI (AX,BX,CX off the BP frame slot; add cap->CX at +16). Kind-gated (TY_STR / isstrtype, never size==24). cstage==wwstage byte-identical -- cross-stage identity is the correctness oracle here, since there is no local slice sibling.
test/wcc/935: table-driven runtime .cap-survives over let s = t.1; poison rides the return ABI (R8) into the slot's cap word; a CX-clobbering call ensures a 2-word read cannot coincidentally pass. fail-before/pass-after verified INDEPENDENTLY on both stages.
main.combined.ww regenerated via the canonical make path (md5-stable).
This commit is contained in:
@@ -15336,9 +15336,11 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// Walk the tuple element type list summing slotsize
|
||||
// (matches the (scalar, str) init layout: scalar in an
|
||||
// 8B slot, str in 24B — str IS []u8, #1/Phase 3). For a
|
||||
// str element, load (ptr, len) into (AX, BX); the cap
|
||||
// stays in the slot (the 2-word str-field read, like
|
||||
// every other chained/dot str leaf read — task #14).
|
||||
// str element, load (ptr, len, cap) into (AX, BX, CX),
|
||||
// the canonical slice-header ABI. No slice-element
|
||||
// sibling here, so the triple is hand-authored; base is
|
||||
// BP (frame, not a target reg) so ptr/len/cap order has
|
||||
// no clobber risk.
|
||||
if (lkind == nkind.N_TTUPLE) {
|
||||
let idx: i32 = fldnumidx(fld);
|
||||
if (idx >= 0) {
|
||||
@@ -15362,6 +15364,9 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 16): i64);
|
||||
emitline("(BP), CX\n");
|
||||
return;
|
||||
};
|
||||
let sz: i32 = slotsize(c, tpt);
|
||||
|
||||
@@ -1508,9 +1508,11 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// Walk the tuple element type list summing slotsize
|
||||
// (matches the (scalar, str) init layout: scalar in an
|
||||
// 8B slot, str in 24B — str IS []u8, #1/Phase 3). For a
|
||||
// str element, load (ptr, len) into (AX, BX); the cap
|
||||
// stays in the slot (the 2-word str-field read, like
|
||||
// every other chained/dot str leaf read — task #14).
|
||||
// str element, load (ptr, len, cap) into (AX, BX, CX),
|
||||
// the canonical slice-header ABI. No slice-element
|
||||
// sibling here, so the triple is hand-authored; base is
|
||||
// BP (frame, not a target reg) so ptr/len/cap order has
|
||||
// no clobber risk.
|
||||
if (lkind == nkind.N_TTUPLE) {
|
||||
let idx: i32 = fldnumidx(fld);
|
||||
if (idx >= 0) {
|
||||
@@ -1534,6 +1536,9 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 16): i64);
|
||||
emitline("(BP), CX\n");
|
||||
return;
|
||||
};
|
||||
let sz: i32 = slotsize(c, tpt);
|
||||
|
||||
@@ -15336,9 +15336,11 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// Walk the tuple element type list summing slotsize
|
||||
// (matches the (scalar, str) init layout: scalar in an
|
||||
// 8B slot, str in 24B — str IS []u8, #1/Phase 3). For a
|
||||
// str element, load (ptr, len) into (AX, BX); the cap
|
||||
// stays in the slot (the 2-word str-field read, like
|
||||
// every other chained/dot str leaf read — task #14).
|
||||
// str element, load (ptr, len, cap) into (AX, BX, CX),
|
||||
// the canonical slice-header ABI. No slice-element
|
||||
// sibling here, so the triple is hand-authored; base is
|
||||
// BP (frame, not a target reg) so ptr/len/cap order has
|
||||
// no clobber risk.
|
||||
if (lkind == nkind.N_TTUPLE) {
|
||||
let idx: i32 = fldnumidx(fld);
|
||||
if (idx >= 0) {
|
||||
@@ -15362,6 +15364,9 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 8): i64);
|
||||
emitline("(BP), BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((lc.off + foff + 16): i64);
|
||||
emitline("(BP), CX\n");
|
||||
return;
|
||||
};
|
||||
let sz: i32 = slotsize(c, tpt);
|
||||
|
||||
Reference in New Issue
Block a user