From ece185f06705864ae55cbe15fea88c6bc4315f62 Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Fri, 11 Sep 2015 14:10:05 -0400 Subject: implement aggregate passing in regs --- lisc/isel.c | 77 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 36 deletions(-) (limited to 'lisc/isel.c') diff --git a/lisc/isel.c b/lisc/isel.c index 6efbd70..a018cd5 100644 --- 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; iop == 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; iinmem) 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; iinmem) 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); } -- cgit 1.4.1