diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-10-01 01:04:30 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-10-11 00:14:35 +0200 |
| commit | 4ce39e4fc1de9536de7dedfe91b6dee38dec76ae (patch) | |
| tree | f9820f96b8eab624430c3700f32a2878a7036ee2 /src/prc1/cgen/qbe/qbe.c | |
| parent | 9140988be4e5bb028b7140aca1a67af1370c72a7 (diff) | |
| download | prc-4ce39e4fc1de9536de7dedfe91b6dee38dec76ae.tar.gz | |
WIP sym + cgen
Diffstat (limited to 'src/prc1/cgen/qbe/qbe.c')
| -rw-r--r-- | src/prc1/cgen/qbe/qbe.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/prc1/cgen/qbe/qbe.c b/src/prc1/cgen/qbe/qbe.c new file mode 100644 index 0000000..c27bad6 --- /dev/null +++ b/src/prc1/cgen/qbe/qbe.c @@ -0,0 +1,187 @@ +#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 <stddef.h> +#include <stdlib.h> +#include <string.h> + +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, + .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; +} |
