diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-06-18 14:33:06 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-06-18 14:33:06 +0200 |
commit | f883a252b108bd9c4fadb1a78daec85440cc7f08 (patch) | |
tree | 5feb4a1f26b717e7a7f83393058a2d13344acdbd /src/codegen.c | |
parent | cc8060636ee0a341f68db9ad8fda4ebaabaf49cf (diff) |
Do more work on the typechecker and compiler
Diffstat (limited to 'src/codegen.c')
-rw-r--r-- | src/codegen.c | 84 |
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(); + } +} |