diff options
-rw-r--r-- | lisc/Makefile | 2 | ||||
-rw-r--r-- | lisc/emit.c | 287 | ||||
-rw-r--r-- | lisc/main.c | 2 |
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; } |