#include "cgen.h" #include "fn.h" #include "lex.h" #include "lit.h" #include "parse.h" #include "storage.h" #include #include #include void cgen_free(struct cgen *c) { } 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_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; } int cgen_param(const struct fn *fn, const struct stentry *e) { const struct pr *pr = fn->pr; const char *name = e->tk->s; for (size_t i = 0; i < pr->nparams; i++) if (!strcmp(pr->params[i].tk->s, name)) return 1; return 0; } int cgen_global(const struct fn *fn, const struct stentry *e) { const struct storage *ws = fn->ws, *gl = fn->gl; const struct pr *pr = fn->pr; const struct param *ret = pr->ret; const char *name = e->tk->s; /* A variable is only global if it is defined inside the global * variables section ("gl"), or if it is not listed on the working * storage section ("ws"), as a function parameter or a return value. */ if (gl) for (size_t i = 0; i < gl->nentries; i++) if (!strcmp(gl->entries[i].tk->s, name)) return 1; if (cgen_param(fn, e)) return 0; if (ret && !strcmp(ret->tk->s, name)) return 0; if (ws) for (size_t i = 0; i < ws->nentries; i++) if (!strcmp(ws->entries[i].tk->s, name)) return 0; return 1; } static void pushfmt(const char *type, const char *fmt) { printf("data $____fmt%s = { b \"%s\" , b 0 }\n", type, fmt); } int cgen(const struct ast *ast, struct cgen *c) { /* 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; }