aboutsummaryrefslogtreecommitdiff
path: root/src/lower.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lower.c')
-rw-r--r--src/lower.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/src/lower.c b/src/lower.c
index f4ca28e..beb89c5 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -1,4 +1,5 @@
#include <stdlib.h>
+#include <sys/mman.h>
#include <posthaste/lower.h>
#include <posthaste/scope.h>
@@ -40,12 +41,18 @@ static struct loc null_loc()
return build_global_loc(1);
}
-static void output_insn(struct fn *f, enum insn_kind k, struct loc o, struct loc i0, struct loc i1, int64_t v)
+static void output_insn(struct fn *f, enum insn_kind k, struct loc o,
+ struct loc i0, struct loc i1, int64_t v)
{
struct insn i = {.k = k, .o = o, .i0 = i0, .i1 = i1, .v = v};
vect_append(struct insn, f->insns, &i);
}
+static void output_label(struct fn *f)
+{
+ output_insn(f, LABEL, null_loc(), null_loc(), null_loc(), 0);
+}
+
static void lower_var(struct fn *f, struct ast *n)
{
n->l = build_local_loc(f->sp++);
@@ -222,7 +229,8 @@ static void lower_print(struct fn *f, struct ast *p)
/* don't print space on last element */
if (n->n)
- output_insn(f, PRINT_SPACE, null_loc(), null_loc(), null_loc(), 0);
+ output_insn(f, PRINT_SPACE, null_loc(), null_loc(),
+ null_loc(), 0);
}
output_insn(f, PRINT_NEWLINE, null_loc(), null_loc(), null_loc(), 0);
@@ -243,7 +251,8 @@ static void lower_proc_call(struct fn *f, struct ast *c)
}
struct ast *def = file_scope_find(c->scope, proc_call_id(c));
- output_insn(f, CALL, null_loc(), null_loc(), null_loc(), loc_as_int(def->l));
+ output_insn(f, CALL, null_loc(), null_loc(), null_loc(),
+ loc_as_int(def->l));
c->l = build_local_loc(f->sp);
if (c->t != TYPE_VOID)
@@ -266,7 +275,8 @@ static void lower_func_call(struct fn *f, struct ast *c)
}
struct ast *def = file_scope_find(c->scope, func_call_id(c));
- output_insn(f, CALL, null_loc(), null_loc(), null_loc(), loc_as_int(def->l));
+ output_insn(f, CALL, null_loc(), null_loc(), null_loc(),
+ loc_as_int(def->l));
c->l = build_local_loc(f->sp);
if (c->t != TYPE_VOID)
output_insn(f, RETVAL, c->l, null_loc(), null_loc(), 0);
@@ -394,7 +404,7 @@ static void lower_date_diff(struct fn *f, struct ast *n)
static void lower_until(struct fn *f, struct ast *n)
{
size_t off = vec_len(&f->insns);
- output_insn(f, LABEL, null_loc(), null_loc(), null_loc(), 0);
+ output_label(f);
lower_list(f, until_body(n));
@@ -407,6 +417,8 @@ static void lower_until(struct fn *f, struct ast *n)
static void patch_branch(struct fn *f, size_t branch, size_t off)
{
+ assert((vect_at(struct insn, f->insns, off)).k == LABEL);
+
struct insn i = vect_at(struct insn, f->insns, branch);
i.v = off;
vect_at(struct insn, f->insns, branch) = i;
@@ -429,12 +441,14 @@ static void lower_unless(struct fn *f, struct ast *n)
output_insn(f, J, null_loc(), null_loc(), null_loc(), 0);
size_t off = vec_len(&f->insns);
+ output_label(f);
patch_branch(f, branch, off);
struct ast *otherwise = unless_otherwise(n);
lower_list(f, otherwise);
off = vec_len(&f->insns);
+ output_label(f);
patch_branch(f, jump, off);
n->l = null_loc();
@@ -461,6 +475,7 @@ static void lower_unless_expr(struct fn *f, struct ast *n)
output_insn(f, J, null_loc(), null_loc(), null_loc(), 0);
size_t off = vec_len(&f->insns);
+ output_label(f);
patch_branch(f, branch, off);
struct ast *otherwise = unless_expr_otherwise(n);
@@ -468,6 +483,7 @@ static void lower_unless_expr(struct fn *f, struct ast *n)
output_insn(f, MOVE, n->l, otherwise->l, null_loc(), 0);
off = vec_len(&f->insns);
+ output_label(f);
patch_branch(f, jump, off);
}
@@ -538,9 +554,9 @@ static void add_proc(struct ast *n) {
size_t idx = vec_len(&fns);
n->l = build_global_loc(idx);
struct fn f = {.name = proc_id(n),
- .idx = idx,
- .sp = 0,
- .insns = vec_create(sizeof(struct insn))};
+ .idx = idx,
+ .sp = 0,
+ .insns = vec_create(sizeof(struct insn))};
vect_append(struct fn, fns, &f);
}
@@ -549,9 +565,9 @@ static void add_func(struct ast *n) {
size_t idx = vec_len(&fns);
n->l = build_global_loc(idx);
struct fn f = {.name = func_id(n),
- .idx = idx,
- .sp = 0,
- .insns = vec_create(sizeof(struct insn))};
+ .idx = idx,
+ .sp = 0,
+ .insns = vec_create(sizeof(struct insn))};
vect_append(struct fn, fns, &f);
}
@@ -561,6 +577,8 @@ static void lower_proc_def(struct ast *d)
struct fn *f = vec_at(&fns, d->l.o);
assert(f);
+ f->params = ast_list_len(proc_formals(d));
+
lower_list(f, proc_formals(d));
lower_list(f, proc_vars(d));
lower_list(f, proc_body(d));
@@ -574,6 +592,8 @@ static void lower_func_def(struct ast *d)
struct fn *f = vec_at(&fns, d->l.o);
assert(f);
+ f->params = ast_list_len(func_formals(d));
+
lower_list(f, func_formals(d));
lower_list(f, func_vars(d));
lower_list(f, func_body(d));
@@ -678,9 +698,9 @@ int lower_ast(struct ast *tree)
fns = vec_create(sizeof(struct fn));
struct fn main = {.name = "main",
- .idx = 0,
- .sp = 0,
- .insns = vec_create(sizeof(struct insn))};
+ .idx = 0,
+ .sp = 0,
+ .insns = vec_create(sizeof(struct insn))};
vect_append(struct fn, fns, &main);
@@ -717,6 +737,8 @@ int lower_ast(struct ast *tree)
static void destroy_fn(struct fn *f)
{
vec_destroy(&f->insns);
+ if (f->arena)
+ munmap(f->arena, f->size);
}
void destroy_lowering()