diff options
Diffstat (limited to 'end.c')
| -rw-r--r-- | end.c | 80 |
1 files changed, 80 insertions, 0 deletions
@@ -0,0 +1,80 @@ +#include "end.h" +#include "errloc.h" +#include "fn.h" +#include "stmt.h" +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +void end_free(struct end *e) +{ +} + +int end_cgen(const struct end *e, struct cgen *c) +{ + const struct stmt *s = &c->fn->stmts[e->block_i]; + + if (!s->end) + { + fprintf(stderr, "%s: unreachable\n", __func__); + return -1; + } + else if (s->end(s, c)) + return -1; + + printf("@__end%zu\n", e->block_i); + return 0; +} + +int end(const struct lex *l, struct prv *p) +{ + struct pos *pos = &p->pos[p->i]; + struct fn *fn = fn_cur(p); + size_t nst = fn->nstmts + 1, *bl, bl_i; + struct stmt *s; + + if (!fn->nblocks) + { + errloc(p->stk, "unexpected \"end\" statement"); + return -1; + } + + bl_i = fn->blocks[fn->nblocks - 1]; + + if (fn->nblocks > 1) + { + if (!(bl = realloc(fn->blocks, (fn->nblocks - 1) * sizeof *bl))) + { + perror("realloc(3)"); + return -1; + } + + fn->blocks = bl; + } + else + { + free(fn->blocks); + fn->blocks = NULL; + } + + fn->nblocks--; + + if (!(s = realloc(fn->stmts, nst * sizeof *s))) + { + perror("realloc(3)"); + return -1; + } + + s[fn->nstmts++] = (struct stmt) + { + .type = END, + .u.end.block_i = bl_i + }; + + fn->stmts = s; + pos->seq = pos->stseq = stmts; + pos->step = stmts->steps; + p->stk = p->tk; + fprintf(stderr, "\t\tadding end statement, block index %zu\n", bl_i); + return 1; +} |
