#include "cgen.h" #include "fn.h" #include "gl.h" #include "stmt.h" #include "qbe.h" #include "ws.h" #include 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; }