aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.c
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-18 14:33:06 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-18 14:33:06 +0200
commitf883a252b108bd9c4fadb1a78daec85440cc7f08 (patch)
tree5feb4a1f26b717e7a7f83393058a2d13344acdbd /src/codegen.c
parentcc8060636ee0a341f68db9ad8fda4ebaabaf49cf (diff)
Do more work on the typechecker and compiler
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c84
1 files changed, 62 insertions, 22 deletions
diff --git a/src/codegen.c b/src/codegen.c
index a3a1b87..a5d0f46 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -12,18 +12,25 @@
#include "parser.h"
#include "types.h"
-static size_t codegenstmt(LLVMBuilderRef, struct ast, struct lexemes,
- size_t);
-static size_t codegenexpr(LLVMBuilderRef, struct ast, struct lexemes,
- size_t, LLVMValueRef *)
+static size_t codegenstmt(LLVMBuilderRef, LLVMValueRef *, struct ast,
+ struct lexemes, size_t);
+static size_t codegenexpr(LLVMBuilderRef, LLVMValueRef *, struct ast,
+ struct lexemes, size_t, LLVMValueRef *)
__attribute__((nonnull));
+static LLVMTypeRef type2llvm(struct type);
+
void
-codegen(struct ast ast, struct lexemes toks)
+codegen(const char *file, struct type *types, struct ast ast,
+ struct lexemes toks)
{
LLVMModuleRef mod = LLVMModuleCreateWithName("oryx");
+ LLVMSetSourceFileName(mod, file, strlen(file));
LLVMBuilderRef builder = LLVMCreateBuilder();
+ LLVMValueRef *declvals = bufalloc(NULL, ast.len, sizeof(*declvals));
+ memset(declvals, 0, ast.len * sizeof(*declvals));
+
for (size_t i = 0; i < ast.len;) {
switch (ast.kinds[i]) {
case ASTDECL: {
@@ -32,10 +39,11 @@ codegen(struct ast ast, struct lexemes toks)
char *name = bufalloc(NULL, sv.len + 1, 1);
((uchar *)memcpy(name, sv.p, sv.len))[sv.len] = 0;
+ LLVMTypeRef T = type2llvm(types[i]);
LLVMValueRef globl, val;
- globl = LLVMAddGlobal(mod, LLVMInt64Type(), name);
- i = codegenexpr(builder, ast, toks, ast.kids[i].rhs, &val);
- LLVMSetInitializer(globl, val);
+ globl = LLVMAddGlobal(mod, T, name);
+ i = codegenexpr(builder, declvals, ast, toks, ast.kids[i].rhs, &val);
+ LLVMSetInitializer(globl, LLVMConstTrunc(val, T));
free(name);
break;
}
@@ -77,7 +85,7 @@ codegen(struct ast ast, struct lexemes toks)
free(fnname);
for (i = ast.kids[body].lhs; i <= ast.kids[body].rhs;)
- i = codegenstmt(builder, ast, toks, i);
+ i = codegenstmt(builder, declvals, ast, toks, i);
break;
}
default:
@@ -85,6 +93,7 @@ codegen(struct ast ast, struct lexemes toks)
}
}
+ free(declvals);
LLVMDisposeBuilder(builder);
char *error = NULL;
@@ -96,8 +105,8 @@ codegen(struct ast ast, struct lexemes toks)
}
size_t
-codegenstmt(LLVMBuilderRef builder, struct ast ast, struct lexemes toks,
- size_t i)
+codegenstmt(LLVMBuilderRef builder, LLVMValueRef *declvals, struct ast ast,
+ struct lexemes toks, size_t i)
{
switch (ast.kinds[i]) {
case ASTRET:
@@ -106,7 +115,7 @@ codegenstmt(LLVMBuilderRef builder, struct ast ast, struct lexemes toks,
return i + 1;
}
LLVMValueRef v;
- i = codegenexpr(builder, ast, toks, ast.kids[i].rhs, &v);
+ i = codegenexpr(builder, declvals, ast, toks, ast.kids[i].rhs, &v);
LLVMBuildRet(builder, v);
return i;
}
@@ -116,8 +125,8 @@ codegenstmt(LLVMBuilderRef builder, struct ast ast, struct lexemes toks,
}
size_t
-codegenexpr(LLVMBuilderRef builder, struct ast ast, struct lexemes toks,
- size_t i, LLVMValueRef *v)
+codegenexpr(LLVMBuilderRef builder, LLVMValueRef *declvals, struct ast ast,
+ struct lexemes toks, size_t i, LLVMValueRef *v)
{
(void)builder;
switch (ast.kinds[i]) {
@@ -125,20 +134,51 @@ codegenexpr(LLVMBuilderRef builder, struct ast ast, struct lexemes toks,
/* TODO: Arbitrary precision? */
struct strview sv = toks.strs[ast.lexemes[i]];
+ bool has_sep = memchr(sv.p, '\'', sv.len) != NULL;
+
/* TODO: Temporary one-time-use allocator? */
- size_t len = 0;
- char *p = bufalloc(NULL, sv.len, 1);
- for (size_t i = 0; i < sv.len; i++) {
- if (sv.p[i] != '\'')
- p[len++] = sv.p[i];
- }
+ if (has_sep) {
+ size_t len = 0;
+ char *p = bufalloc(NULL, sv.len, 1);
+ for (size_t i = 0; i < sv.len; i++) {
+ if (sv.p[i] != '\'')
+ p[len++] = sv.p[i];
+ }
- *v = LLVMConstIntOfStringAndSize(LLVMInt64Type(), p, len, 10);
- free(p);
+ *v = LLVMConstIntOfStringAndSize(LLVMInt64Type(), p, len, 10);
+ free(p);
+ } else
+ *v = LLVMConstIntOfStringAndSize(LLVMInt64Type(), sv.p, sv.len, 10);
return i + 1;
}
+ case ASTIDENT:
+ err("codegen: %s: Not implemented", __func__);
}
assert(!"unreachable");
__builtin_unreachable();
}
+
+LLVMTypeRef
+type2llvm(struct type t)
+{
+ switch (t.kind) {
+ case TYPE_UNSET:
+ case TYPE_CHECKING:
+ assert(!"codegen: Hit TYPE_UNSET or TYPE_CHECKING");
+ __builtin_unreachable();
+ case TYPE_FN:
+ case TYPE_F16:
+ case TYPE_F32:
+ case TYPE_F64:
+ err("codegen: %s: Not implemented", __func__);
+ case TYPE_NUM:
+ assert(t.issigned);
+ /* TODO: Arbitrary precision */
+ if (t.size == 0)
+ t.size = 8;
+ return LLVMIntType(t.size * 8);
+ default:
+ __builtin_unreachable();
+ }
+}