commit ece185f06705864ae55cbe15fea88c6bc4315f62
parent 8201c6161e215e4716f3305e3dcb1e6b3de15ea9
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Fri, 11 Sep 2015 14:10:05 -0400
implement aggregate passing in regs
Diffstat:
4 files changed, 45 insertions(+), 44 deletions(-)
diff --git a/lisc/emit.c b/lisc/emit.c
@@ -249,10 +249,7 @@ eins(Ins i, Fn *fn, FILE *f)
1, TMP(RSP), i.to);
break;
case OXPush:
- emitf(fn, f, "\tpush%w %R\n", 1, i.arg[0]);
- break;
- case OXMovs:
- emitf(fn, f, "\trep movsb\n");
+ emitf(fn, f, "\tpush%w %R\n", i.wide, i.arg[0]);
break;
case OXDiv:
emitf(fn, f, "\tidiv%w %R\n", i.wide, i.arg[0]);
diff --git a/lisc/isel.c b/lisc/isel.c
@@ -155,7 +155,6 @@ sel(Ins i, Fn *fn)
n = 1;
goto Emit;
case OCall:
- case OXMovs:
case OSAlloc:
case OCopy:
case OSext:
@@ -446,23 +445,22 @@ classify(AInfo *a, Typ *t)
static void
selcall(Fn *fn, Ins *i0, Ins *i1)
{
- static int ireg[8] = { RDI, RSI, RDX, RCX, R8, R9, R10, R11 };
+ static int ireg[6] = {RDI, RSI, RDX, RCX, R8, R9};
Ins *i;
AInfo *ai, *a;
int nint, nsse, ni, ns, n;
uint stk, sz;
- Ref r;
+ Ref r, r1;
ai = alloc((i1-i0) * sizeof ai[0]);
nint = 6;
nsse = 8;
- stk = 0;
for (i=i0, a=ai; i<i1; i++, a++) {
if (i->op == OArgc) {
classify(a, &typ[i->arg[0].val]);
if (a->inmem)
- goto Mem;
+ continue;
ni = ns = 0;
for (n=0; n<2; n++)
switch (a->rty[n]) {
@@ -476,73 +474,80 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
if (nint > ni && nsse > ns) {
nint -= ni;
nsse -= ns;
- } else {
+ } else
a->inmem = 1;
- Mem:
- stk += a->size;
- if (a->align == 4 && stk % 16)
- stk += 8;
- }
} else {
if (nint > 0) {
nint--;
a->inmem = 0;
- } else {
- stk += 8;
+ } else
a->inmem = 1;
- }
a->align = 3;
a->size = 8;
a->rty[0] = RInt;
}
}
- if (!req(i1->arg[1], R))
+ for (stk=0, a=&ai[i1-i0]; a>ai;)
+ if ((--a)->inmem) {
+ assert(a->align <= 4);
+ stk += a->size;
+ if (a->align == 4)
+ stk += stk & 15;
+ }
+ stk += stk & 15;
+
+ if (rtype(i1->arg[1]) == RTyp)
diag("struct-returning function not implemented");
- if (stk)
- emit(OSAlloc, 0, R, newcon(-(int64_t)stk, fn), R);
- for (n=0; n<2; n++) {
- r = TMP(ireg[n]);
- emit(OCopy, 0, R, r, R);
- }
+
emit(OCopy, i1->wide, i1->to, TMP(RAX), R);
- emit(OCall, 0, R, i->arg[0], R);
- emit(OCopy, 0, TMP(RAX), CON_Z, R);
- if (stk % 16)
- emit(OXPush, 1, R, TMP(RAX), R);
+#if 1
+ for (n=0; n<6; n++) {
+ emit(OCopy, 0, R, TMP(ireg[n]), R);
+ }
+#endif
+ r = newcon(-(int64_t)stk, fn);
+ emit(OSAlloc, 0, R, r, R);
+ emit(OCall, 0, TMP(RAX), i->arg[0], R);
for (i=i0, a=ai, ni=0; i<i1; i++, a++) {
if (a->inmem)
continue;
if (i->op == OArgc) {
- diag("aggregate in registers not implemented");
+ if (a->size > 8) {
+ r = TMP(ireg[ni+1]);
+ r1 = newtmp(fn);
+ emit(OLoad, 1, r, r1, R);
+ r = newcon(8, fn);
+ emit(OAdd, 1, r1, i->arg[1], r);
+ r = TMP(ireg[ni]);
+ ni += 2;
+ } else
+ r = TMP(ireg[ni++]);
+ emit(OLoad, 1, r, i->arg[1], R);
} else {
r = TMP(ireg[ni++]);
emit(OCopy, i->wide, r, i->arg[0], R);
}
}
- stk = 0;
for (i=i0, a=ai; i<i1; i++, a++) {
if (!a->inmem)
continue;
sz = a->size;
if (a->align == 4 && stk % 16)
sz += 8;
- stk += sz;
+ stk -= sz;
if (i->op == OArgc) {
- emit(OCopy, 0, R, TMP(RCX), R);
- emit(OCopy, 0, R, TMP(RDI), R);
- emit(OCopy, 0, R, TMP(RSI), R);
- emit(OXMovs, 0, R, R, R);
- emit(OCopy, 1, TMP(RCX), newcon(a->size, fn), R);
- emit(OCopy, 1, TMP(RDI), TMP(RSP), R);
- emit(OCopy, 1, TMP(RSI), i->arg[1], R);
- emit(OSAlloc, 0, R, newcon(sz, fn), R);
+ assert(!"argc todo 2");
} else {
emit(OXPush, 1, R, i->arg[0], R);
}
}
+ if (stk) {
+ assert(stk == 8);
+ emit(OXPush, 1, R, CON_Z, R);
+ }
free(ai);
}
diff --git a/lisc/lisc.h b/lisc/lisc.h
@@ -147,7 +147,6 @@ enum Op {
OSign,
OSAlloc,
OXPush,
- OXMovs,
OXDiv,
OXCmp,
OXSet,
diff --git a/lisc/parse.c b/lisc/parse.c
@@ -33,7 +33,6 @@ OpDesc opdesc[NOp] = {
[ONop] = { "nop", 0, 0 },
[OSwap] = { "swap", 2, 2 },
[OSign] = { "sign", 1, 0 },
- [OXMovs] = { "xmovs", 0, 0 },
[OXPush] = { "xpush", 1, 1 },
[OSAlloc] = { "salloc", 1, 0 },
[OXDiv] = { "xdiv", 1, 1 },
@@ -684,7 +683,7 @@ parsetyp()
}
if (a > al)
al = a;
- if ((a = sz & s-1)) {
+ if ((a = sz & (s-1))) {
a = s - a;
if (++n < NSeg) {
/* padding segment */
@@ -830,7 +829,8 @@ printfn(Fn *fn, FILE *f)
assert(opdesc[i->op].name);
fprintf(f, "%s", opdesc[i->op].name);
if (req(i->to, R))
- if (i->op == OXCmp || i->op == OXTest)
+ if (i->op == OXCmp || i->op == OXTest
+ || i->op == OXPush)
fprintf(f, i->wide ? "l" : "w");
if (!req(i->arg[0], R)) {
fprintf(f, " ");