Author | Jakob Wakeling <[email protected]> |
Date | 2022-03-29 00:53:47 |
Commit | 30b1fa8700e75102ebe5aa17d1d41b0a95fb40af |
Parent | 6d07b21638d06401c3fd9d67f8e868958cb9443e |
llvm: Implement variables with a temporary hack
Diffstat
M | README.md | | | 2 | +- |
A | examples/dual.g | | | 2 | ++ |
M | src/llvm.c | | | 14 | ++++++++++++-- |
M | src/main.c | | | 2 | +- |
M | src/parse.c | | | 23 | ++++++++++++++++++----- |
M | src/parse.h | | | 2 | +- |
M | src/symbol.c | | | 4 | +++- |
7 files changed, 38 insertions, 11 deletions
diff --git a/README.md b/README.md index b2d1210..ade1857 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ command. The second command will output an executable file, *a.out* by default. > Not all todo items will necesarilly be implemented - [ ] Implement main entrypoint -- [ ] Implement procedure definitions +- [ ] Implement procedure declarations - [ ] Implement procedure calls - [ ] Implement variable assignments - [x] Implement integers diff --git a/examples/dual.g b/examples/dual.g new file mode 100644 index 0000000..81a3d6b --- /dev/null +++ b/examples/dual.g @@ -0,0 +1,2 @@ +main :: proc() -> s64 { var := 42; return var; } +test :: proc() -> s64 { return 2; } diff --git a/src/llvm.c b/src/llvm.c index 7174a44..e4aa6d4 100644 --- a/src/llvm.c +++ b/src/llvm.c @@ -5,6 +5,7 @@ #include "llvm.h" #include "parse.h" +#include "symbol.h" #include "type.h" #include "util/error.h" #include "util/util.h" @@ -97,6 +98,7 @@ static LLVMValueRef llvm_stmt_compound(ast *a) { 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 */ @@ -112,8 +114,14 @@ static LLVMValueRef llvm_stmt_decl(ast *a) { llvm_expr_proc(C[0]); } else { - LLVMValueRef v = LLVMAddGlobal(llvm_module, llvm_type(C[0]->t), a->s); - LLVMSetInitializer(v, llvm_int(C[0])); + 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; + } + else { + LLVMValueRef v = LLVMBuildAlloca(llvm_builder, llvm_type(C[0]->t), a->s); + LLVMBuildStore(llvm_builder, llvm_int(C[0]), v); ref = v; + } } return NULL; @@ -143,7 +151,8 @@ static LLVMValueRef llvm_stmt_for(ast *a) { static LLVMValueRef llvm_expr(ast *a) { if (a->k == AK_PROC) { return llvm_expr_proc(a); } if (a->k == AK_INT) { return llvm_int(a); } - else { error(2, "_expr unknown kind"); } + if (a->k == AK_VAR) { return LLVMBuildLoad2(llvm_builder, LLVMIntType(64), ref, "var"); } + else { error(2, "_expr unknown kind %s", ast_ks[a->k]); } } /* Generate IR for a procedure. */ diff --git a/src/main.c b/src/main.c index 480721d..73e325f 100644 --- a/src/main.c +++ b/src/main.c @@ -22,7 +22,7 @@ static struct lop lops[] = { }; static char *aw[] = { - "g", "--debug-parse", "/home/deus/Workspace/G/examples/main.g", NULL + "g", "--debug-parse", "/home/deus/Workspace/G/examples/dual.g", NULL }; static void hlp(void); diff --git a/src/parse.c b/src/parse.c index 3555ea4..c79afa4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -22,7 +22,7 @@ char *ast_ks[] = { "AK_EXPR", "AK_PROC", - "AK_INT", + "AK_VAR", "AK_INT", }; static ast *parse_stmt(lex *l, syt *st); @@ -36,7 +36,7 @@ static ast *parse_stmt_for(lex *l, syt *st); static ast *parse_expr(lex *l, syt *st); static ast *parse_expr_proc(lex *l, syt *st); -static ast *parse_int(lex *l); +static ast *parse_int(lex *l, syt *st); /* Initialise an AST node. */ ast *ast_init(void) { @@ -85,7 +85,7 @@ static ast *parse_stmt_compound(lex *l, syt *st) { lex_kind(l, TK_LBRACE); ast *a = ast_init(); a->k = AK_COMP; - for (; T.k != TK_EOF && T.k != TK_RBRACE;) { ast_push(a, parse_stmt(l, st)); } + for (; T.k != TK_EOF && T.k != TK_RBRACE;) { ast_push(a, parse_stmt(l, &a->st)); } lex_kind(l, TK_RBRACE); return a; } @@ -176,7 +176,17 @@ static ast *parse_stmt_for(lex *l, syt *st) { /* Parse an expression. */ static ast *parse_expr(lex *l, syt *st) { if (T.k == TK_PROC) { return parse_expr_proc(l, st); } - if (T.k == TK_INT) { return parse_int(l); } + if (T.k == TK_INT) { return parse_int(l, st); } + if (T.k == TK_ID) { + ast *a = ast_init(); tok t = lex_kind(l, TK_ID); + a->k = AK_VAR; a->ln = t.ln; a->cl = t.cl; + + a->t = syt_search_h(st, t.h, t.s).t; + + if (!(a->s = strdup(t.s))) { error(1, "%s", SERR); } + + return a; + } else { error(1, "PARSE_EXPR %s", tok_ks[T.k]); } } @@ -210,10 +220,12 @@ static ast *parse_expr_proc(lex *l, syt *st) { } /* Parse an interger. */ -static ast *parse_int(lex *l) { +static ast *parse_int(lex *l, syt *st) { ast *a = ast_init(); tok t = lex_kind(l, TK_INT); a->k = AK_INT; a->ln = t.ln; a->cl = t.cl; + a->t = &types[TY_U64]; /* TODO properly determine type */ + if (!(a->s = strdup(t.s))) { error(1, "%s", SERR); } if (!(a->v = val_parse_int(t.s)).k) { error(1, "%s: %s", t.s, SERR); } diff --git a/src/parse.h b/src/parse.h index 67eaab7..3900784 100644 --- a/src/parse.h +++ b/src/parse.h @@ -19,7 +19,7 @@ typedef enum { AK_EXPR, AK_PROC, - AK_INT, + AK_VAR, AK_INT, } ast_k; /* k: kind, ln: line, cl: column */ diff --git a/src/symbol.c b/src/symbol.c index 43ef8e1..e4ff063 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -10,6 +10,7 @@ 'typeof' operator will become standard in C23. */ +#include "parse.h" #include "symbol.h" #include "util/util.h" @@ -159,7 +160,7 @@ sym syt_search_h(syt *st, u64 h, char *k) { /* Print a basic representation of a map to stdout. */ void syt_print(syt *st) { for (UINT i = 0; i < st->ac; i += 1) if (st->a[i].h != 0) { - printf("%s -> %s\n", st->a[i].k, "TODO"); + printf("%s -> %s\n", st->a[i].k, st->a[i].v.a->c.a[0]->t->s); } }