From a244ca17f1c4e81a92d26119d4f0b5137e93476b Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Sun, 19 Jul 2015 07:03:52 -0400 Subject: start simple work on isel --- lisc/isel.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 lisc/isel.c (limited to 'lisc/isel.c') diff --git a/lisc/isel.c b/lisc/isel.c new file mode 100644 index 0000000..d47ed0f --- /dev/null +++ b/lisc/isel.c @@ -0,0 +1,107 @@ +#include "lisc.h" + +/* For x86_64, we have to: + * + * - add dummy uses for the second argument + * after non-commutative arithmetic + * operations (this prevents the reg. + * allocator to get 'eax = sub ebx eax') + * + * - check that constants are used only in + * places allowed by the machine + * + * - explicit machine register contraints + * on instructions like division. + * + * - lower calls (future, I have to think + * about their representation and the + * way I deal with structs/unions in the + * ABI) + */ + +extern Ins insb[NIns]; /* shared work buffer */ +static Ins *curi; + +static void +emit(short op, Ref to, Ref arg0, Ref arg1) +{ + if (curi == insb) + diag("isel: too many instructions"); + *curi-- = (Ins){op, to, {arg0, arg1}}; +} + +static void +sel(Ins *i, Fn *fn) +{ + int t; + Ref r0, r1; + + switch (i->op) { + case ODiv: + r0 = SYM(RAX); + r1 = SYM(RDX); + if (0) { + case ORem: + r0 = SYM(RDX); + r1 = SYM(RAX); + } + emit(OCopy, i->to, r0, R); + emit(OCopy, R, r1, R); + if (rtype(i->arg[1]) == RConst) { + /* immediates not allowed for + * divisions in x86 + */ + t = fn->ntmp++; + r0 = SYM(t); + } else + r0 = i->arg[1]; + emit(OXDiv, R, r0, R); + emit(OXCltd, SYM(RDX), R, R); + emit(OCopy, SYM(RAX), i->arg[0], R); + if (rtype(i->arg[1]) == RConst) + emit(OCopy, r0, i->arg[1], R); + break; + case OAdd: + case OSub: + if (!opdesc[i->op].commut + && rtype(i->arg[1]) != RConst) + emit(OCopy, R, i->arg[1], R); + emit(i->op, i->to, i->arg[0], i->arg[1]); + break; + default: + diag("isel: non-exhaustive implementation"); + } +} + +/* instruction selection + */ +void +isel(Fn *fn) +{ + Blk *b; + Ins *i; + int t0, t, nins; + + t0 = fn->ntmp; + for (b=fn->start; b; b=b->link) { + curi = &insb[NIns-1]; + for (i=&b->ins[b->nins]; i!=b->ins;) { + sel(--i, fn); + } + nins = &insb[NIns-1] - curi; + curi++; + free(b->ins); + b->ins = alloc(nins * sizeof b->ins[0]); + memcpy(b->ins, curi, nins * sizeof b->ins[0]); + b->nins = nins; + } + if (fn->ntmp == t0) + return; + fn->sym = realloc(fn->sym, fn->ntmp * sizeof(Sym)); + if (!fn->sym) + diag("isel: out of memory"); + for (t=t0; tntmp; t++) { + fn->sym[t].type = STmp; + sprintf(fn->sym[t].name, "isel%d", t-t0); + } +} -- cgit 1.4.1