G

G Programming Language
git clone http://git.omkov.net/G
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2022-04-13 13:41:59
Commita019f098d23d9dfeeb80e1d0f814e9bcd517e9a4
Parenta47f6532e4d1c1d6af1d4c443e4e0d28f2bbd5d9

Remove LLVM variable hack

Diffstat

M src/llvm.c | 73 +++++++++++++++++++++++++++++++++++++++++++------------------------------
M src/parse.h | 4 ++++
M src/symbol.c | 3 ++-

3 files changed, 49 insertions, 31 deletions

diff --git a/src/llvm.c b/src/llvm.c
index e4aa6d4..61ded72 100644
--- a/src/llvm.c
+++ b/src/llvm.c
@@ -23,16 +23,16 @@ static LLVMContextRef llvm_context = NULL;
 static LLVMModuleRef  llvm_module  = NULL;
 static LLVMBuilderRef llvm_builder = NULL;
 
-static LLVMValueRef llvm_stmt(ast *a);
-static LLVMValueRef llvm_stmt_compound(ast *a);
-static LLVMValueRef llvm_stmt_decl(ast *a);
-static LLVMValueRef llvm_stmt_expr(ast *a);
-static LLVMValueRef llvm_stmt_return(ast *a);
-static LLVMValueRef llvm_stmt_if(ast *a);
-static LLVMValueRef llvm_stmt_for(ast *a);
+static LLVMValueRef llvm_stmt(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_compound(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_decl(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_expr(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_return(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_if(ast *a, syt *st);
+static LLVMValueRef llvm_stmt_for(ast *a, syt *st);
 
-static LLVMValueRef llvm_expr(ast *a);
-static LLVMValueRef llvm_expr_proc(ast *a);
+static LLVMValueRef llvm_expr(ast *a, syt *st);
+static LLVMValueRef llvm_expr_proc(ast *a, syt *st);
 
 static LLVMValueRef llvm_int(ast *a);
 
@@ -40,6 +40,7 @@ static inline void llvm_init(void);
 static inline void llvm_free(void);
 static LLVMTypeRef llvm_type(type *t);
 
+#define A (*a)
 #define C (a->c.a) /* AST child shorthand "C[i]" */
 
 /* Generate IR from an AST with LLVM. */
@@ -47,7 +48,7 @@ void llvm(ast *a) {
 	llvm_init();
 
 	/* Generate IR for all child nodes */
-	for (UINT i = 0; i < a->c.al; i += 1) { llvm_stmt_decl(a->c.a[i]); }
+	for (UINT i = 0; i < a->c.al; i += 1) { llvm_stmt_decl(a->c.a[i], &a->st); }
 
 	if (LLVMWriteBitcodeToFile(llvm_module, "llvm.bc")) {
 		error(2, "LLVMWriteBitcodeToFile failure");
@@ -80,28 +81,29 @@ void llvm(ast *a) {
 }
 
 /* Generate IR for a statement. */
-static LLVMValueRef llvm_stmt(ast *a) {
+static LLVMValueRef llvm_stmt(ast *a, syt *st) {
 	switch (a->k) {
-	case AK_COMP:   { return llvm_stmt_compound(a); } break;
-	case AK_DECL:   { return llvm_stmt_decl(a);     } break;
-	case AK_RETURN: { return llvm_stmt_return(a);   } break;
-	case AK_IF:     { return llvm_stmt_if(a);       } break;
-	case AK_FOR:    { return llvm_stmt_for(a);      } break;
+	case AK_COMP:   { return llvm_stmt_compound(a, st); } break;
+	case AK_DECL:   { return llvm_stmt_decl(a, st);     } break;
+	case AK_RETURN: { return llvm_stmt_return(a, st);   } break;
+	case AK_IF:     { return llvm_stmt_if(a, st);       } break;
+	case AK_FOR:    { return llvm_stmt_for(a, st);      } break;
 	default:        { error(2, "llvm_stmt: Unhandled AST kind %s", ast_ks[a->k]); } break;
 	}
 }
 
 /* Generate IR for a compound statement. */
-static LLVMValueRef llvm_stmt_compound(ast *a) {
-	for (UINT i = 0; i < a->c.al; i += 1) { llvm_stmt(C[i]); }
+static LLVMValueRef llvm_stmt_compound(ast *a, syt *st) {
+	assert(A.k == AK_COMP);
+	
+	for (UINT i = 0; i < a->c.al; i += 1) { llvm_stmt(C[i], &A.st); }
 
 	return NULL;
 }
 
-static LLVMValueRef ref = NULL; /* TODO fix hack */
 /* Generate IR for a declaration statement. */
-static LLVMValueRef llvm_stmt_decl(ast *a) {
-	if (a->k != AK_DECL) { error(2, "_stmt_decl != AK_DECL"); } /* DEBUG */
+static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) {
+	assert(a->k == AK_DECL);
 
 	if (C[0]->k == AK_PROC) {
 		/* TODO handle procedure arguments if present */
@@ -111,16 +113,16 @@ static LLVMValueRef llvm_stmt_decl(ast *a) {
 		LLVMBasicBlockRef bb = LLVMAppendBasicBlock(f, "entry");
 		LLVMPositionBuilderAtEnd(llvm_builder, bb);
 
-		llvm_expr_proc(C[0]);
+		llvm_expr_proc(C[0], st);
 	}
 	else {
 		if (a->p->k == AK_PROG) {
 			LLVMValueRef v = LLVMAddGlobal(llvm_module, llvm_type(C[0]->t), a->s);
-			LLVMSetInitializer(v, llvm_int(C[0])); ref = v;
+			LLVMSetInitializer(v, llvm_int(C[0])); a->llvm_v = v;
 		}
 		else {
 			LLVMValueRef v = LLVMBuildAlloca(llvm_builder, llvm_type(C[0]->t), a->s);
-			LLVMBuildStore(llvm_builder, llvm_int(C[0]), v); ref = v;
+			LLVMBuildStore(llvm_builder, llvm_int(C[0]), v); a->llvm_v = v;
 		}
 	}
 
@@ -128,36 +130,41 @@ static LLVMValueRef llvm_stmt_decl(ast *a) {
 }
 
 /* Generate IR for an expression statement. */
-static LLVMValueRef llvm_stmt_expr(ast *a) {
+static LLVMValueRef llvm_stmt_expr(ast *a, syt *st) {
 
 }
 
 /* Generate IR for a return statement. */
-static LLVMValueRef llvm_stmt_return(ast *a) {
-	return LLVMBuildRet(llvm_builder, llvm_expr(C[0]));
+static LLVMValueRef llvm_stmt_return(ast *a, syt *st) {
+	return LLVMBuildRet(llvm_builder, llvm_expr(C[0], st));
 }
 
 /* Generate IR for an if statement. */
-static LLVMValueRef llvm_stmt_if(ast *a) {
+static LLVMValueRef llvm_stmt_if(ast *a, syt *st) {
 
 }
 
 /* Generate IR for a for statement. */
-static LLVMValueRef llvm_stmt_for(ast *a) {
+static LLVMValueRef llvm_stmt_for(ast *a, syt *st) {
 
 }
 
 /* Generate IR for an expression. */
-static LLVMValueRef llvm_expr(ast *a) {
-	if (a->k == AK_PROC) { return llvm_expr_proc(a); }
+static LLVMValueRef llvm_expr(ast *a, syt *st) {
+	if (a->k == AK_PROC) { return llvm_expr_proc(a, st); }
 	if (a->k == AK_INT) { return llvm_int(a); }
-	if (a->k == AK_VAR) { return LLVMBuildLoad2(llvm_builder, LLVMIntType(64), ref, "var"); }
+	if (a->k == AK_VAR) {
+		ast *v = syt_search(st, a->s);
+		if (v == NULL) { error(2, "llvm_expr: Undefined variable %s", a->s); }
+		
+		return LLVMBuildLoad2(llvm_builder, llvm_type(v->t), v->llvm_v, v->s);
+	}
 	else { error(2, "_expr unknown kind %s", ast_ks[a->k]); }
 }
 
 /* Generate IR for a procedure. */
-static LLVMValueRef llvm_expr_proc(ast *a) {
-	return llvm_stmt_compound(C[0]);
+static LLVMValueRef llvm_expr_proc(ast *a, syt *st) {
+	return llvm_stmt_compound(C[0], st);
 }
 
 /* Generate IR for an integer. */
diff --git a/src/parse.h b/src/parse.h
index e702883..f051e2c 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -12,6 +12,8 @@
 #include "util/util.h"
 #include "value.h"
 
+#include <llvm-c/Types.h>
+
 typedef enum {
 	AK_NULL, AK_PROG, AK_PROC, AK_TYPE,
 
@@ -27,6 +29,8 @@ typedef enum {
 typedef struct ast_s {
 	ast_k k; UINT ln, cl; u64 h; char *s; type *t; val v; syt st;
 	struct ast_s *p; struct { struct ast_s **a; UINT al; } c;
+	
+	LLVMValueRef llvm_v;
 } ast;
 
 typedef struct { ast **a; UINT al; } ast_a;
diff --git a/src/symbol.c b/src/symbol.c
index e3bb6bd..4ff4d92 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -149,9 +149,9 @@ ast *syt_search_h(syt *st, u64 h, char *k) {
 	ast *sm = syt_lookup_h(&kwt, h, k);
 	if (sm != NULL) { return sm; }
 
-	for (; st->pt != NULL; st = st->pt) {
+	for (; st != NULL; st = st->pt) {
 		sm = syt_lookup_h(st, h, k);
-		if (sm->h != 0) { return sm; }
+		if (sm != NULL) { return sm; }
 	}
 
 	return NULL;