cgen: str arr[i].field read -> 3-word -- Phase 2 C4.6 arrfield (both stages)
A str-typed field read of an INDEXED element (arr[i].f) loaded 2 words (ptr,len), dropping cap -- the last 2-word str VALUE-read in the cluster. At the leaf the element base is always in AX; insert cap->CX at foff+16 (final order len->BX+8, cap->CX+16, ptr->AX+0 LAST). ONE shared leaf covers value-array / slice / pointer-element sub-cases (base-formation differs upstream, unaffected). Author-to-ABI, matched to the proven cgslicehdr(D_AX) / caseB slice-arm shape. Kind-gated (TY_STR / isstrtype, never size==24). cstage==wwstage byte-identical at the leaf. test/wcc/936: table-driven runtime .cap-survives over [N]S-local / []S-local / [N]*S-pointer-elem reads; a 2-word read cannot coincidentally pass (the index scale-multiply clobbers CX, plus an interposed call). fail-before/pass-after verified independently on both drivers. main.combined.ww regenerated via the canonical make path (md5-stable). Completes the str 3-word VALUE-read cluster (F2 element; C4.6/caseB/S3 fields; arrfield indexed-field). Store-side cap-drop and a struct-slice-creation divergence are separately filed.
This commit is contained in:
@@ -15606,10 +15606,19 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
};
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
// str IS the 3-word {ptr,len,cap}
|
||||
// slice header (#1). AX holds the
|
||||
// element base, so load .ptr (which
|
||||
// targets AX) LAST. Matches the
|
||||
// caseB *struct slice arm and
|
||||
// cgslicehdr(D_AX).
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 8): i64, "AX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 16): i64, "AX");
|
||||
emitline(", CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(fi.foff: i64, "AX");
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
|
||||
@@ -1778,10 +1778,19 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
};
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
// str IS the 3-word {ptr,len,cap}
|
||||
// slice header (#1). AX holds the
|
||||
// element base, so load .ptr (which
|
||||
// targets AX) LAST. Matches the
|
||||
// caseB *struct slice arm and
|
||||
// cgslicehdr(D_AX).
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 8): i64, "AX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 16): i64, "AX");
|
||||
emitline(", CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(fi.foff: i64, "AX");
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
|
||||
@@ -15606,10 +15606,19 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tBX, AX\n");
|
||||
};
|
||||
if (isstrtype(c, fi.tnode)) {
|
||||
// str IS the 3-word {ptr,len,cap}
|
||||
// slice header (#1). AX holds the
|
||||
// element base, so load .ptr (which
|
||||
// targets AX) LAST. Matches the
|
||||
// caseB *struct slice arm and
|
||||
// cgslicehdr(D_AX).
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 8): i64, "AX");
|
||||
emitline(", BX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg((fi.foff + 16): i64, "AX");
|
||||
emitline(", CX\n");
|
||||
emitline("\tMOVQ\t");
|
||||
emitdispreg(fi.foff: i64, "AX");
|
||||
emitline(", AX\n");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user