diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-08-12 15:25:53 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-15 23:01:31 -0400 |
commit | 78bf28f56e7dcdd89efba5c69bd90ed858658162 (patch) | |
tree | 071be80e60e3d6ef0f4109112ac9a3803db5a896 | |
parent | 8be35bf2be509f32d2fccc182743ae409838c4e4 (diff) | |
download | roux-78bf28f56e7dcdd89efba5c69bd90ed858658162.tar.gz |
add basic support for stack allocation
-rw-r--r-- | lisc/emit.c | 13 | ||||
-rw-r--r-- | lisc/isel.c | 40 | ||||
-rw-r--r-- | lisc/lisc.h | 2 | ||||
-rw-r--r-- | lisc/parse.c | 2 |
4 files changed, 54 insertions, 3 deletions
diff --git a/lisc/emit.c b/lisc/emit.c index 15be31e..a08ad52 100644 --- a/lisc/emit.c +++ b/lisc/emit.c @@ -128,6 +128,7 @@ eins(Ins i, Fn *fn, FILE *f) static char *otoa[NOp] = { [OAdd] = "add", [OSub] = "sub", + [OAnd] = "and", [OLoad] = "mov", [OLoadss] = "movsw", [OLoadus] = "movzw", @@ -140,12 +141,13 @@ eins(Ins i, Fn *fn, FILE *f) [OStores - OStorel] = "w", [OStoreb - OStorel] = "b", }; - int r; + int reg; int64_t val; switch (i.op) { case OAdd: case OSub: + case OAnd: if (req(i.to, i.arg[1])) { if (i.op == OSub) { eop("neg", i.to, R, fn, f); @@ -177,8 +179,8 @@ eins(Ins i, Fn *fn, FILE *f) case OStoreb: fprintf(f, "\tmov%s ", stoa[i.op - OStorel]); if (rtype(i.arg[0]) == RReg) { - r = RBASE(i.arg[0].val); - fprintf(f, "%%%s", rsub[r][i.op - OStorel]); + reg = RBASE(i.arg[0].val); + fprintf(f, "%%%s", rsub[reg][i.op - OStorel]); } else eref(i.arg[0], fn, f); fprintf(f, ", "); @@ -200,6 +202,11 @@ eins(Ins i, Fn *fn, FILE *f) eref(i.to, fn, f); fprintf(f, "\n"); break; + case OAlloc: + eop("sub", i.arg[0], REG(RSP), fn, f); + if (!req(i.to, R)) + eop("mov", REG(RSP), i.to, fn ,f); + break; case OSwap: eop("xchg", i.arg[0], i.arg[1], fn, f); break; diff --git a/lisc/isel.c b/lisc/isel.c index 7c634d8..5b83081 100644 --- a/lisc/isel.c +++ b/lisc/isel.c @@ -42,6 +42,22 @@ newtmp(int type, Fn *fn) return TMP(t); } +static Ref +newcon(int64_t val, Fn *fn) +{ + int c; + + for (c=0; c<fn->ncon; c++) + if (fn->con[c].type == CNum && fn->con[c].val == val) + return CON(c); + fn->ncon++; + fn->con = realloc(fn->con, fn->ncon * sizeof fn->con[0]); + if (!fn->con) + diag("isel: out of memory"); + fn->con[c] = (Con){.type = CNum, .val = val}; + return CON(c); +} + static int noimm(Ref r, Fn *fn) { @@ -96,6 +112,7 @@ sel(Ins i, Fn *fn) { Ref r0, r1, ra, rd; int n, ty, c; + int64_t val; switch (i.op) { case ODiv: @@ -166,6 +183,29 @@ Emit: } } break; + case OAlloc: + /* we need to make sure + * the stack remains aligned + * (rsp + 8 = 0) mod 16 + * as a consequence, the alloc + * alignment is 8, we can change + * that in the future + */ + if (rtype(i.arg[0]) == RCon) { + val = fn->con[i.arg[0].val].val; + val = (val + 15) & ~INT64_C(15); + if (val < 0 || val > INT32_MAX) + diag("isel: alloc too large"); + emit(OAlloc, i.to, newcon(val, fn), R); + } else { + /* r0 = (i.arg[0] + 15) & -16 */ + r0 = newtmp(TLong, fn); + r1 = newtmp(TLong, fn); + emit(OAlloc, i.to, r0, R); + emit(OAnd, r0, r1, newcon(-16, fn)); + emit(OAdd, r1, i.arg[0], newcon(15, fn)); + } + break; default: if (OCmp <= i.op && i.op <= OCmp1) { c = i.op - OCmp; diff --git a/lisc/lisc.h b/lisc/lisc.h index cd64e29..abf9c1f 100644 --- a/lisc/lisc.h +++ b/lisc/lisc.h @@ -126,6 +126,7 @@ enum { OSub, ODiv, ORem, + OAnd, OCmp, OCmp1 = OCmp + NCmp-1, OStorel, @@ -138,6 +139,7 @@ enum { OLoadsb, OLoadub, OCopy, + OAlloc, NPubOp, /* reserved instructions */ diff --git a/lisc/parse.c b/lisc/parse.c index 104c2a2..fc35800 100644 --- a/lisc/parse.c +++ b/lisc/parse.c @@ -16,6 +16,7 @@ OpDesc opdesc[NOp] = { [OSub] = { "sub", 2, 2 }, [ODiv] = { "div", 2, 2 }, [ORem] = { "rem", 2, 2 }, + [OAnd] = { "and", 2, 2 }, [OStorel] = { "storel", 2, 0 }, [OStorew] = { "storew", 2, 0 }, [OStores] = { "stores", 2, 0 }, @@ -25,6 +26,7 @@ OpDesc opdesc[NOp] = { [OLoadus] = { "loadus", 1, 0 }, [OLoadsb] = { "loadsb", 1, 0 }, [OLoadub] = { "loadub", 1, 0 }, + [OAlloc] = { "alloc", 1, 1 }, [OCopy] = { "copy", 1, 1 }, [ONop] = { "nop", 0, 0 }, [OSwap] = { "swap", 2, 2 }, |