libqbe/libqbe.c

145 lines
2.7 KiB
C

#include "libqbe.h"
#include <getopt.h>
#include <stdio.h>
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));
}