summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lisc/emit.c117
-rw-r--r--lisc/lisc.h6
-rw-r--r--lisc/main.c22
-rw-r--r--lisc/spill.c1
4 files changed, 145 insertions, 1 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
new file mode 100644
index 0000000..9841c14
--- /dev/null
+++ b/lisc/emit.c
@@ -0,0 +1,117 @@
+#include "lisc.h"
+
+
+static void
+eref(Ref r, Fn *fn, FILE *f)
+{
+ switch (rtype(r)) {
+ case RSym:
+ assert(fn->sym[r.val].type == SReg);
+ fprintf(f, "%%%s", fn->sym[r.val].name);
+ break;
+ case RSlot:
+ fprintf(f, "-%d(%%rbp)", 8 * r.val);
+ break;
+ case RConst:
+ fprintf(f, "$%d", (int)r.val);
+ break;
+ default:
+ diag("emitref: invalid reference");
+ }
+}
+
+static void
+eop(char *op, Ref a, Ref b, Fn *fn, FILE *f)
+{
+ fprintf(f, "\t%s ", op);
+ eref(a, fn, f);
+ if (!req(b, R)) {
+ fprintf(f, ", ");
+ eref(b, fn, f);
+ }
+ fprintf(f, "\n");
+}
+
+static void
+eins(Ins i, Fn *fn, FILE *f)
+{
+ static char *opi[] = {
+ [OAdd] = "add",
+ [OSub] = "sub",
+ };
+
+ switch (i.op) {
+ case OAdd:
+ case OSub:
+ if (!req(i.to, i.arg[0]))
+ eop("mov", i.arg[0], i.to, fn, f);
+ eop(opi[i.op], i.arg[1], i.to, fn, f);
+ break;
+ case OStore:
+ i.to = i.arg[1];
+ /* fall through */
+ case OCopy:
+ case OLoad:
+ if (!req(i.arg[0], i.to))
+ eop("mov", i.arg[0], i.to, fn, f);
+ break;
+ case OSwap:
+ eop("xchg", i.arg[0], i.arg[1], fn, f);
+ break;
+ case ONop:
+ break;
+ default:
+ diag("emit: unhandled instruction");
+ }
+}
+
+void
+emitfn(Fn *fn, FILE *f)
+{
+ char *js;
+ Blk *b, *s;
+ Ins *i;
+
+ fprintf(f,
+ ".text\n"
+ ".globl liscf\n"
+ ".type liscf, @function\n"
+ "liscf:\n"
+ "\tpush %%rbp\n"
+ "\tmov %%rsp, %%rbp\n"
+ "\tsub $%u, %%rsp\n",
+ fn->nspill * 8
+ );
+ for (b=fn->start; b; b=b->link) {
+ fprintf(f, ".L%s:\n", b->name);
+ for (i=b->ins; i-b->ins < b->nins; i++)
+ eins(*i, fn, f);
+ switch (b->jmp.type) {
+ case JRet:
+ fprintf(f,
+ "\tleave\n"
+ "\tret\n"
+ );
+ break;
+ case JJmp:
+ if (b->s1 != b->link)
+ fprintf(f, "\tjmp .L%s\n", b->s1->name);
+ break;
+ case JJez:
+ if (b->s1 == b->link) {
+ js = "jnz";
+ s = b->s2;
+ } else if (b->s2 == b->link) {
+ js = "jz";
+ s = b->s1;
+ } else
+ diag("emit: unhandled jump (1)");
+ eop("test", b->jmp.arg, b->jmp.arg, fn, f);
+ fprintf(f, "\t%s .L%s\n", js, s->name);
+ break;
+ default:
+ diag("emit: unhandled jump (2)");
+ }
+ }
+
+}
diff --git a/lisc/lisc.h b/lisc/lisc.h
index f3b9913..d1c25f0 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -19,9 +19,9 @@ enum {
RAX = 1,
RCX,
RDX,
- RBX,
RSI,
RDI,
+ RBX,
R8,
R9,
R10,
@@ -164,6 +164,7 @@ struct Fn {
int ntmp;
int nblk;
Blk **rpo;
+ uint nspill;
};
@@ -197,3 +198,6 @@ void spill(Fn *);
/* rega.c */
void rega(Fn *);
+
+/* emit.c */
+void emitfn(Fn *, FILE *);
diff --git a/lisc/main.c b/lisc/main.c
index d3688ad..81bbb72 100644
--- a/lisc/main.c
+++ b/lisc/main.c
@@ -113,6 +113,28 @@ main(int ac, char *av[])
goto RPODump;
break;
}
+ case 'e': {
+ int n;
+
+ fprintf(stderr, "[Testing Code Emission]\n");
+ fillrpo(fn);
+ fillpreds(fn);
+ filllive(fn);
+ fillcost(fn);
+ spill(fn);
+ rega(fn);
+ fillrpo(fn);
+ assert(fn->rpo[0] == fn->start);
+ for (n=0;; n++)
+ if (n == fn->nblk-1) {
+ fn->rpo[n]->link = 0;
+ break;
+ } else
+ fn->rpo[n]->link = fn->rpo[n+1];
+ emitfn(fn, stdout);
+ pr = 0;
+ break;
+ }
default:
break;
}
diff --git a/lisc/spill.c b/lisc/spill.c
index 76957fc..1181bc1 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -391,4 +391,5 @@ spill(Fn *fn)
memcpy(b->ins, curi, b->nins * sizeof(Ins));
b->in = v;
}
+ fn->nspill = ns;
}