w6c: append() accepts struct CALL rvalue elements (#34)
Evaluate the call pre-grow into a per-site scratch, receiving by the N_LET matrix (sret / float / odd-tail / GP), then grow, slot, sized ladder. Both stages, byte-identical. The two reject pins graduate to 16B GP accept rows; three new fixtures cover 24B GP, 3B/4B tails, 16B float, and 40B sret.
This commit is contained in:
@@ -6599,7 +6599,8 @@ fn cgappend(c: *cgen, n: *syntax.node) void = {
|
||||
let asoff: i32 = 0;
|
||||
let aroot: *syntax.node = nil;
|
||||
let aidx: *syntax.node = nil;
|
||||
if (elstruct && vn.kind != syntax.nkind.N_STRUCTLIT && vn.kind != syntax.nkind.N_IDENT) {
|
||||
if (elstruct && vn.kind != syntax.nkind.N_STRUCTLIT && vn.kind != syntax.nkind.N_IDENT
|
||||
&& vn.kind != syntax.nkind.N_CALL) {
|
||||
let ch: *syntax.node = vn;
|
||||
let aok: bool = true;
|
||||
for (aok && ch.kind == syntax.nkind.N_DOT) {
|
||||
@@ -6722,6 +6723,101 @@ fn cgappend(c: *cgen, n: *syntax.node) void = {
|
||||
vn = vn.next;
|
||||
continue;
|
||||
};
|
||||
if (vn.kind == syntax.nkind.N_CALL) {
|
||||
// #34 close: a struct CALL rvalue element.
|
||||
// Evaluate the call FIRST into a fresh per-site
|
||||
// scratch (the STRUCTLIT arm's pre-grow
|
||||
// discipline: arg exprs must see the pre-append
|
||||
// len, and the value must survive rt_ensure),
|
||||
// receiving by the N_LET matrix (#23 sret /
|
||||
// #171a float / #107 odd-tail / #169 GP), then
|
||||
// grow, slot, sized-ladder scratch->slot.
|
||||
let stscr: i32 = localalloc(c, "@appendstructscr", esz, nil);
|
||||
let scs: i32 = callsretsize(c, vn);
|
||||
if (scs > 0) {
|
||||
c.sretdestoff = stscr;
|
||||
cgexpr(c, vn);
|
||||
c.sretdestoff = 0;
|
||||
} else {
|
||||
let sfc: i32 = structfloatclassti(esubti);
|
||||
if (sfc != 0) {
|
||||
cgexpr(c, vn);
|
||||
let nb: i32 = sfc & 15;
|
||||
let gpcur: i32 = 0;
|
||||
let ssecur: i32 = 0;
|
||||
let e: i32 = 0;
|
||||
for (e < nb) {
|
||||
let issse: bool = (sfc & (16 << e)) != 0;
|
||||
if (issse) {
|
||||
emitline("\tMOVSD\t");
|
||||
emitline(tupsse(ssecur));
|
||||
emitline(", ");
|
||||
emitoff((stscr + e * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
ssecur += 1;
|
||||
} else {
|
||||
emitline("\tMOVQ\t");
|
||||
emitline(tupreg(gpcur));
|
||||
emitline(", ");
|
||||
emitoff((stscr + e * 8): i64);
|
||||
emitline("(BP)\n");
|
||||
gpcur += 1;
|
||||
};
|
||||
e += 1;
|
||||
};
|
||||
} else { if (esz == 3 || esz == 5
|
||||
|| esz == 6 || esz == 7) {
|
||||
cgexpr(c, vn);
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(stscr: i64);
|
||||
emitline("(BP)\n");
|
||||
} else {
|
||||
cgexpr(c, vn);
|
||||
cgaggregstore(c, "BP", stscr, esz, true);
|
||||
}; };
|
||||
};
|
||||
cgappendgrow(c, sndirect, sn_off, snscr, esz);
|
||||
cgappendslot(c, sndirect, sn_off, snscr, esz, "BX");
|
||||
let ck: i32 = 0;
|
||||
for (ck + 8 <= esz) {
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff((stscr + ck): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitdispreg(ck: i64, "BX");
|
||||
emitline("\n");
|
||||
ck += 8;
|
||||
};
|
||||
if (ck + 4 <= esz) {
|
||||
emitline("\tMOVL\t");
|
||||
emitoff((stscr + ck): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVL\tAX, ");
|
||||
emitdispreg(ck: i64, "BX");
|
||||
emitline("\n");
|
||||
ck += 4;
|
||||
};
|
||||
if (ck + 2 <= esz) {
|
||||
emitline("\tMOVW\t");
|
||||
emitoff((stscr + ck): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVW\tAX, ");
|
||||
emitdispreg(ck: i64, "BX");
|
||||
emitline("\n");
|
||||
ck += 2;
|
||||
};
|
||||
if (ck + 1 <= esz) {
|
||||
emitline("\tMOVB\t");
|
||||
emitoff((stscr + ck): i64);
|
||||
emitline("(BP), AX\n");
|
||||
emitline("\tMOVB\tAX, ");
|
||||
emitdispreg(ck: i64, "BX");
|
||||
emitline("\n");
|
||||
ck += 1;
|
||||
};
|
||||
vn = vn.next;
|
||||
continue;
|
||||
};
|
||||
if (vn.kind == syntax.nkind.N_STRUCTLIT) {
|
||||
// #59 (#50's eval-order kin): resolve the struct
|
||||
// info, then fill the literal into a fresh
|
||||
|
||||
Reference in New Issue
Block a user