diff options
Diffstat (limited to 'cgen.c')
| -rw-r--r-- | cgen.c | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -0,0 +1,166 @@ +#include "cgen.h" +#include "fn.h" +#include "lex.h" +#include "lit.h" +#include "parse.h" +#include "storage.h" +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +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; +} |
