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:
@@ -9467,7 +9467,8 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
int abase_slice = 0, aroot_off = 0;
|
||||
Node *aroot = NULL, *aidx = NULL;
|
||||
if (el_struct && vn->kind != N_STRUCTLIT
|
||||
&& vn->kind != N_IDENT) {
|
||||
&& vn->kind != N_IDENT
|
||||
&& vn->kind != N_CALL) {
|
||||
Node *ch = vn;
|
||||
int aok = 1;
|
||||
while (aok && ch->kind == N_DOT) {
|
||||
@@ -9567,6 +9568,80 @@ cgexpr(Cg *c, Node *n, Local *locals)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (vn->kind == 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. */
|
||||
int st_scr = local_alloc(c,
|
||||
&locals, "@appendstructscr",
|
||||
esz, cg_frame);
|
||||
int sclass[2], snb;
|
||||
if (cg_sret_retsize(esub) > 0) {
|
||||
cg_sret_dest_off = st_scr;
|
||||
cgexpr(c, vn, locals);
|
||||
cg_sret_dest_off = 0;
|
||||
} else if ((snb = struct_float_class(esubu, sclass)) > 0) {
|
||||
cgexpr(c, vn, locals);
|
||||
int gpcur = 0, ssecur = 0;
|
||||
for (int e = 0; e < snb; e++) {
|
||||
if (sclass[e]) {
|
||||
ins2(c, A_MOVSD,
|
||||
areg(tuple_sse_seq[ssecur]),
|
||||
amem(D_BP, st_scr + e * 8));
|
||||
ssecur++;
|
||||
} else {
|
||||
ins2(c, A_MOVQ,
|
||||
areg(tuple_rseq[gpcur]),
|
||||
amem(D_BP, st_scr + e * 8));
|
||||
gpcur++;
|
||||
}
|
||||
}
|
||||
} else if (esz < 8 && (esz % 8 == 3
|
||||
|| esz % 8 == 5 || esz % 8 == 6
|
||||
|| esz % 8 == 7)) {
|
||||
cgexpr(c, vn, locals);
|
||||
ins2(c, A_MOVQ, areg(D_AX),
|
||||
amem(D_BP, st_scr));
|
||||
} else {
|
||||
cgexpr(c, vn, locals);
|
||||
cg_agg_reg_store(c, &locals,
|
||||
D_BP, st_scr, esz, 1);
|
||||
}
|
||||
cg_append_grow(c, sn_direct, sn_off,
|
||||
sn_scr, esz);
|
||||
cg_append_slot(c, sn_direct, sn_off,
|
||||
sn_scr, esz, D_BX);
|
||||
int ck = 0;
|
||||
for (; ck + 8 <= esz; ck += 8) {
|
||||
ins2(c, A_MOVQ, amem(D_BP, st_scr + ck), areg(D_AX));
|
||||
ins2(c, A_MOVQ, areg(D_AX), amem(D_BX, ck));
|
||||
}
|
||||
if (ck + 4 <= esz) {
|
||||
ins2(c, A_MOVL, amem(D_BP, st_scr + ck), areg(D_AX));
|
||||
ins2(c, A_MOVL, areg(D_AX), amem(D_BX, ck));
|
||||
ck += 4;
|
||||
}
|
||||
if (ck + 2 <= esz) {
|
||||
ins2(c, A_MOVW, amem(D_BP, st_scr + ck), areg(D_AX));
|
||||
ins2(c, A_MOVW, areg(D_AX), amem(D_BX, ck));
|
||||
ck += 2;
|
||||
}
|
||||
if (ck + 1 <= esz) {
|
||||
ins2(c, A_MOVB, amem(D_BP, st_scr + ck), areg(D_AX));
|
||||
ins2(c, A_MOVB, areg(D_AX), amem(D_BX, ck));
|
||||
ck += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (vn->kind == N_STRUCTLIT) {
|
||||
/* #59 (#50's eval-order kin):
|
||||
* fill the literal into a fresh
|
||||
|
||||
Reference in New Issue
Block a user