From 79d80d2d8905b62a30f8856b86811ed932c00c45 Mon Sep 17 00:00:00 2001
From: Kimplul <kimi.h.kuparinen@gmail.com>
Date: Sun, 5 Jan 2025 18:26:26 +0200
Subject: fix procedure/function compilation

+ Add fib example
---
 src/lower.c | 42 ++++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 22 deletions(-)

(limited to 'src')

diff --git a/src/lower.c b/src/lower.c
index 5e0e41e..cdede46 100644
--- a/src/lower.c
+++ b/src/lower.c
@@ -36,9 +36,7 @@
  * now */
 static struct vec fns = {0};
 
-/* locs use global 0 to mean unitialized and global 1 is reserved as null_loc(),
- * so skip two first globals */
-static size_t globals = 2;
+static size_t globals = 1;
 
 /* get register/stack slot for AST node */
 #define regno(x) ((x)->l.s)
@@ -59,18 +57,17 @@ static void lower_list(struct fn *f, struct ast *l)
 
 static struct loc build_local_loc(size_t idx)
 {
-	return (struct loc){.g = 0, .s = idx};
+	return (struct loc){.g = -1, .s = idx};
 }
 
 static struct loc build_global_loc(size_t idx)
 {
-	return (struct loc){.g = idx, .s = 0};
+	return (struct loc){.g = idx, .s = -1};
 }
 
 static struct loc null_loc()
 {
-	/* don't exactly love this but I guess it works */
-	return build_global_loc(1);
+	return (struct loc){.g = -1, .s = -1};
 }
 
 static enum ejit_type ejit_type_from(enum type_kind t)
@@ -87,9 +84,9 @@ static enum ejit_type ejit_type_from(enum type_kind t)
 
 static void put(struct fn *f, struct loc l)
 {
-	assert(l.g != 1);
+	assert(l.g != 0);
 	/* local values are already where they should be */
-	if (l.g <= 1)
+	if (l.g == -1)
 		return;
 
 	/* something like this I think, should still check the type width */
@@ -98,8 +95,8 @@ static void put(struct fn *f, struct loc l)
 
 static void get(struct fn *f, struct loc l)
 {
-	assert(l.g != 1);
-	if (l.g <= 1)
+	assert(l.g != 0);
+	if (l.g == -1)
 		return;
 
 	ejit_ldxi_u64(f->f, EJIT_GPR(l.s), EJIT_GPR(0), l.g * sizeof(int64_t));
@@ -321,8 +318,8 @@ static void get_id_loc(struct fn *f, struct ast *n)
 	/* using ast nodes/scope lookup as convenient way to store variable ->
 	 * location mappings */
 	n->l = exists->l;
-	assert(n->l.g != 1);
-	if (n->l.g > 1) {
+	assert(n->l.g != 0);
+	if (n->l.g != -1) {
 		/* global variables should get loaded to the stack for handling */
 		n->l.s = f->sp;
 	}
@@ -538,7 +535,10 @@ static void lower_proc_call(struct fn *f, struct ast *c)
 	}
 
 	struct ast *def = file_scope_find(c->scope, proc_call_id(c));
-	ejit_calli(f->f, (struct ejit_func *)def->l.s, count, args);
+	struct fn *target = vec_at(&fns, def->l.s);
+	assert(target);
+
+	ejit_calli(f->f, target->f, count, args);
 
 	f->sp -= count;
 
@@ -562,9 +562,10 @@ static void lower_func_call(struct fn *f, struct ast *c)
 	}
 
 	struct ast *def = file_scope_find(c->scope, func_call_id(c));
-	/* note, def->l.s is not actually a register, rather a pointer to the
-	 * struct ejit_func */
-	ejit_calli(f->f, (struct ejit_func *)def->l.s, count, args);
+	struct fn *target = vec_at(&fns, def->l.s);
+	assert(target);
+
+	ejit_calli(f->f, target->f, count, args);
 
 	f->sp -= count;
 
@@ -957,10 +958,7 @@ static void lower_global_var(struct fn *f, struct ast *n) {
 
 static void add_proc(struct ast *n) {
 	size_t idx = vec_len(&fns);
-	/* global locs are effectively just indexes, so this is a nifty way to
-	 * encode the procedure index into the AST for later use by
-	 * lower_proc_call and so on */
-	n->l = build_global_loc(idx);
+	n->l = build_local_loc(idx);
 	struct fn f = {.name = proc_id(n),
 		       .idx = idx,
 		       .sp = 0,
@@ -971,7 +969,7 @@ static void add_proc(struct ast *n) {
 
 static void add_func(struct ast *n) {
 	size_t idx = vec_len(&fns);
-	n->l = build_global_loc(idx);
+	n->l = build_local_loc(idx);
 	struct fn f = {.name = func_id(n),
 		       .idx = idx,
 		       .sp = 0,
-- 
cgit v1.2.3