#include "cgen.h" #include "cgen/prv.h" #include "fn.h" #include "lex.h" #include "lit.h" #include "parse.h" #include "qbe.h" #include "storage.h" #include #include #include const char *cgen_sz(const size_t sz) { switch (sz) { case 1: return "b"; case 2: return "h"; case 4: return "w"; case 8: return "l"; default: break; } return NULL; } const char *cgen_tmp2(struct cgen *c) { struct fn_cgen *fnc = c->fnc; for (size_t i = 0; i < sizeof fnc->tmp - 1; i++) { char *s = &fnc->tmp[i]; if (!*s) *s = 'a'; else if (*s >= 'z') *s = 'A'; else if (*s >= 'Z') continue; else (*s)++; return s; } fprintf(stderr, "%s: ran out of temporaries\n", __func__); return NULL; } const char *cgen_tmp(const size_t sz) { switch (sz) { case 1: return "vb"; case 2: return "vh"; case 4: return "vw"; case 8: return "vl"; default: break; } return "v"; } const char *cgen_type(const struct type *t) { switch (t->sz) { case 1: return t->sign ? "b" : "ub"; case 2: return t->sign ? "h" : "uh"; case 4: return t->sign ? "w" : "uw"; case 8: return t->sign ? "l" : "ul"; default: break; } return NULL; } const char *cgen_abity(const struct type *t) { switch (t->sz) { case 1: return t->sign ? "b" : "ub"; case 2: return t->sign ? "h" : "uh"; case 4: return "w"; case 8: return "l"; default: break; } return NULL; } const char *cgen_load(const struct type *t) { switch (t->sz) { case 1: return t->sign ? "sb" : "ub"; case 2: return t->sign ? "sh" : "uh"; case 4: return t->sign ? "sw" : "uw"; case 8: return "l"; default: break; } return NULL; } void cgen_printvar(const struct fn *fn, const struct stentry *e) { const char *name = e->tk->s; if (cgen_global(fn, e)) printf("$%s", name); else printf("%%%s_", name); } static void pushfmt(const char *type, const char *fmt) { printf("data $____fmt%s = { b \"%s\" , b 0 }\n", type, fmt); } int cgen_qbe(const struct ast *ast, struct cgen *c) { static const struct cgen_drv drv = { .print = qbe_print, .call = qbe_call, .free = qbe_free, .from = qbe_from, .set = qbe_set, .gl = qbe_gl, .ws = qbe_ws, .fn = qbe_fn }; c->drv = &drv; /* generate literals to use with printf(3) */ pushfmt("b", "%hhd"); pushfmt("h", "%hd"); pushfmt("w", "%d"); pushfmt("l", "%ld"); pushfmt("ub", "%hhu"); pushfmt("uh", "%hu"); pushfmt("uw", "%u"); pushfmt("ul", "%lu"); pushfmt("bx", "%#hhx"); pushfmt("hx", "%#hx"); pushfmt("wx", "%#x"); pushfmt("lx", "%#lx"); for (const struct lit *l = ast->lits; l; l = l->next) if (lit_cgen(l)) return-1; for (size_t i = 0; i < ast->nfns; i++) if (fn_cgen((c->fn = &ast->fns[i]), c)) return -1; return 0; }