aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c4
-rw-r--r--src/check.c125
-rw-r--r--src/compile.c652
-rw-r--r--src/core.c21
-rw-r--r--src/date.c3
-rw-r--r--src/execute.c83
-rw-r--r--src/lower.c50
7 files changed, 817 insertions, 121 deletions
diff --git a/src/ast.c b/src/ast.c
index 3860c97..10f14d0 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -50,8 +50,8 @@ struct ast *gen_ast(enum ast_kind kind,
struct ast *a1,
struct ast *a2,
char *id,
- char *type,
- int64_t v,
+ char *type,
+ int64_t v,
struct src_loc loc)
{
struct ast *n = create_empty_ast();
diff --git a/src/check.c b/src/check.c
index 54929a1..498fcf8 100644
--- a/src/check.c
+++ b/src/check.c
@@ -42,7 +42,8 @@ static int analyze_list(struct state *state, struct scope *scope, struct ast *l)
return 0;
}
-static struct ast *file_scope_find_analyzed(struct state *state, struct scope *scope, char *id)
+static struct ast *file_scope_find_analyzed(struct state *state,
+ struct scope *scope, char *id)
{
struct ast *exists = file_scope_find(scope, id);
if (!exists)
@@ -74,7 +75,8 @@ static int analyze_type(struct scope *scope, struct ast *n)
return -1;
}
-static int analyze_func_def(struct state *state, struct scope *scope, struct ast *f)
+static int analyze_func_def(struct state *state, struct scope *scope,
+ struct ast *f)
{
UNUSED(state);
if (analyze_type(scope, f))
@@ -97,7 +99,8 @@ static int analyze_func_def(struct state *state, struct scope *scope, struct ast
return analyze(&func_state, func_scope, func_body(f));
}
-static int analyze_proc_def(struct state *state, struct scope *scope, struct ast *p)
+static int analyze_proc_def(struct state *state, struct scope *scope,
+ struct ast *p)
{
UNUSED(state);
if (analyze_type(scope, p))
@@ -129,7 +132,8 @@ static int analyze_proc_def(struct state *state, struct scope *scope, struct ast
return 0;
}
-static int analyze_var_def(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_var_def(struct state *state, struct scope *scope,
+ struct ast *n)
{
if (scope_add_var(scope, n))
return -1;
@@ -142,7 +146,8 @@ static int analyze_var_def(struct state *state, struct scope *scope, struct ast
return 0;
}
-static int analyze_formal_def(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_formal_def(struct state *state, struct scope *scope,
+ struct ast *n)
{
UNUSED(state);
if (analyze_type(scope, n))
@@ -162,9 +167,9 @@ static int analyze_neg(struct state *state, struct scope *scope, struct ast *n)
if (expr->t != TYPE_INT) {
semantic_error(scope, n,
- "negation requires %s, got %s\n",
- type_str(TYPE_INT),
- type_str(expr->t));
+ "negation requires %s, got %s\n",
+ type_str(TYPE_INT),
+ type_str(expr->t));
return -1;
}
@@ -180,9 +185,9 @@ static int analyze_pos(struct state *state, struct scope *scope, struct ast *p)
if (expr->t != TYPE_INT) {
semantic_error(scope, p,
- "unary pos requires %s, got %s\n",
- type_str(TYPE_INT),
- type_str(expr->t));
+ "unary pos requires %s, got %s\n",
+ type_str(TYPE_INT),
+ type_str(expr->t));
return -1;
}
@@ -190,7 +195,8 @@ static int analyze_pos(struct state *state, struct scope *scope, struct ast *p)
return 0;
}
-static int analyze_const_date(struct state *state, struct scope *scope, struct ast *d)
+static int analyze_const_date(struct state *state, struct scope *scope,
+ struct ast *d)
{
UNUSED(state);
UNUSED(scope);
@@ -199,7 +205,8 @@ static int analyze_const_date(struct state *state, struct scope *scope, struct a
return 0;
}
-static int analyze_const_int(struct state *state, struct scope *scope, struct ast *i)
+static int analyze_const_int(struct state *state, struct scope *scope,
+ struct ast *i)
{
UNUSED(state);
UNUSED(scope);
@@ -207,7 +214,8 @@ static int analyze_const_int(struct state *state, struct scope *scope, struct as
return 0;
}
-static int analyze_const_string(struct state *state, struct scope *scope, struct ast *s)
+static int analyze_const_string(struct state *state, struct scope *scope,
+ struct ast *s)
{
UNUSED(state);
UNUSED(scope);
@@ -227,8 +235,8 @@ static int analyze_eq(struct state *state, struct scope *scope, struct ast *e)
if (r->t != l->t) {
semantic_error(scope, e, "type mismatch: %s vs %s\n",
- type_str(l->t),
- type_str(r->t));
+ type_str(l->t),
+ type_str(r->t));
return -1;
}
@@ -248,8 +256,8 @@ static int analyze_lt(struct state *state, struct scope *scope, struct ast *e)
if (r->t != l->t) {
semantic_error(scope, e, "type mismatch: %s vs %s\n",
- type_str(l->t),
- type_str(r->t));
+ type_str(l->t),
+ type_str(r->t));
return -1;
}
@@ -308,7 +316,7 @@ static int analyze_sub(struct state *state, struct scope *scope, struct ast *s)
}
semantic_error(scope, s, "illegal subtraction types: %s, %s",
- type_str(l->t), type_str(r->t));
+ type_str(l->t), type_str(r->t));
return -1;
}
@@ -320,7 +328,7 @@ static int analyze_mul(struct state *state, struct scope *scope, struct ast *m)
if (l->t != TYPE_INT) {
semantic_error(scope, l, "expected %s, got %s",
- type_str(TYPE_INT), type_str(l->t));
+ type_str(TYPE_INT), type_str(l->t));
return -1;
}
@@ -330,7 +338,7 @@ static int analyze_mul(struct state *state, struct scope *scope, struct ast *m)
if (r->t != TYPE_INT) {
semantic_error(scope, r, "expected %s, got %s",
- type_str(TYPE_INT), type_str(r->t));
+ type_str(TYPE_INT), type_str(r->t));
return -1;
}
@@ -346,7 +354,7 @@ static int analyze_div(struct state *state, struct scope *scope, struct ast *d)
if (l->t != TYPE_INT) {
semantic_error(scope, l, "expected %s, got %s",
- type_str(TYPE_INT), type_str(l->t));
+ type_str(TYPE_INT), type_str(l->t));
return -1;
}
@@ -356,7 +364,7 @@ static int analyze_div(struct state *state, struct scope *scope, struct ast *d)
if (r->t != TYPE_INT) {
semantic_error(scope, r, "expected %s, got %s",
- type_str(TYPE_INT), type_str(r->t));
+ type_str(TYPE_INT), type_str(r->t));
return -1;
}
@@ -364,7 +372,8 @@ static int analyze_div(struct state *state, struct scope *scope, struct ast *d)
return 0;
}
-static int analyze_print(struct state *state, struct scope *scope, struct ast *p)
+static int analyze_print(struct state *state, struct scope *scope,
+ struct ast *p)
{
struct ast *items = print_items(p);
struct ast *fixups = NULL, *last_fixup = NULL;
@@ -395,7 +404,8 @@ static int analyze_print(struct state *state, struct scope *scope, struct ast *p
return 0;
}
-static int analyze_return(struct state *state, struct scope *scope, struct ast *r)
+static int analyze_return(struct state *state, struct scope *scope,
+ struct ast *r)
{
struct ast *parent = state->parent;
if (!parent) {
@@ -405,7 +415,8 @@ static int analyze_return(struct state *state, struct scope *scope, struct ast *
if (!has_type(parent)) {
- semantic_error(scope, r, "stray return in proc without return type");
+ semantic_error(scope, r,
+ "stray return in proc without return type");
return -1;
}
@@ -415,7 +426,7 @@ static int analyze_return(struct state *state, struct scope *scope, struct ast *
if (expr->t != parent->t) {
semantic_error(scope, r, "return type mismatch: %s vs %s",
- type_str(parent->t), type_str(expr->t));
+ type_str(parent->t), type_str(expr->t));
return -1;
}
@@ -449,7 +460,7 @@ static int analyze_dot(struct state *state, struct scope *scope, struct ast *d)
if (base->t != TYPE_DATE) {
semantic_error(scope, d, "expected %d, got %d",
- type_str(TYPE_DATE), type_str(base->t));
+ type_str(TYPE_DATE), type_str(base->t));
return -1;
}
@@ -474,8 +485,8 @@ static int analyze_attr(struct state *state, struct scope *scope, struct ast *d)
return -1;
if (base->t != TYPE_DATE) {
- semantic_error(scope, d, "expected %d, got %d",
- type_str(TYPE_DATE), type_str(base->t));
+ semantic_error(scope, d, "expected %s, got %s",
+ type_str(TYPE_DATE), type_str(base->t));
return -1;
}
@@ -501,7 +512,8 @@ static int analyze_attr(struct state *state, struct scope *scope, struct ast *d)
return -1;
}
-static int analyze_assign(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_assign(struct state *state, struct scope *scope,
+ struct ast *n)
{
struct ast *l = assign_l(n);
if (analyze(state, scope, l))
@@ -513,7 +525,7 @@ static int analyze_assign(struct state *state, struct scope *scope, struct ast *
if (l->t != r->t) {
semantic_error(scope, n, "type mismatch: %s vs %s",
- type_str(l->t), type_str(r->t));
+ type_str(l->t), type_str(r->t));
return -1;
}
@@ -521,12 +533,13 @@ static int analyze_assign(struct state *state, struct scope *scope, struct ast *
return 0;
}
-static int analyze_today(struct state *state, struct scope *scope, struct ast *c)
+static int analyze_today(struct state *state, struct scope *scope,
+ struct ast *c)
{
UNUSED(state);
if (ast_list_len(func_call_args(c)) != 0) {
semantic_error(scope, c, "expected 0 arguments, got %zd",
- ast_list_len(func_call_args(c)));
+ ast_list_len(func_call_args(c)));
return -1;
}
@@ -535,9 +548,11 @@ static int analyze_today(struct state *state, struct scope *scope, struct ast *c
return 0;
}
-static int analyze_proc_call(struct state *state, struct scope *scope, struct ast *c)
+static int analyze_proc_call(struct state *state, struct scope *scope,
+ struct ast *c)
{
- struct ast *exists = file_scope_find_analyzed(state, scope, proc_call_id(c));
+ struct ast *exists = file_scope_find_analyzed(state, scope,
+ proc_call_id(c));
if (!exists || exists->k != AST_PROC_DEF) {
semantic_error(scope, c, "no such proc");
return -1;
@@ -550,14 +565,15 @@ static int analyze_proc_call(struct state *state, struct scope *scope, struct as
struct ast *formal = proc_formals(exists);
if (ast_list_len(formal) != ast_list_len(args)) {
semantic_error(scope, c, "expected %s args, got %s",
- ast_list_len(formal), ast_list_len(args));
+ ast_list_len(formal), ast_list_len(args));
return -1;
}
foreach_node(a, args) {
if (a->t != formal->t) {
semantic_error(scope, c, "expected %s, got %s",
- type_str(formal->t), type_str(a->t));
+ type_str(formal->t), type_str(a->t));
+ return -1;
}
formal = formal->n;
@@ -567,13 +583,15 @@ static int analyze_proc_call(struct state *state, struct scope *scope, struct as
return 0;
}
-static int analyze_func_call(struct state *state, struct scope *scope, struct ast *c)
+static int analyze_func_call(struct state *state, struct scope *scope,
+ struct ast *c)
{
/* handle special Today() built-in */
if (same_id(func_call_id(c), "Today"))
return analyze_today(state, scope, c);
- struct ast *exists = file_scope_find_analyzed(state, scope, func_call_id(c));
+ struct ast *exists = file_scope_find_analyzed(state, scope,
+ func_call_id(c));
if (!exists || exists->k != AST_FUNC_DEF) {
semantic_error(scope, c, "no such func");
return -1;
@@ -585,15 +603,16 @@ static int analyze_func_call(struct state *state, struct scope *scope, struct as
struct ast *formal = func_formals(exists);
if (ast_list_len(formal) != ast_list_len(args)) {
- semantic_error(scope, c, "expected %s args, got %s",
- ast_list_len(formal), ast_list_len(args));
+ semantic_error(scope, c, "expected %zd args, got %zd",
+ ast_list_len(formal), ast_list_len(args));
return -1;
}
foreach_node(a, args) {
if (a->t != formal->t) {
semantic_error(scope, c, "expected %s, got %s",
- type_str(formal->t), type_str(a->t));
+ type_str(formal->t), type_str(a->t));
+ return -1;
}
formal = formal->n;
@@ -603,7 +622,8 @@ static int analyze_func_call(struct state *state, struct scope *scope, struct as
return 0;
}
-static int analyze_until(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_until(struct state *state, struct scope *scope,
+ struct ast *n)
{
struct scope *until_scope = create_scope();
scope_add_scope(scope, until_scope);
@@ -618,7 +638,7 @@ static int analyze_until(struct state *state, struct scope *scope, struct ast *n
if (cond->t != TYPE_BOOL) {
semantic_error(scope, cond, "expected %s, got %s",
- type_str(TYPE_BOOL), type_str(cond->t));
+ type_str(TYPE_BOOL), type_str(cond->t));
return -1;
}
@@ -626,7 +646,8 @@ static int analyze_until(struct state *state, struct scope *scope, struct ast *n
return 0;
}
-static int analyze_unless(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_unless(struct state *state, struct scope *scope,
+ struct ast *n)
{
struct scope *unless_scope = create_scope();
struct scope *otherwise_scope = create_scope();
@@ -643,7 +664,7 @@ static int analyze_unless(struct state *state, struct scope *scope, struct ast *
if (cond->t != TYPE_BOOL) {
semantic_error(scope, cond, "expected %s, got %s",
- type_str(TYPE_BOOL), type_str(cond->t));
+ type_str(TYPE_BOOL), type_str(cond->t));
return -1;
}
@@ -655,7 +676,8 @@ static int analyze_unless(struct state *state, struct scope *scope, struct ast *
return 0;
}
-static int analyze_unless_expr(struct state *state, struct scope *scope, struct ast *n)
+static int analyze_unless_expr(struct state *state, struct scope *scope,
+ struct ast *n)
{
struct ast *body = unless_expr_body(n);
if (analyze(state, scope, body))
@@ -667,7 +689,7 @@ static int analyze_unless_expr(struct state *state, struct scope *scope, struct
if (cond->t != TYPE_BOOL) {
semantic_error(scope, cond, "expected %s, got %s",
- type_str(TYPE_BOOL), type_str(cond->t));
+ type_str(TYPE_BOOL), type_str(cond->t));
return -1;
}
@@ -677,7 +699,7 @@ static int analyze_unless_expr(struct state *state, struct scope *scope, struct
if (body->t != otherwise->t) {
semantic_error(scope, n, "type mismatch: %s vs %s",
- type_str(body->t), type_str(otherwise->t));
+ type_str(body->t), type_str(otherwise->t));
return -1;
}
@@ -714,7 +736,8 @@ static int analyze(struct state *state, struct scope *scope, struct ast *n)
case AST_POS: ret = analyze_pos(state, scope, n); break;
case AST_CONST_DATE: ret = analyze_const_date(state, scope, n); break;
case AST_CONST_INT: ret = analyze_const_int(state, scope, n); break;
- case AST_CONST_STRING: ret = analyze_const_string(state, scope, n); break;
+ case AST_CONST_STRING: ret = analyze_const_string(state, scope, n);
+ break;
case AST_EQ: ret = analyze_eq(state, scope, n); break;
case AST_LT: ret = analyze_lt(state, scope, n); break;
case AST_ADD: ret = analyze_add(state, scope, n); break;
diff --git a/src/compile.c b/src/compile.c
new file mode 100644
index 0000000..9bbdbf4
--- /dev/null
+++ b/src/compile.c
@@ -0,0 +1,652 @@
+#include <math.h>
+#include <sys/mman.h>
+
+#include <posthaste/compile.h>
+#include <posthaste/lower.h>
+#include <posthaste/date.h>
+
+#include <lightening/lightening.h>
+
+#define UNUSED(x) (void)x
+
+static void compile_fn(struct fn *f);
+
+static void *alloc_arena(size_t size)
+{
+ return mmap(NULL, size,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void free_arena(void *arena, size_t size)
+{
+ munmap(arena, size);
+}
+
+static jit_operand_t formal_at(size_t i)
+{
+ return jit_operand_mem(JIT_OPERAND_ABI_INT64, JIT_SP,
+ i * sizeof(int64_t));
+}
+
+static void get(jit_state_t *j, jit_gpr_t r, struct loc l)
+{
+ if (l.l) {
+ jit_ldxi_l(j, r, JIT_SP, l.o * sizeof(int64_t));
+ return;
+ }
+
+ jit_ldxi_l(j, r, JIT_V0, l.o * sizeof(int64_t));
+}
+
+static void put(jit_state_t *j, jit_gpr_t r, struct loc l)
+{
+ if (l.l) {
+ jit_stxi_l(j, l.o * sizeof(int64_t), JIT_SP, r);
+ return;
+ }
+
+ jit_stxi_l(j, l.o * sizeof(int64_t), JIT_V0, r);
+}
+
+static void compile_add(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_addr(j, JIT_R0, JIT_R0, JIT_R1);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_sub(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_subr(j, JIT_R0, JIT_R0, JIT_R1);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_mul(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_mulr(j, JIT_R0, JIT_R0, JIT_R1);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_div(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_divr(j, JIT_R0, JIT_R0, JIT_R1);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_move(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_const(jit_state_t *j, struct insn i)
+{
+ jit_movi(j, JIT_R0, i.v);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_eq(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_reloc_t branch = jit_beqr(j, JIT_R0, JIT_R1);
+
+ jit_movi(j, JIT_R0, 0);
+ jit_reloc_t jump = jit_jmp(j);
+ jit_patch_there(j, branch, jit_address(j));
+
+ jit_movi(j, JIT_R0, 1);
+ jit_patch_there(j, jump, jit_address(j));
+
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_lt(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_reloc_t branch = jit_bltr(j, JIT_R0, JIT_R1);
+
+ jit_movi(j, JIT_R0, 0);
+ jit_reloc_t jump = jit_jmp(j);
+ jit_patch_there(j, branch, jit_address(j));
+
+ jit_movi(j, JIT_R0, 1);
+ jit_patch_there(j, jump, jit_address(j));
+
+ put(j, JIT_R0, i.o);
+}
+
+static void print_date(int64_t date)
+{
+ char str[11];
+ date_to_string(str, (ph_date_t)date);
+ printf("%s", str);
+}
+
+static void compile_print_date(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, print_date,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+}
+
+static void print_int(int64_t i)
+{
+ printf("%lli", (long long)i);
+}
+
+static void compile_print_int(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, print_int,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+}
+
+static void print_string(const char *s)
+{
+ printf("%s", s);
+}
+
+static void compile_print_string(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, print_string,
+ jit_operand_gpr(JIT_OPERAND_ABI_POINTER, JIT_R0));
+}
+
+static void print_bool(int64_t b)
+{
+ printf("%s", b ? "true" : "false");
+}
+
+static void compile_print_bool(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, print_bool,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+}
+
+static void compile_print_newline(jit_state_t *j, struct insn i)
+{
+ UNUSED(i);
+ jit_calli_1(j, putchar, jit_operand_imm(JIT_OPERAND_ABI_INT8, '\n'));
+}
+
+static void compile_print_space(jit_state_t *j, struct insn i)
+{
+ UNUSED(i);
+ jit_calli_1(j, putchar, jit_operand_imm(JIT_OPERAND_ABI_INT8, ' '));
+}
+
+static void compile_label(jit_state_t *j, size_t ii, struct vec *labels)
+{
+ vect_at(jit_addr_t, *labels, ii) = jit_address(j);
+}
+
+struct reloc_helper {
+ jit_reloc_t r;
+ size_t to;
+};
+
+static void compile_j(jit_state_t *j, struct insn i, struct vec *relocs)
+{
+ jit_reloc_t r = jit_jmp(j);
+ struct reloc_helper h = {.r = r, .to = i.v};
+ vect_append(struct reloc_helper, *relocs, &h);
+}
+
+static void compile_b(jit_state_t *j, struct insn i, struct vec *relocs)
+{
+ get(j, JIT_R0, i.i0);
+ jit_reloc_t r = jit_bnei(j, JIT_R0, 0);
+ struct reloc_helper h = {.r = r, .to = i.v};
+ vect_append(struct reloc_helper, *relocs, &h);
+}
+
+static void compile_bz(jit_state_t *j, struct insn i, struct vec *relocs)
+{
+ get(j, JIT_R0, i.i0);
+ jit_reloc_t r = jit_beqi(j, JIT_R0, 0);
+ struct reloc_helper h = {.r = r, .to = i.v};
+ vect_append(struct reloc_helper, *relocs, &h);
+}
+
+static void compile_arg(struct insn i, struct vec *params)
+{
+ jit_operand_t operand;
+ struct loc l = i.i0;
+ if (l.l) {
+ operand = jit_operand_mem(JIT_OPERAND_ABI_INT64, JIT_SP,
+ l.o * sizeof(int64_t));
+ }
+ else {
+ operand = jit_operand_mem(JIT_OPERAND_ABI_INT64, JIT_V0,
+ l.o * sizeof(int64_t));
+ }
+
+ vect_append(jit_operand_t, *params, &operand);
+}
+
+static void compile_call(jit_state_t *j, struct insn i, struct vec *params)
+{
+ jit_operand_t gp = jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_V0);
+ vect_append(jit_operand_t, *params, &gp);
+
+ struct fn *f = find_fn(i.v);
+ assert(f);
+
+ if (!f->arena)
+ compile_fn(f);
+
+ jit_calli(j, f->arena, vec_len(params), params->buf);
+ vec_reset(params);
+}
+
+static void compile_retval(jit_state_t *j, struct insn i)
+{
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_neg(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_negr(j, JIT_R0, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static void compile_today(jit_state_t *j, struct insn i)
+{
+ jit_calli_0(j, current_date);
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static ph_date_t date_add(int64_t i0, int64_t i1)
+{
+ struct tm time = tm_from_date((ph_date_t)i0);
+ time.tm_mday += i1;
+ mktime(&time);
+
+ return date_from_tm(time);
+}
+
+static void compile_date_add(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_calli_2(j, date_add,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static ph_date_t date_sub(int64_t i0, int64_t i1)
+{
+ struct tm time = tm_from_date((ph_date_t)i0);
+ time.tm_mday -= i1;
+ mktime(&time);
+
+ return date_from_tm(time);
+}
+
+static void compile_date_sub(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_calli_2(j, date_sub,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t date_diff(int64_t i0, int64_t i1)
+{
+ struct tm tm0 = tm_from_date((ph_date_t)i0);
+ struct tm tm1 = tm_from_date((ph_date_t)i1);
+
+ time_t t0 = mktime(&tm0);
+ time_t t1 = mktime(&tm1);
+
+ double seconds = difftime(t0, t1);
+ return round(seconds / 86400);
+}
+
+static void compile_date_diff(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+
+ jit_calli_2(j, date_diff,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t load_year(int64_t i0)
+{
+ unsigned year = 0;
+ date_split((ph_date_t)i0, &year, NULL, NULL);
+ return year;
+}
+
+static void compile_load_year(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, load_year,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t load_month(int64_t i0)
+{
+ unsigned month = 0;
+ date_split((ph_date_t)i0, NULL, &month, NULL);
+ return month;
+}
+
+static void compile_load_month(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, load_month,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t load_day(int64_t i0)
+{
+ unsigned day = 0;
+ date_split((ph_date_t)i0, NULL, NULL, &day);
+ return day;
+}
+
+static void compile_load_day(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, load_day,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t load_weekday(int64_t i0)
+{
+ struct tm time = tm_from_date((ph_date_t)i0);
+
+ const char *day = "Sunday";
+ switch (time.tm_wday) {
+ case 0: day = "Sunday"; break;
+ case 1: day = "Monday"; break;
+ case 2: day = "Tuesday"; break;
+ case 3: day = "Wednesday"; break;
+ case 4: day = "Thursday"; break;
+ case 5: day = "Friday"; break;
+ case 6: day = "Saturday"; break;
+ }
+
+ return (int64_t)day;
+}
+
+static void compile_load_weekday(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, load_weekday,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t load_weeknum(int64_t i0)
+{
+ struct tm time = tm_from_date((ph_date_t)i0);
+ return time.tm_yday / 7;
+}
+
+static void compile_load_weeknum(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ jit_calli_1(j, load_weeknum,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t store_year(int64_t i0, int64_t i1)
+{
+ unsigned month = 0;
+ unsigned day = 0;
+ date_split((ph_date_t)i0, NULL, &month, &day);
+ return date_from_numbers(i1, month, day);
+}
+
+static void compile_store_year(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_calli_2(j, store_year,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t store_month(int64_t i0, int64_t i1)
+{
+ unsigned year = 0;
+ unsigned day = 0;
+ date_split((ph_date_t)i0, &year, NULL, &day);
+ return date_from_numbers(year, i1, day);
+}
+
+static void compile_store_month(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_calli_2(j, store_month,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static int64_t store_day(int64_t i0, int64_t i1)
+{
+ unsigned year = 0;
+ unsigned month = 0;
+ date_split((ph_date_t)i0, &year, &month, NULL);
+ return date_from_numbers(year, month, i1);
+}
+
+static void compile_store_day(jit_state_t *j, struct insn i)
+{
+ get(j, JIT_R0, i.i0);
+ get(j, JIT_R1, i.i1);
+ jit_calli_2(j, store_day,
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R0),
+ jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_R1));
+
+ jit_retval_l(j, JIT_R0);
+ put(j, JIT_R0, i.o);
+}
+
+static size_t compile_fn_body(struct fn *f, jit_state_t *j)
+{
+ jit_begin(j, f->arena, f->size);
+ size_t frame = jit_enter_jit_abi(j, 1, 0, 0);
+ /* easy off-by-one to miss, damn */
+ size_t stack = jit_align_stack(j, (f->max_sp + 1) * sizeof(int64_t));
+
+ /* move parameters to where they belong */
+ struct vec params = vec_create(sizeof(jit_operand_t));
+ for (size_t i = 0; i < f->params; ++i) {
+ jit_operand_t operand = formal_at(i);
+ vec_append(&params, &operand);
+ }
+
+ jit_operand_t gp = jit_operand_gpr(JIT_OPERAND_ABI_INT64, JIT_V0);
+ vec_append(&params, &gp);
+ jit_load_args(j, f->params + 1, params.buf);
+
+ /* reuse vector as argument vector */
+ vec_reset(&params);
+
+ struct vec relocs = vec_create(sizeof(struct reloc_helper));
+ struct vec labels = vec_create(sizeof(jit_addr_t));
+ vec_reserve(&labels, vec_len(&f->insns));
+
+ foreach_vec(ii, f->insns) {
+ struct insn i = vect_at(struct insn, f->insns, ii);
+ switch (i.k) {
+ case LABEL: compile_label(j, ii, &labels); break;
+ case J: compile_j(j, i, &relocs); break;
+ case B: compile_b(j, i, &relocs); break;
+ case BZ: compile_bz(j, i, &relocs); break;
+ case ADD: compile_add(j, i); break;
+ case SUB: compile_sub(j, i); break;
+ case MUL: compile_mul(j, i); break;
+ case DIV: compile_div(j, i); break;
+ case MOVE: compile_move(j, i); break;
+ case CONST: compile_const(j, i); break;
+ case EQ: compile_eq(j, i); break;
+ case LT: compile_lt(j, i); break;
+
+ case PRINT_DATE: compile_print_date(j, i); break;
+ case PRINT_INT: compile_print_int(j, i); break;
+ case PRINT_STRING: compile_print_string(j, i); break;
+ case PRINT_BOOL: compile_print_bool(j, i); break;
+ case PRINT_NEWLINE: compile_print_newline(j, i); break;
+ case PRINT_SPACE: compile_print_space(j, i); break;
+
+ case ARG: compile_arg(i, &params); break;
+ case CALL: compile_call(j, i, &params); break;
+ case RETVAL: compile_retval(j, i); break;
+
+ case NEG: compile_neg(j, i); break;
+
+ case TODAY: compile_today(j, i); break;
+
+ case DATE_ADD: compile_date_add(j, i); break;
+ case DATE_SUB: compile_date_sub(j, i); break;
+ case DATE_DIFF: compile_date_diff(j, i); break;
+
+ case LOAD_YEAR: compile_load_year(j, i); break;
+ case LOAD_MONTH: compile_load_month(j, i); break;
+ case LOAD_DAY: compile_load_day(j, i); break;
+ case LOAD_WEEKDAY: compile_load_weekday(j, i); break;
+ case LOAD_WEEKNUM: compile_load_weeknum(j, i); break;
+
+ case STORE_YEAR: compile_store_year(j, i); break;
+ case STORE_MONTH: compile_store_month(j, i); break;
+ case STORE_DAY: compile_store_day(j, i); break;
+
+ case RET: {
+ get(j, JIT_R0, i.i0);
+ jit_shrink_stack(j, stack);
+ jit_leave_jit_abi(j, 1, 0, frame);
+ jit_retr(j, JIT_R0);
+ break;
+ }
+
+ case STOP: {
+ jit_shrink_stack(j, stack);
+ jit_leave_jit_abi(j, 1, 0, frame);
+ jit_ret(j);
+ break;
+ }
+ }
+ }
+
+ /* fix relocs */
+ foreach_vec(ri, relocs) {
+ struct reloc_helper h = vect_at(struct reloc_helper, relocs,
+ ri);
+ jit_addr_t a = vect_at(jit_addr_t, labels, h.to);
+ jit_reloc_t r = h.r;
+
+ assert(a);
+ jit_patch_there(j, r, a);
+ }
+
+ vec_destroy(&relocs);
+ vec_destroy(&labels);
+ vec_destroy(&params);
+
+ size_t size = 0;
+ void *p = jit_end(j, &size);
+ if (p)
+ return 0;
+
+ return size;
+}
+
+static void compile_fn(struct fn *f)
+{
+ init_jit();
+ jit_state_t *j = jit_new_state(NULL, NULL);
+ assert(j);
+
+ void *arena_base = NULL;
+ size_t arena_size = 4096;
+ while (1) {
+ arena_base = alloc_arena(arena_size);
+ assert(arena_base &&
+ "failed allocating executable arena, aborting");
+
+ f->arena = arena_base;
+ f->size = arena_size;
+
+ size_t required_size = compile_fn_body(f, j);
+ if (required_size == 0)
+ break;
+
+ free_arena(arena_base, arena_size);
+ /* give at least one page more than necessary to be on the safe
+ * side */
+ arena_size = required_size + 4096;
+ }
+
+ jit_destroy_state(j);
+}
+
+void compile()
+{
+ struct fn *f = find_fn(0);
+ compile_fn(f);
+}
+
+void execute_compilation()
+{
+ struct fn *f = find_fn(0);
+ void (*p)(int64_t *globals) = f->arena;
+
+ struct vec globals = vec_create(sizeof(int64_t));
+ vec_reserve(&globals, 65535);
+
+ p(globals.buf);
+
+ vec_destroy(&globals);
+}
diff --git a/src/core.c b/src/core.c
index c50860e..44aa130 100644
--- a/src/core.c
+++ b/src/core.c
@@ -3,6 +3,7 @@
#include <limits.h>
#include <errno.h>
+#include <posthaste/compile.h>
#include <posthaste/execute.h>
#include <posthaste/parser.h>
#include <posthaste/debug.h>
@@ -12,16 +13,6 @@
#include <posthaste/core.h>
#include <posthaste/ast.h>
-/**
- * Read whole file into a buffer and return pointer to buffer.
- * Possibly kind of silly to have both \p file and \p f.
- * Apparently there's no standardized way to get the file name of a
- * file pointer.
- *
- * @param fname Name of file to read.
- * @param f File pointer.
- * @return Pointer to buffer with file contents.
- */
static char *read_file(const char *fname, FILE *f)
{
fseek(f, 0, SEEK_END);
@@ -91,12 +82,14 @@ int run(const char *fname)
goto out;
}
- if (lower_ast(ast)) {
- ret = -1;
- goto out;
- }
+ lower_ast(ast);
+#ifdef JIT
+ compile(ast);
+ execute_compilation();
+#else
execute();
+#endif
out:
free((void *)buf);
diff --git a/src/date.c b/src/date.c
index 11f35c4..f81b69f 100644
--- a/src/date.c
+++ b/src/date.c
@@ -30,7 +30,8 @@ struct tm tm_from_date(ph_date_t date)
unsigned day = 0;
date_split(date, &year, &month, &day);
- struct tm time = {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day};
+ struct tm time = {.tm_year = year - 1900, .tm_mon = month - 1,
+ .tm_mday = day};
mktime(&time);
return time;
}
diff --git a/src/execute.c b/src/execute.c
index 0d321d7..bd9cd6b 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -8,9 +8,11 @@
#define UNUSED(x) (void)x
#define DEF(x) \
-static void exec_##x(struct insn i, size_t sp, struct vec *stack, struct vec *globals)
+ static void exec_##x(struct insn i, size_t sp, struct vec *stack, \
+ struct vec *globals)
-static int64_t load(struct loc l, size_t sp, struct vec *stack, struct vec *globals)
+static int64_t load(struct loc l, size_t sp, struct vec *stack,
+ struct vec *globals)
{
if (l.l)
return vect_at(int64_t, *stack, l.o + sp);
@@ -18,7 +20,8 @@ static int64_t load(struct loc l, size_t sp, struct vec *stack, struct vec *glob
return vect_at(int64_t, *globals, l.o);
}
-static void store(struct loc l, int64_t v, size_t sp, struct vec *stack, struct vec *globals)
+static void store(struct loc l, int64_t v, size_t sp, struct vec *stack,
+ struct vec *globals)
{
if (l.l) {
vect_at(int64_t, *stack, l.o + sp) = v;
@@ -155,13 +158,13 @@ DEF(LOAD_WEEKDAY) {
const char *day = "Sunday";
switch (time.tm_wday) {
- case 0: day = "Sunday"; break;
- case 1: day = "Monday"; break;
- case 2: day = "Tuesday"; break;
- case 3: day = "Wednesday"; break;
- case 4: day = "Thursday"; break;
- case 5: day = "Friday"; break;
- case 6: day = "Saturday"; break;
+ case 0: day = "Sunday"; break;
+ case 1: day = "Monday"; break;
+ case 2: day = "Tuesday"; break;
+ case 3: day = "Wednesday"; break;
+ case 4: day = "Thursday"; break;
+ case 5: day = "Friday"; break;
+ case 6: day = "Saturday"; break;
}
put(i.o, (int64_t)day);
@@ -250,7 +253,8 @@ DEF(DATE_DIFF) {
put(i.o, days);
}
-static int64_t exec_func(struct fn *f, struct vec *args, size_t sp, struct vec *stack, struct vec *globals)
+static int64_t exec_func(struct fn *f, struct vec *args, size_t sp,
+ struct vec *stack, struct vec *globals)
{
/* move args to formal locations */
size_t i = 0;
@@ -306,37 +310,38 @@ static int64_t exec_func(struct fn *f, struct vec *args, size_t sp, struct vec *
struct fn *cf = find_fn(i.v);
assert(cf);
- retval = exec_func(cf, args, sp + f->max_sp, stack, globals);
+ retval = exec_func(cf, args, sp + f->max_sp, stack,
+ globals);
break;
}
- DO(MOVE);
- DO(ADD);
- DO(SUB);
- DO(MUL);
- DO(DIV);
- DO(CONST);
- DO(PRINT_DATE);
- DO(PRINT_INT);
- DO(PRINT_BOOL);
- DO(PRINT_STRING);
- DO(PRINT_NEWLINE);
- DO(PRINT_SPACE);
- DO(LOAD_DAY);
- DO(LOAD_MONTH);
- DO(LOAD_YEAR);
- DO(LOAD_WEEKDAY);
- DO(LOAD_WEEKNUM);
- DO(STORE_DAY);
- DO(STORE_MONTH);
- DO(STORE_YEAR);
- DO(DATE_ADD);
- DO(DATE_SUB);
- DO(DATE_DIFF);
- DO(TODAY);
- DO(EQ);
- DO(LT);
- DO(NEG);
+ DO(MOVE);
+ DO(ADD);
+ DO(SUB);
+ DO(MUL);
+ DO(DIV);
+ DO(CONST);
+ DO(PRINT_DATE);
+ DO(PRINT_INT);
+ DO(PRINT_BOOL);
+ DO(PRINT_STRING);
+ DO(PRINT_NEWLINE);
+ DO(PRINT_SPACE);
+ DO(LOAD_DAY);
+ DO(LOAD_MONTH);
+ DO(LOAD_YEAR);
+ DO(LOAD_WEEKDAY);
+ DO(LOAD_WEEKNUM);
+ DO(STORE_DAY);
+ DO(STORE_MONTH);
+ DO(STORE_YEAR);
+ DO(DATE_ADD);
+ DO(DATE_SUB);
+ DO(DATE_DIFF);
+ DO(TODAY);
+ DO(EQ);
+ DO(LT);
+ DO(NEG);
}
#undef DO
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()