aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/cgen/qbe/fn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/prc1/cgen/qbe/fn.c')
-rw-r--r--src/prc1/cgen/qbe/fn.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/prc1/cgen/qbe/fn.c b/src/prc1/cgen/qbe/fn.c
new file mode 100644
index 0000000..61b0bf0
--- /dev/null
+++ b/src/prc1/cgen/qbe/fn.c
@@ -0,0 +1,94 @@
+#include "cgen.h"
+#include "fn.h"
+#include "gl.h"
+#include "stmt.h"
+#include "qbe.h"
+#include "ws.h"
+#include <stdio.h>
+
+int qbe_fn(const struct fn *fn, struct cgen *c)
+{
+ const struct pr *pr = fn->pr;
+ const struct param *ret = pr->ret;
+ const struct type *rt = NULL;
+ const char *s = NULL;
+ struct fn_cgen fnc = {0};
+
+ c->fnc = &fnc;
+
+ if (fn->gl && gl_cgen(fn->gl, c))
+ return -1;
+
+ switch (fn->linkage)
+ {
+ case STATIC:
+ printf("function ");
+ break;
+ case EXTERNAL:
+ printf("export function ");
+ break;
+ }
+
+ if (ret)
+ {
+ rt = ret->entry->t;
+ s = ret->entry->tk->s;
+ printf("%s ", cgen_abity(ret->entry->t));
+ }
+
+ printf("$%s(", fn->tk->s);
+
+ for (size_t i = 0; i < pr->nparams; i++)
+ {
+ const struct param *p = &pr->params[i];
+
+ printf(" %s", cgen_abity(p->entry->t));
+ printf(" %%__param_%s ", p->tk->s);
+
+ if (i + 1 < pr->nparams)
+ fputs(", ", stdout);
+ }
+
+ puts(") {\n@start");
+
+ for (size_t i = 0; i < pr->nparams; i++)
+ {
+ const struct param *p = &pr->params[i];
+ const struct type *t = p->entry->t;
+ const char *s = p->tk->s;
+
+ printf("%%%s_ =l alloc%zu %zu\n", s, t->align, t->sz);
+ printf("store%s %%__param_%s, %%%s_\n", cgen_sz(t->sz), s, s);
+ }
+
+ if (ret)
+ printf("%%%s_ =l alloc%zu %zu\n", s, rt->align, rt->sz);
+
+ if (fn->ws && ws_cgen(fn->ws, c))
+ return -1;
+
+ for (const struct tmp *tmp = fn->tmps; tmp; tmp = tmp->next)
+ {
+ const struct stentry *e = &tmp->e;
+ const struct type *t = tmp->e.t;
+
+ printf("%%%s_ =l alloc%zu %zu\n", e->tk->s, t->align, t->sz);
+ }
+
+ for (size_t i = 0; i < fn->nstmts; i++)
+ if (stmt_cgen(&fn->stmts[i], c))
+ return -1;
+
+ if (ret)
+ {
+ const char *t = cgen_tmp(rt->sz);
+
+ printf("%%%s =%s load%s %%%s_\n", t, cgen_sz(rt->sz), cgen_load(rt), s);
+ printf("ret %%%s", t);
+ }
+ else
+ fputs("ret", stdout);
+
+ puts("\n}");
+ return 0;
+}