diff options
Diffstat (limited to 'lisc/emit.c')
-rw-r--r-- | lisc/emit.c | 117 |
1 files changed, 117 insertions, 0 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)"); + } + } + +} |