cgen: extract the narrow-tail aggregate-register materialise into a shared helper (#14)
This commit is contained in:
@@ -1721,6 +1721,88 @@ fn aggcopy(c: *cgen, sz: i32) void = {
|
||||
};
|
||||
};
|
||||
|
||||
// cgaggregstore — ww twin of cstage cgen.c cg_agg_reg_store. The ONE
|
||||
// register-cursor aggregate materialise: an in-cap (<=24B, GP-class)
|
||||
// struct/array/tuple already held in the {AX,DX,CX} return cursor is
|
||||
// stored into basereg+disp. full=sz/8 exact-8B MOVQ words land straight
|
||||
// in; the sz%8 tail is one sized MOVB/MOVW/MOVL for {1,2,4} (BOTH
|
||||
// branches). Extracted from the cstage site-E #10 template so every
|
||||
// narrow-tail materialise funnels through one place — close-by-
|
||||
// construction (task #14).
|
||||
//
|
||||
// dest_padded forks ONLY the {3,5,6,7} tail (no GP sub-register exists
|
||||
// for those widths and w6a has no shift):
|
||||
// dest_padded == "the dest is a ceil-8/round8 slot (a scratch, or a
|
||||
// #75 let/local aggregate slot) so an 8B tail over-store stays
|
||||
// in-bounds." Post-#9: packed struct fields + array elements => false;
|
||||
// let/local/scratch slots => true. It CANNOT be derived — paddedness
|
||||
// is routing knowledge the caller owns.
|
||||
// true -> a single full MOVQ of the cursor tail eightbyte (= the
|
||||
// #10 template; the over-store lands in the slot's pad).
|
||||
// false -> MOVQ the cursor tail eightbyte into the helper's own
|
||||
// ceil-8 @tagscr pad, then a sized aggcopy of the tail bytes
|
||||
// into the dest so a packed field / array element is never
|
||||
// overrun.
|
||||
// PRECONDITION (caller-owned, stays per-site): the value is already in
|
||||
// AX/DX/CX, the dest base is resolved into basereg+disp, and the
|
||||
// float-class (#165) / over-cap-sret (#234) loud-stops have already
|
||||
// fired. Clobbers SI/BX/AX only on the dest_padded==false detour (the
|
||||
// value words are in memory by then).
|
||||
fn cgaggregstore(c: *cgen, basereg: str, disp: i32, sz: i32, dest_padded: bool) void = {
|
||||
let full: i32 = sz / 8;
|
||||
let tail: i32 = sz - full * 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitdispreg((disp + i * 8): i64, basereg);
|
||||
emitline("\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tail == 0) { return; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
if (tail == 1 || tail == 2 || tail == 4) {
|
||||
let top: str = "MOVB";
|
||||
if (tail == 4) { top = "MOVL"; };
|
||||
if (tail == 2) { top = "MOVW"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((disp + full * 8): i64, basereg);
|
||||
emitline("\n");
|
||||
return;
|
||||
};
|
||||
if (dest_padded) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((disp + full * 8): i64, basereg);
|
||||
emitline("\n");
|
||||
return;
|
||||
};
|
||||
let pad: i32 = tagscradd(c, 8);
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg(pad: i64, "BP");
|
||||
emitline("\n");
|
||||
emitline("\tLEAQ\t");
|
||||
emitdispreg(pad: i64, "BP");
|
||||
emitline(", SI\n");
|
||||
emitline("\tLEAQ\t");
|
||||
emitdispreg((disp + full * 8): i64, basereg);
|
||||
emitline(", BX\n");
|
||||
aggcopy(c, tail);
|
||||
};
|
||||
|
||||
// copysrcnatsize — natural byte width of a whole-struct copy's SOURCE
|
||||
// operand, read from the source node's stamped tinfo (tichase peels
|
||||
// NAMED). #71: the four whole-struct field-copy sites must move this many
|
||||
@@ -8399,34 +8481,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
emitline("\tPUSHQ\tBX\n");
|
||||
cgexpr(c, n.rhs);
|
||||
emitline("\tPOPQ\tBX\n");
|
||||
let full: i32 = ssz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitdispreg((i * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((full * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
cgaggregstore(c, "BX", 0, ssz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -9217,36 +9272,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
let scrc2: i32 = tagscradd(c, esz);
|
||||
cgexpr(c, n.rhs); // call -> AX/DX/CX
|
||||
// AX/DX/CX -> scratch (mirror cstage cgen.c:3434).
|
||||
let full: i32 = esz / 8;
|
||||
let tail: i32 = esz % 8;
|
||||
let wi: i32 = 0;
|
||||
for (wi < full) {
|
||||
let rn: str = "AX";
|
||||
if (wi == 1) { rn = "DX"; }
|
||||
else { if (wi == 2) { rn = "CX"; }; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(rn);
|
||||
emitline(", ");
|
||||
emitoff((scrc2 + wi * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
wi += 1;
|
||||
};
|
||||
if (tail > 0) {
|
||||
let top: str = "MOVQ";
|
||||
if (tail == 1) { top = "MOVB"; }
|
||||
else { if (tail == 2) { top = "MOVW"; }
|
||||
else { if (tail == 4) { top = "MOVL"; }; }; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; }
|
||||
else { if (full == 2) { treg = "CX"; }; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitoff((scrc2 + full * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
cgaggregstore(c, "BP", scrc2, esz, true);
|
||||
// dest &a[i] -> BX (#121 / #270-1b base resolve)
|
||||
cgexpr(c, idx);
|
||||
if (esz > 1) {
|
||||
@@ -10601,34 +10627,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(lc.off: i64);
|
||||
emitline("(BP), BX\n");
|
||||
let full: i32 = ssz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitdispreg((fi.foff + i * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((fi.foff + full * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
cgaggregstore(c, "BX", fi.foff, ssz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -10847,34 +10846,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
if (tlm == 0 || tlm == 1
|
||||
|| tlm == 2 || tlm == 4) {
|
||||
cgexpr(c, n.rhs);
|
||||
let full: i32 = ssz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitoff((lc.off + fi.foff + i * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitoff((lc.off + fi.foff + full * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
cgaggregstore(c, "BP", lc.off + fi.foff, ssz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -11141,34 +11113,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, bn);
|
||||
emitline("(SB), BX\n");
|
||||
let full: i32 = ssz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitdispreg((fi.foff + i * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((fi.foff + full * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
};
|
||||
cgaggregstore(c, "BX", fi.foff, ssz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -11848,52 +11793,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
emitline("(SB), BX\n");
|
||||
};
|
||||
};
|
||||
let full: i32 = lsz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
if (viacx) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitdispreg((totaloff + i * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitoff((rootoff + totaloff + i * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
if (viacx) {
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitdispreg((totaloff + full * 8): i64, "BX");
|
||||
emitline("\n");
|
||||
} else {
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitoff((rootoff + totaloff + full * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
};
|
||||
if (viacx) { cgaggregstore(c, "BX", totaloff, lsz, false); } else { cgaggregstore(c, "BP", rootoff + totaloff, lsz, false); };
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -12638,34 +12538,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
if (tlm == 0 || tlm == 1
|
||||
|| tlm == 2 || tlm == 4) {
|
||||
cgexpr(c, n.rhs);
|
||||
let full: i32 = lcsz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitoff((off + i * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitoff((off + full * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
cgaggregstore(c, "BP", off, lcsz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
@@ -12702,34 +12575,7 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
if (tlm == 0 || tlm == 1
|
||||
|| tlm == 2 || tlm == 4) {
|
||||
cgexpr(c, n.rhs);
|
||||
let full: i32 = lcsz / 8;
|
||||
let i: i32 = 0;
|
||||
for (i < full) {
|
||||
let reg: str = "AX";
|
||||
if (i == 1) { reg = "DX"; };
|
||||
if (i == 2) { reg = "CX"; };
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(reg);
|
||||
emitline(", ");
|
||||
emitoff((off + i * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
i += 1;
|
||||
};
|
||||
if (tlm > 0) {
|
||||
let top: str = "MOVB";
|
||||
if (tlm == 4) { top = "MOVL"; };
|
||||
if (tlm == 2) { top = "MOVW"; };
|
||||
let treg: str = "AX";
|
||||
if (full == 1) { treg = "DX"; };
|
||||
if (full == 2) { treg = "CX"; };
|
||||
emitline("\t");
|
||||
emitline(top);
|
||||
emitline("\t");
|
||||
emitline(treg);
|
||||
emitline(", ");
|
||||
emitoff((off + full * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
};
|
||||
cgaggregstore(c, "BP", off, lcsz, false);
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user