diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-17 19:29:49 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-17 19:29:49 -0400 |
commit | c298820211351716c22198c7b4e6c7c0ea664c64 (patch) | |
tree | 7e966c725710e7af147076f2dea90e2829601151 | |
parent | bca7e0c32df2c29e013e15f8254c3ccb7496dc99 (diff) | |
download | roux-c298820211351716c22198c7b4e6c7c0ea664c64.tar.gz |
start work on fuction parameters
-rw-r--r-- | lisc/emit.c | 2 | ||||
-rw-r--r-- | lisc/isel.c | 198 | ||||
-rw-r--r-- | lisc/lisc.h | 4 |
3 files changed, 146 insertions, 58 deletions
diff --git a/lisc/emit.c b/lisc/emit.c index 935b2e6..535bf18 100644 --- a/lisc/emit.c +++ b/lisc/emit.c @@ -81,7 +81,7 @@ Next: break; case RSlot: Slot: - fprintf(f, "-%d(%%rbp)", 4 * ref.val); + fprintf(f, "%d(%%rbp)", -4 * ref.val); break; case RCon: fputc('$', f); diff --git a/lisc/isel.c b/lisc/isel.c index 1712333..1879e72 100644 --- a/lisc/isel.c +++ b/lisc/isel.c @@ -382,23 +382,23 @@ slota(int sz, int al /* log2 */, int *sa) return ret; } -typedef struct AInfo AInfo; +typedef struct AClass AClass; -enum { - RNone, - RInt, - RSse, -}; - -struct AInfo { +struct AClass { int inmem; int align; uint size; int rty[2]; }; +enum { + RNone, + RInt, + RSse, +}; + static void -classify(AInfo *a, Typ *t) +aclass(AClass *a, Typ *t) { int e, s, n, rty; uint sz, al; @@ -413,8 +413,7 @@ classify(AInfo *a, Typ *t) */ if (al < 8) al = 8; - if (sz & (al-1)) - sz = (sz + al-1) & -al; + sz = (sz + al-1) & -al; a->size = sz; a->align = t->align; @@ -442,6 +441,50 @@ classify(AInfo *a, Typ *t) } } +static int +classify(Ins *i0, Ins *i1, AClass *ac, int op) +{ + int nint, ni, nsse, ns, n; + AClass *a; + Ins *i; + + nint = 6; + nsse = 8; + for (i=i0, a=ac; i<i1; i++, a++) { + if (i->op == op) { + if (nint > 0) { + nint--; + a->inmem = 0; + } else + a->inmem = 2; + a->align = 3; + a->size = 8; + a->rty[0] = RInt; + } else { + aclass(a, &typ[i->arg[0].val]); + if (a->inmem) + continue; + ni = ns = 0; + for (n=0; n<2; n++) + switch (a->rty[n]) { + case RInt: + ni++; + break; + case RSse: + ns++; + break; + } + if (nint > ni && nsse > ns) { + nint -= ni; + nsse -= ns; + } else + a->inmem = 1; + } + } + + return (6-nint) << 4; +} + int rsave[NRSave] = {RDI, RSI, RDX, RCX, R8, R9, R10, R11, RAX}; uint64_t calldef(Ins i, int *p) @@ -488,48 +531,15 @@ static void selcall(Fn *fn, Ins *i0, Ins *i1) { Ins *i; - AInfo *ai, *a; - int nint, nsse, ni, ns, n; + AClass *ac, *a; + int ci, ni; uint stk, sz; Ref r, r1; - ai = alloc((i1-i0) * sizeof ai[0]); - - nint = 6; - nsse = 8; - for (i=i0, a=ai; i<i1; i++, a++) { - if (i->op == OArgc) { - classify(a, &typ[i->arg[0].val]); - if (a->inmem) - continue; - ni = ns = 0; - for (n=0; n<2; n++) - switch (a->rty[n]) { - case RInt: - ni++; - break; - case RSse: - ns++; - break; - } - if (nint > ni && nsse > ns) { - nint -= ni; - nsse -= ns; - } else - a->inmem = 1; - } else { - if (nint > 0) { - nint--; - a->inmem = 0; - } else - a->inmem = 1; - a->align = 3; - a->size = 8; - a->rty[0] = RInt; - } - } + ac = alloc((i1-i0) * sizeof ac[0]); + ci = classify(i0, i1, ac, OArg); - for (stk=0, a=&ai[i1-i0]; a>ai;) + for (stk=0, a=&ac[i1-i0]; a>ac;) if ((--a)->inmem) { assert(a->align <= 4); stk += a->size; @@ -540,15 +550,14 @@ selcall(Fn *fn, Ins *i0, Ins *i1) if (!req(i1->arg[1], R)) diag("struct-returning function not implemented"); - if (stk) { r = newcon(-(int64_t)stk, fn); emit(OSAlloc, 0, R, r, R); } emit(OCopy, i1->wide, i1->to, TMP(RAX), R); - emit(OCall, 0, R, i->arg[0], CALL(1 + ((6-nint) << 4))); + emit(OCall, 0, R, i1->arg[0], CALL(1 + ci)); - for (i=i0, a=ai, ni=0; i<i1; i++, a++) { + for (i=i0, a=ac, ni=0; i<i1; i++, a++) { if (a->inmem) continue; if (i->op == OArgc) { @@ -570,8 +579,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1) emit(OCopy, i->wide, r, i->arg[0], R); } } - - for (i=i0, a=ai; i<i1; i++, a++) { + for (i=i0, a=ac; i<i1; i++, a++) { if (!a->inmem) continue; sz = a->size; @@ -579,7 +587,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1) sz += (stk-sz) & 15; stk -= sz; if (i->op == OArgc) { - assert(!"argc todo 2"); + assert(!"argc todo 1"); } else { emit(OXPush, 1, R, i->arg[0], R); } @@ -589,7 +597,71 @@ selcall(Fn *fn, Ins *i0, Ins *i1) emit(OXPush, 1, R, CON_Z, R); } - free(ai); + free(ac); +} + +static void +selpar(Fn *fn, Ins *i0, Ins *i1) +{ + AClass *ac, *a; + Ins *i; + int ni, stk, al; + Ref r, r1, r2; + + ac = alloc((i1-i0) * sizeof ac[0]); + classify(i0, i1, ac, OPar); + + curi = insb; + for (i=i0, a=ac, ni=0; i<i1; i++, a++) { + if (a->inmem) + continue; + r = TMP(rsave[ni++]); + if (i->op == OParc) { + if (a->rty[0] == RSse || a->rty[1] == RSse) + diag("isel: unsupported float struct"); + r1 = newtmp(fn); + *curi++ = (Ins){OCopy, 1, r1, {r}}; + a->rty[0] = r1.val; + if (a->size > 8) { + r = TMP(rsave[ni++]); + r1 = newtmp(fn); + *curi++ = (Ins){OCopy, 1, r1, {r}}; + a->rty[1] = r1.val; + } + } else + *curi++ = (Ins){OCopy, i->wide, i->to, {r}}; + } + for (i=i0, a=ac; i<i1; i++, a++) { + if (i->op != OParc || a->inmem) + continue; + for (al=0; a->align >> (al+2); al++) /* careful here, this is because base alloc is aligned at 4 */ + ; + r1 = newtmp(fn); + r = TMP(a->rty[0]); + *curi++ = (Ins){OAlloc+al, 1, r1, {R}}; + *curi++ = (Ins){OStorel, 0, R, {r, r1}}; + if (a->size > 8) { + r1 = newtmp(fn); + r2 = newcon(8, fn); + *curi++ = (Ins){OAdd, 1, r1, {r, r2}}; + r = TMP(a->rty[1]); + *curi++ = (Ins){OStorel, 0, R, {r, r1}}; + } + } + for (a=&ac[i1-i0], stk=0; a>ac;) { + i = &i0[--a - ac]; + switch (a->inmem) { + case 1: + assert(!"argc todo 2"); + break; + case 2: + stk += 2; + fn->tmp[i->to.val].spill = -stk; + break; + } + } + + free(ac); } /* instruction selection @@ -605,6 +677,20 @@ isel(Fn *fn) int n, al, s; int64_t sz; + /* lower arguments */ + for (b=fn->start, i=b->ins; i-b->ins < b->nins; i++) + if (i->op != OPar && i->op != OParc) + break; + selpar(fn, b->ins, i); + i0 = i; + n = b->nins - (i0-b->ins); + b->nins = n + (curi-insb); + i = alloc(b->nins * sizeof i[0]); + memcpy(i, insb, (curi-insb) * sizeof i[0]); + memcpy(&i[n], i0, n * sizeof i[0]); + free(b->ins); + b->ins = i; + /* lower function calls */ for (b=fn->start; b; b=b->link) { curi = &insb[NIns]; diff --git a/lisc/lisc.h b/lisc/lisc.h index e353a09..930651d 100644 --- a/lisc/lisc.h +++ b/lisc/lisc.h @@ -139,7 +139,9 @@ enum Op { NPubOp, /* function instructions */ - OArg = NPubOp, + OPar = NPubOp, + OParc, + OArg, OArgc, OCall, |