#include "libqbe.h" #include #include Target T; char debug['Z'+1] = { ['P'] = 0, /* parsing */ ['M'] = 0, /* memory optimization */ ['N'] = 0, /* ssa construction */ ['C'] = 0, /* copy elimination */ ['F'] = 0, /* constant folding */ ['A'] = 0, /* abi lowering */ ['I'] = 0, /* instruction selection */ ['L'] = 0, /* liveness */ ['S'] = 0, /* spilling */ ['R'] = 0, /* reg. allocation */ }; static FILE *outf; static int dbg; static void data(Dat *d) { if (dbg) return; emitdat(d, outf); if (d->type == DEnd) { fputs("/* end data */\n\n", outf); freeall(); } } static void func(Fn *fn) { uint n; if (dbg) fprintf(stderr, "**** Function %s ****", fn->name); if (debug['P']) { fprintf(stderr, "\n> After parsing:\n"); printfn(fn, stderr); } T.abi0(fn); fillrpo(fn); fillpreds(fn); filluse(fn); promote(fn); filluse(fn); ssa(fn); filluse(fn); ssacheck(fn); fillalias(fn); loadopt(fn); filluse(fn); fillalias(fn); coalesce(fn); filluse(fn); ssacheck(fn); copy(fn); filluse(fn); fold(fn); T.abi1(fn); simpl(fn); fillpreds(fn); filluse(fn); T.isel(fn); fillrpo(fn); filllive(fn); fillloop(fn); fillcost(fn); spill(fn); rega(fn); fillrpo(fn); simpljmp(fn); fillpreds(fn); fillrpo(fn); assert(fn->rpo[0] == fn->start); for (n=0;; n++) if (n == fn->nblk-1) { fn->rpo[n]->link = 0; break; } else fn->rpo[n]->link = fn->rpo[n+1]; if (!dbg) { T.emitfn(fn, outf); fprintf(outf, "/* end function %s */\n\n", fn->name); } else fprintf(stderr, "\n"); freeall(); } static void dbgfile(char *fn) { emitdbgfile(fn, outf); } const char* qbe_gen(Target target, const char* ssa) { T = target; FILE *inf = tmpfile(); fputs(ssa, inf); rewind(inf); outf = tmpfile(); char* f = "-"; parse(inf, f, dbgfile, data, func); fclose(inf); if (!dbg) T.emitfin(outf); fseek(outf, 0, SEEK_END); long size = ftell(outf); fseek(outf, 0, SEEK_SET); char* buf = malloc(size + 1); fread(buf, size, 1, outf); buf[size] = '\0'; fclose(outf); return buf; } void qbe_emit(const char* filename, const char* assembly) { char cc[255]; snprintf(cc, 255, "cc -x assembler -o %s -", filename); FILE* cc_pipe = popen(cc, "w"); if(fputs(assembly, cc_pipe) == EOF) { perror("fputs"); } pclose(cc_pipe); } void qbe_gen_and_emit(Target target, const char* filename, const char* ssa) { qbe_emit(filename, qbe_gen(target, ssa)); }