ref: 3e6f824c6113b7c4defaa01cf25cd94d1b050f69
dir: /8/isel.c/
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <stdarg.h> #include <ctype.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "parse.h" #include "gen.h" #include "asm.h" typedef struct Isel Isel; struct Isel { Insn **il; size_t ni; }; char *regnames[] = { #define Reg(r, name, mode) name, #include "regs.def" #undef Reg }; Mode regmodes[] = { #define Reg(r, name, mode) mode, #include "regs.def" #undef Reg }; char *insnfmts[] = { #define Insn(val, fmt, attr) fmt, #include "insns.def" #undef Insn }; Loc *loclbl(Loc *l, char *lbl) { l->type = Loclbl; l->mode = ModeL; l->lbl = strdup(lbl); return l; } Loc *locreg(Loc *l, Reg r) { l->type = Locreg; l->mode = regmodes[r]; l->reg = r; return l; } Loc *locpseudo(Loc *l, Mode mode) { static long nextpseudo; l->type = Locpseudo; l->mode = mode; l->pseudo = nextpseudo++; return l; } Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode) { l->type = Locmem; l->mode = mode; l->mem.constdisp = disp; l->mem.base = base; l->mem.idx = idx; return l; } Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode) { l->type = Locmem; l->mode = mode; l->mem.lbldisp = strdup(disp); l->mem.base = base; l->mem.idx = idx; return l; } Loc *loclit(Loc *l, long val) { l->type = Loclit; l->mode = ModeL; /* FIXME: what do we do for mode? */ l->lit = val; return l; } Insn *mkinsnv(AsmOp op, va_list ap) { Loc *l; Insn *i; int n; n = 0; i = malloc(sizeof(Insn)); i->op = op; while ((l = va_arg(ap, Loc*)) != NULL) i->args[n++] = *l; i->narg = n; return i; } Insn *mkinsn(AsmOp op, ...) { va_list ap; Insn *i; va_start(ap, op); i = mkinsnv(op, ap); va_end(ap); return i; } void g(Isel *s, AsmOp op, ...) { va_list ap; Insn *i; va_start(ap, op); i = mkinsnv(op, ap); va_end(ap); lappend(&s->il, &s->ni, i); } void selexpr(Isel *s, Node *n) { Loc a, b; Node **args; args = n->expr.args; switch (exprop(n)) { case Oadd: die("Unimplemented op %s", opstr(exprop(n))); break; case Osub: die("Unimplemented op %s", opstr(exprop(n))); break; case Omul: die("Unimplemented op %s", opstr(exprop(n))); break; case Odiv: die("Unimplemented op %s", opstr(exprop(n))); break; case Omod: die("Unimplemented op %s", opstr(exprop(n))); break; case Oneg: die("Unimplemented op %s", opstr(exprop(n))); break; case Obor: die("Unimplemented op %s", opstr(exprop(n))); break; case Oband: die("Unimplemented op %s", opstr(exprop(n))); break; case Obxor: die("Unimplemented op %s", opstr(exprop(n))); break; case Obsl: die("Unimplemented op %s", opstr(exprop(n))); break; case Obsr: die("Unimplemented op %s", opstr(exprop(n))); break; case Obnot: die("Unimplemented op %s", opstr(exprop(n))); break; case Oaddr: die("Unimplemented op %s", opstr(exprop(n))); break; case Oderef: die("Unimplemented op %s", opstr(exprop(n))); break; case Oeq: die("Unimplemented op %s", opstr(exprop(n))); break; case One: die("Unimplemented op %s", opstr(exprop(n))); break; case Ogt: die("Unimplemented op %s", opstr(exprop(n))); break; case Oge: die("Unimplemented op %s", opstr(exprop(n))); break; case Olt: die("Unimplemented op %s", opstr(exprop(n))); break; case Ole: die("Unimplemented op %s", opstr(exprop(n))); break; case Oasn: g(s, Imov, locreg(&b, Rebx), locreg(&a, Reax), NULL); break; case Oidx: die("Unimplemented op %s", opstr(exprop(n))); break; case Oslice: die("Unimplemented op %s", opstr(exprop(n))); break; case Osize: die("Unimplemented op %s", opstr(exprop(n))); break; case Ocall: die("Unimplemented op %s", opstr(exprop(n))); break; case Ocast: die("Unimplemented op %s", opstr(exprop(n))); break; case Ojmp: g(s, Ijmp, loclbl(&a, args[0]->lbl.name), NULL); break; case Ocjmp: die("Unimplemented op %s", opstr(exprop(n))); break; case Ovar: die("Unimplemented op %s", opstr(exprop(n))); break; case Olit: die("Unimplemented op %s", opstr(exprop(n))); break; case Olbl: die("Unimplemented op %s", opstr(exprop(n))); break; case Obad: case Oret: case Opreinc: case Opostinc: case Opredec: case Opostdec: case Olor: case Oland: case Olnot: case Oaddeq: case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq: case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb: die("Should not see %s in isel", opstr(exprop(n))); break; } } void locprint(FILE *fd, Loc *l) { switch (l->type) { case Loclbl: fprintf(fd, "%s", l->lbl); break; case Locreg: fprintf(fd, "%s", regnames[l->reg]); break; case Locpseudo: fprintf(fd, "%%P%ld", l->pseudo); break; case Locmem: case Locmeml: if (l->type == Locmem) { if (l->mem.constdisp) fprintf(fd, "%ld", l->mem.constdisp); } else { if (l->mem.lbldisp) fprintf(fd, "%s", l->mem.lbldisp); } if (l->mem.base) fprintf(fd, "(%s", regnames[l->mem.base]); if (l->mem.idx) fprintf(fd, ",%s", regnames[l->mem.idx]); if (l->mem.base) fprintf(fd, ")"); break; case Loclit: break; } } void modeprint(FILE *fd, Loc *l) { char mode[] = {'b', 's', 'l', 'q'}; fputc(mode[l->mode], fd); } void iprintf(FILE *fd, Insn *insn) { char *p; int i; int modeidx; p = insnfmts[insn->op]; i = 0; for (; *p; p++) { if (*p != '%') { fputc(*p, fd); continue; } /* %-formating */ p++; switch (*p) { case '\0': goto done; case 'r': case 'm': case 'l': case 'x': case 'v': locprint(fd, &insn->args[i]); i++; break; case 't': modeidx = 0; default: if (isdigit(*p)) modeidx = strtol(p, &p, 10); if (*p == 't') modeprint(fd, &insn->args[modeidx]); else die("Invalid %%-specifier '%c'", *p); break; } } done: return; } void isel(Node *n) { struct Isel is = {0,}; Loc lbl; int i; switch (n->type) { case Nlbl: g(&is, Ilbl, loclbl(&lbl, n->lbl.name), NULL); break; case Nexpr: selexpr(&is, n); break; case Ndecl: break; default: die("Bad node type in isel()"); break; } for (i = 0; i < is.ni; i++) iprintf(stdout, is.il[i]); } void genasm(Node **nl, int nn) { int i; for (i = 0; i < nn; i++) isel(nl[i]); }