commit 78bf28f56e7dcdd89efba5c69bd90ed858658162
parent 8be35bf2be509f32d2fccc182743ae409838c4e4
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Wed, 12 Aug 2015 15:25:53 -0400
add basic support for stack allocation
Diffstat:
4 files changed, 54 insertions(+), 3 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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 },