diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-05 17:14:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-26 03:41:55 +0200 |
| commit | 3c0819236e4f07c8f57aaf1ca46d0d68aa761558 (patch) | |
| tree | bd8b57cf5420cabc4ec29815052df545b55026f9 /fn.c | |
| parent | a3f56c76444fee090e62a59f257ed5f60b4e552b (diff) | |
| download | prc-3c0819236e4f07c8f57aaf1ca46d0d68aa761558.tar.gz | |
Move source to src/prc1
Diffstat (limited to 'fn.c')
| -rw-r--r-- | fn.c | 273 |
1 files changed, 0 insertions, 273 deletions
@@ -1,273 +0,0 @@ -#include "fn.h" -#include "div.h" -#include "errloc.h" -#include "gl.h" -#include "im.h" -#include "parse.h" -#include "prv.h" -#include "pr.h" -#include "stmt.h" -#include "storage.h" -#include "td.h" -#include "ws.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -static int pubfn(const struct lex *l, struct prv *p); -static int prvfn(const struct lex *l, struct prv *p); - -static const struct seq fnseq[] = -{ - {(struct step[]) - {{ID, "public"}, {ID, "function"}, {ID}, {0}}, .fn = pubfn, - .end = fn_end}, - {(struct step[]) - {{ID, "function"}, {ID}, {0}}, .fn = prvfn, .end = fn_end}, - {0} -}; - -int fn_end(const struct lex *l, struct prv *p) -{ - const struct fn *fn = fn_cur(p); - - if (!fn->pr) - { - const struct tk *tk = fn->tk; - const char *s = p->proto ? "prototype" : "function"; - - errloc(p->stk - 1, "%s \"%s\" has no procedure", s, tk->s); - return -1; - } - else if (fn->nblocks) - { - const struct tk *tk = lex_eof(l, p->stk) ? p->tk - 1 : p->stk; - - errloc(tk, "missing \"end\" in function \"%s\"", fn->tk->s); - return -1; - } - - return 0; -} - -static const struct tk *findfn(const char *s, const struct ast *ast) -{ - for (size_t i = 0; i < ast->nfns; i++) - { - const struct tk *tk = ast->fns[i].tk; - - if (!strcmp(tk->s, s)) - return tk; - } - - return NULL; -} - -static int pushfn(const struct tk *tk, const struct lex *lex, struct prv *p, - enum linkage l) -{ - const struct tk *def; - struct ast *ast = p->ast; - size_t n = ast->nfns + 1; - struct fn *fns; - - if ((def = findfn(tk->s, ast))) - { - const struct loc *loc = &def->loc; - - errloc(tk, "function \"%s\" already defined at %s:%d:%d", tk->s, - loc->f, loc->line, loc->col); - return -1; - } - else if (!(fns = realloc(ast->fns, n * sizeof *fns))) - { - perror("realloc(3)"); - return -1; - } - - fns[ast->nfns++] = (struct fn){.linkage = l, .tk = tk}; - ast->fns = fns; - - if (div_fn(lex, p)) - return -1; - - fprintf(stderr, "adding %s function %s\n", - l == STATIC ? "private" : "public", tk->s); - return 1; -} - -static int pubfn(const struct lex *l, struct prv *p) -{ - return pushfn(p->stk + 2, l, p, EXTERNAL); -} - -static int prvfn(const struct lex *l, struct prv *p) -{ - return pushfn(p->stk + 1, l, p, STATIC); -} - -const struct stentry *fn_var(const struct fn *fn, const struct tk *tk) -{ - const struct storage *lk = fn->lk, *ws = fn->ws, *gl = fn->gl; - const struct stentry *e; - - if ((lk && (e = storage_find(tk->s, lk))) - || (ws && (e = storage_find(tk->s, ws))) - || (gl && (e = storage_find(tk->s, gl)))) - return e; - - for (size_t i = 0; i < fn->nimps; i++) - if ((e = fn_var(fn->imps[i].ast.fns, tk))) - return e; - - return NULL; -} - -int fn_cgen(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; - - 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; -} - -void fn_cgen_free(struct fn_cgen *c) -{ - free(c); -} - -void fn_free(struct fn *fn) -{ - for (size_t i = 0; i < fn->nimps; i++) - im_free(&fn->imps[i]); - - for (size_t i = 0; i < fn->nstmts; i++) - stmt_free(&fn->stmts[i]); - - for (struct tmp *t = fn->tmps; t;) - { - struct tmp *next = t->next; - - free(t->tk.s); - free(t); - t = next; - } - - storage_free(fn->lk); - storage_free(fn->ws); - storage_free(fn->gl); - pr_free(fn->pr); - td_free(fn->td); - free(fn->imps); - free(fn->stmts); - free(fn->blocks); -} - -struct fn *fn_cur(const struct prv *p) -{ - struct ast *ast = p->ast; - - if (p->proto) - return p->proto; - - return &ast->fns[p->ast->nfns - 1]; -} - -int fn(const struct lex *l, struct prv *p) -{ - struct pos init = - { - .seq = fnseq, - .stseq = fnseq, - .step = fnseq->steps - }; - - if (lex_eof(l, p->stk)) - return 0; - else if (lex_eof(l, p->stk + 1)) - { - errloc(p->stk, "incomplete function statement"); - return -1; - } - else if (push(&init, p)) - return -1; - - p->stk = p->tk; - return 1; -} |
