summaryrefslogtreecommitdiff
path: root/lisc
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-08-24 17:39:52 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-15 23:01:32 -0400
commit7beed9e6cf1ebc8bfb995e317f933781c4f2964a (patch)
tree6950d0061f746f8cc46e9e963c1dc856382fcb94 /lisc
parentd9b9c68532a47d9ba84249f17ce2e7dd0d1df3c8 (diff)
downloadroux-7beed9e6cf1ebc8bfb995e317f933781c4f2964a.tar.gz
update emit to the new setting
Diffstat (limited to 'lisc')
-rw-r--r--lisc/Makefile2
-rw-r--r--lisc/emit.c287
-rw-r--r--lisc/main.c2
3 files changed, 126 insertions, 165 deletions
diff --git a/lisc/Makefile b/lisc/Makefile
index c8e9447..fe6b664 100644
--- a/lisc/Makefile
+++ b/lisc/Makefile
@@ -1,5 +1,5 @@
BIN = lisc
-OBJ = main.o parse.o ssa.o live.o isel.o spill.o rega.o # emit.o
+OBJ = main.o parse.o ssa.o live.o isel.o spill.o rega.o emit.o
CFLAGS = -Wall -Wextra -std=c99 -g -pedantic
diff --git a/lisc/emit.c b/lisc/emit.c
index 10a9691..eba04ac 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -1,5 +1,5 @@
#include "lisc.h"
-
+#include <stdarg.h>
enum { SLong, SWord, SShort, SByte };
static char *rsub[][4] = {
@@ -31,13 +31,91 @@ static char *ctoa[NCmp] = {
[Cne ] = "ne",
};
-static char *
-rtoa(int r)
+static void
+emitf(Fn *fn, FILE *f, char *fmt, ...)
{
- if (r < EAX)
- return rsub[r][SLong];
- else
- return rsub[RBASE(r)][SWord];
+ static char stoa[] = "qlwb";
+ va_list ap;
+ char c, *s, *s1;
+ int i, ty;
+ Ref ref;
+ Con *con;
+
+ va_start(ap, fmt);
+ ty = SWord;
+ s = fmt;
+Next:
+ while ((c = *s++) != '%')
+ if (!c) {
+ va_end(ap);
+ return;
+ } else
+ fputc(c, f);
+ switch ((c = *s++)) {
+ default:
+ diag("emit: unknown escape");
+ case 'w':
+ case 'W':
+ i = va_arg(ap, int);
+ ty = i ? SLong: SWord;
+ if (0) {
+ case 't':
+ case 'T':
+ ty = va_arg(ap, int);
+ }
+ if (c == 't' || c == 'w')
+ fputc(stoa[ty], f);
+ break;
+ case 's':
+ s1 = va_arg(ap, char *);
+ fputs(s1, f);
+ break;
+ case 'R':
+ ref = va_arg(ap, Ref);
+ switch (rtype(ref)) {
+ default:
+ diag("emit: invalid reference");
+ case RTmp:
+ assert(isreg(ref));
+ fprintf(f, "%%%s", rsub[ref.val][ty]);
+ break;
+ case RSlot:
+ Slot:
+ fprintf(f, "-%d(%%rbp)", 4 * ref.val);
+ break;
+ case RCon:
+ fputc('$', f);
+ Con:
+ con = &fn->con[ref.val];
+ switch (con->type) {
+ default:
+ diag("emit: invalid constant");
+ case CAddr:
+ fputs(con->label, f);
+ if (con->val)
+ fprintf(f, "%+"PRId64, con->val);
+ break;
+ case CNum:
+ fprintf(f, "%"PRId64, con->val);
+ break;
+ }
+ break;
+ }
+ break;
+ case 'M':
+ ref = va_arg(ap, Ref);
+ switch (rtype(ref)) {
+ default: diag("emit: invalid memory reference");
+ case RSlot: goto Slot;
+ case RCon: goto Con;
+ case RTmp:
+ assert(isreg(ref));
+ fprintf(f, "(%%%s)", rsub[ref.val][SLong]);
+ break;
+ }
+ break;
+ }
+ goto Next;
}
static int
@@ -55,74 +133,6 @@ cneg(int cmp)
}
static void
-econ(Con *c, FILE *f)
-{
- switch (c->type) {
- case CAddr:
- fprintf(f, "%s", c->label);
- if (c->val)
- fprintf(f, "%+"PRId64, c->val);
- break;
- case CNum:
- fprintf(f, "%"PRId64, c->val);
- break;
- default:
- diag("econ: invalid constant");
- }
-}
-
-static void
-eref(Ref r, Fn *fn, FILE *f)
-{
- switch (rtype(r)) {
- default:
- diag("emit: invalid reference");
- case RTmp:
- assert(r.val < Tmp0);
- fprintf(f, "%%%s", rtoa(r.val));
- break;
- case RSlot:
- fprintf(f, "-%d(%%rbp)", 4 * r.val);
- break;
- case RCon:
- fprintf(f, "$");
- econ(&fn->con[r.val], f);
- break;
- }
-}
-
-static void
-emem(Ref r, Fn *fn, FILE *f)
-{
- switch (rtype(r)) {
- default:
- diag("emit: invalid memory reference");
- case RSlot:
- eref(r, fn, f);
- break;
- case RCon:
- econ(&fn->con[r.val], f);
- break;
- case RTmp:
- assert(r.val < EAX);
- fprintf(f, "(%%%s)", rtoa(r.val));
- break;
- }
-}
-
-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 *otoa[NOp] = {
@@ -130,26 +140,15 @@ eins(Ins i, Fn *fn, FILE *f)
[OSub] = "sub",
[OMul] = "imul",
[OAnd] = "and",
- [OSext] = "movslq",
- [OZext] = "movzlq",
+ [OSext] = "movsl",
+ [OZext] = "movzl",
[OLoad] = "mov",
[OLoadss] = "movsw",
[OLoadus] = "movzw",
[OLoadsb] = "movsb",
[OLoadub] = "movzb",
- [OXCmpw] = "cmpl",
- [OXCmpl] = "cmpq",
- [OXTestw] = "testl",
- [OXTestl] = "testq",
- };
- static char *stoa[] = {
- [OStorel - OStorel] = "q",
- [OStorew - OStorel] = "l",
- [OStores - OStorel] = "w",
- [OStoreb - OStorel] = "b",
};
Ref r0, r1;
- int reg;
int64_t val;
switch (i.op) {
@@ -162,9 +161,7 @@ eins(Ins i, Fn *fn, FILE *f)
r1 = i.arg[1];
}
if (rtype(r0) == RCon && rtype(r1) == RTmp) {
- val = fn->con[r0.val].val;
- fprintf(f, "\timul $%"PRId64", %%%s, %%%s\n",
- val, rtoa(r1.val), rtoa(i.to.val));
+ emitf(fn, f, "\timul%w %R, %R, %R\n", i.wide, r0, r1, i.to);
break;
}
/* fall through */
@@ -173,114 +170,89 @@ eins(Ins i, Fn *fn, FILE *f)
case OAnd:
if (req(i.to, i.arg[1])) {
if (i.op == OSub) {
- eop("neg", i.to, R, fn, f);
- eop("add", i.arg[0], i.to, fn, f);
+ emitf(fn, f, "\tneg%w %R\n", i.wide, i.to);
+ emitf(fn, f, "\tadd%w %R, %R\n",
+ i.wide, i.arg[0], i.to);
break;
}
i.arg[1] = i.arg[0];
i.arg[0] = i.to;
}
if (!req(i.to, i.arg[0]))
- eop("mov", i.arg[0], i.to, fn, f);
- eop(otoa[i.op], i.arg[1], i.to, fn, f);
+ emitf(fn, f, "\tmov%w %R, %R\n", i.wide, i.arg[0], i.to);
+ emitf(fn, f, "\t%s%w %R, %R\n", otoa[i.op], i.wide, i.arg[1], i.to);
break;
case OSext:
case OZext:
- eop(otoa[i.op], i.arg[0], i.to, fn, f);
+ emitf(fn, f, "\t%sq %R, %W%R\n", otoa[i.op],
+ i.arg[0], i.wide, i.to.val);
break;
- case OTrunc:
- if (rtype(i.arg[0]) == RTmp)
- i.arg[0] = TMP(RWORD(i.arg[0].val));
- /* fall through */
case OCopy:
if (req(i.to, R))
break;
- if (rtype(i.to) == RTmp
- && i.to.val < EAX
+ if (isreg(i.to)
+ && i.wide
&& rtype(i.arg[0]) == RCon
&& fn->con[i.arg[0].val].type == CNum
&& (val = fn->con[i.arg[0].val].val) >= 0
&& val <= UINT32_MAX) {
- fprintf(f, "\tmov $%"PRId64", %%%s\n",
- val, rsub[i.to.val][SWord]);
- break;
- }
- if (!req(i.arg[0], i.to))
- eop("mov", i.arg[0], i.to, fn, f);
+ emitf(fn, f, "\tmovl %R, %R\n", i.arg[0], i.to);
+ } else if (!req(i.arg[0], i.to))
+ emitf(fn, f, "\tmov%w %R, %R\n", i.wide, i.arg[0], i.to);
break;
case OStorel:
case OStorew:
case OStores:
case OStoreb:
- fprintf(f, "\tmov%s ", stoa[i.op - OStorel]);
- if (rtype(i.arg[0]) == RTmp) {
- assert(i.arg[0].val < Tmp0);
- reg = RBASE(i.arg[0].val);
- fprintf(f, "%%%s", rsub[reg][i.op - OStorel]);
- } else
- eref(i.arg[0], fn, f);
- fprintf(f, ", ");
- emem(i.arg[1], fn, f);
- fprintf(f, "\n");
+ emitf(fn, f, "\tmov%t %R, %M\n", i.op - OStorel, i.arg[0], i.arg[1]);
break;
case OLoad:
case OLoadss:
case OLoadus:
case OLoadsb:
case OLoadub:
- fprintf(f, "\t%s", otoa[i.op]);
- if (i.to.val < EAX)
- fprintf(f, "q ");
- else
- fprintf(f, "l ");
- emem(i.arg[0], fn, f);
- fprintf(f, ", ");
- eref(i.to, fn, f);
- fprintf(f, "\n");
+ emitf(fn, f, "\t%s%w %M, %R\n", otoa[i.op], i.wide, i.arg[0], i.to);
break;
case OAlloc:
- eop("sub", i.arg[0], TMP(RSP), fn, f);
- if (!req(i.to, R))
- eop("mov", TMP(RSP), i.to, fn ,f);
+ emitf(fn, f, "\tsub%w %R, %R\n", 1, i.arg[0], TMP(RSP));
+ emitf(fn, f, "\tmov%w %R, %R\n", 1, TMP(RSP), i.to);
break;
case OAddr:
- eop("lea", i.arg[0], i.to, fn, f);
+ emitf(fn, f, "\tlea%w %M, %R\n", i.wide, i.arg[0], i.to);
break;
case OSwap:
- eop("xchg", i.arg[0], i.arg[1], fn, f);
+ emitf(fn, f, "\txchg%w %R, %R", i.wide, i.arg[0], i.arg[1]);
break;
case OSign:
- if (req(i.to, TMP(RDX)) && req(i.arg[0], TMP(RAX)))
- fprintf(f, "\tcqto\n");
- else if (req(i.to, TMP(EDX)) && req(i.arg[0], TMP(EAX)))
- fprintf(f, "\tcltd\n");
- else
+ if (req(i.to, TMP(RDX)) && req(i.arg[0], TMP(RAX))) {
+ if (i.wide)
+ fprintf(f, "\tcqto\n");
+ else
+ fprintf(f, "\tcltd\n");
+ } else
diag("emit: unhandled instruction (2)");
break;
case OXDiv:
- eop("idiv", i.arg[0], R, fn, f);
+ emitf(fn, f, "\tidiv%w %R\n", i.wide, i.arg[0]);
break;
- case OXCmpw:
- case OXCmpl:
- if (rtype(i.arg[1]) == RTmp && req(i.arg[0], CON_Z)) {
- eop("test", i.arg[1], i.arg[1], fn, f);
+ case OXCmp:
+ if (isreg(i.arg[1]) && req(i.arg[0], CON_Z)) {
+ emitf(fn, f, "\ttest%w %R, %R\n", i.wide, i.arg[1], i.arg[1]);
break;
}
- /* fall through */
- case OXTestw:
- case OXTestl:
- eop(otoa[i.op], i.arg[0], i.arg[1], fn, f);
+ emitf(fn, f, "\tcmp%w %R, %R\n", i.wide, i.arg[0], i.arg[1]);
+ break;
+ case OXTest:
+ emitf(fn, f, "\ttest%w %R, %R\n", i.wide, i.arg[0], i.arg[1]);
break;
case ONop:
break;
default:
if (OXSet <= i.op && i.op <= OXSet1) {
- fprintf(f, "\tset%s %%%s\n",
- ctoa[i.op-OXSet],
- rsub[RBASE(i.to.val)][SByte]);
- fprintf(f, "\tmovzb %%%s, %%%s\n",
- rsub[RBASE(i.to.val)][SByte],
- rtoa(i.to.val));
+ emitf(fn, f, "\tset%s%t %R\n",
+ ctoa[i.op-OXSet], SByte, i.to);
+ emitf(fn, f, "\tmovzb%w %T%R, %W%R\n",
+ i.wide, SByte, i.to, i.wide, i.to);
break;
}
diag("emit: unhandled instruction (3)");
@@ -320,17 +292,8 @@ emitfn(Fn *fn, FILE *f)
fs = framesz(fn);
if (fs)
fprintf(f, "\tsub $%d, %%rsp\n", fs);
- for (b=fn->start; b; b=b->link)
- b->visit = 0;
- for (b=fn->start; b; b=b->link) {
- if (b->s1 && b->link != b->s1)
- b->s1->visit++;
- if (b->s2 && b->link != b->s2)
- b->s2->visit++;
- }
for (b=fn->start; b; b=b->link) {
- if (b->visit != 0)
- fprintf(f, ".L%s:\n", b->name);
+ 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) {
diff --git a/lisc/main.c b/lisc/main.c
index b4abeba..f4ed6ea 100644
--- a/lisc/main.c
+++ b/lisc/main.c
@@ -113,7 +113,6 @@ main(int ac, char *av[])
rega(fn);
goto RPODump;
}
- #if 0
case 'e': {
int n;
@@ -137,7 +136,6 @@ main(int ac, char *av[])
pr = 0;
break;
}
- #endif
default:
break;
}