aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-18 20:35:09 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-18 20:35:09 +0200
commit21d32fc70fbf1832b234340e313cf9400740b161 (patch)
tree75f6e123b82c897c12f2ab108878655927b2dce8
parentb17095a1262d2a8fa453ad70acab504bdddc4d6b (diff)
More code to codegen
-rw-r--r--src/analyzer.c16
-rw-r--r--src/codegen.c139
-rw-r--r--src/main.c2
3 files changed, 52 insertions, 105 deletions
diff --git a/src/analyzer.c b/src/analyzer.c
index fe23e50..a77da67 100644
--- a/src/analyzer.c
+++ b/src/analyzer.c
@@ -85,10 +85,13 @@ fwdnode(struct ast ast, idx_t_ i)
i = ast.kids[i].lhs == AST_EMPTY ? i + 1 : ast.kids[i].rhs;
break;
case ASTDECL:
+ i = ast.kids[i].rhs == AST_EMPTY ? ast.kids[i].lhs
+ : ast.kids[i].rhs;
+ break;
case ASTRET:
if (ast.kids[i].rhs == AST_EMPTY)
return i + 1;
- i++;
+ i = ast.kids[i].rhs;
break;
case ASTBINADD:
case ASTBINSUB:
@@ -159,12 +162,17 @@ typechkdecl(struct typechkctx ctx, struct evstack evs, struct type *types,
struct type ltype, rtype;
ltype.kind = TYPE_UNSET;
- assert(p.rhs != AST_EMPTY);
+ assert(p.lhs != AST_EMPTY || p.rhs != AST_EMPTY);
+
+ idx_t_ ni;
if (p.lhs != AST_EMPTY)
ltype = *typegrab(ast, toks, p.lhs);
- idx_t_ ni = typechkexpr(ctx, evs, types, ast, toks, p.rhs);
- rtype = types[p.rhs];
+ if (p.rhs != AST_EMPTY) {
+ ni = typechkexpr(ctx, evs, types, ast, toks, p.rhs);
+ rtype = types[p.rhs];
+ } else
+ ni = fwdnode(ast, i);
if (ltype.kind == TYPE_UNSET)
ltype = rtype;
diff --git a/src/codegen.c b/src/codegen.c
index 1a0bb53..4253bd4 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -12,11 +12,8 @@
#include "parser.h"
#include "types.h"
-static size_t codegenstmt(LLVMBuilderRef, LLVMValueRef *, struct type *,
- struct ast, struct lexemes, size_t)
- __attribute__((nonnull));
-static size_t codegenexpr(LLVMBuilderRef, LLVMValueRef *, struct type *,
- struct ast, struct lexemes, size_t, LLVMValueRef *)
+static size_t codegenexpr(LLVMBuilderRef, struct type *, struct ast,
+ struct lexemes, size_t, LLVMValueRef *)
__attribute__((nonnull));
static LLVMTypeRef type2llvm(struct type);
@@ -27,81 +24,41 @@ codegen(const char *file, struct type *types, struct ast ast,
{
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));
+ LLVMBuilderRef bob = LLVMCreateBuilder();
for (size_t i = 0; i < ast.len;) {
- switch (ast.kinds[i]) {
- case ASTDECL: {
- /* TODO: Temporary allocator */
- struct strview sv = toks.strs[ast.lexemes[i]];
- 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, T, name);
- i = codegenexpr(builder, declvals, types, ast, toks, ast.kids[i].rhs, &val);
- LLVMSetInitializer(globl, LLVMConstTrunc(val, T));
- free(name);
- break;
- }
- case ASTCDECL: {
- idx_t_ expr = ast.kids[i].rhs;
- if (ast.kinds[expr] != ASTFN) {
- assert(!"not implemented");
- __builtin_unreachable();
- }
+ // LLVMValueRef val;
+ assert(ast.kinds[i] == ASTDECL || ast.kinds[i] == ASTCDECL);
+ // if (ast.kids[i].rhs != AST_EMPTY && types[ast.kids[i].rhs] ==
+ // TYPE_FN) codegenfn(builder, types, ast, toks, i, &val); else
+ // codegenexpr(builder, types, ast, toks, i, &val);
- idx_t_ proto = ast.kids[expr].lhs, body = ast.kids[expr].rhs;
-
- LLVMTypeRef ret;
- LLVMTypeRef params[] = {0};
-
- if (ast.kids[proto].rhs == AST_EMPTY)
- ret = LLVMVoidType();
- else {
- size_t type = ast.kids[proto].rhs;
- struct strview sv = toks.strs[ast.lexemes[type]];
-
- /* Very very temporary! */
- if (strncmp("int", sv.p, sv.len) == 0)
- ret = LLVMInt64Type();
- else if (strncmp("i32", sv.p, sv.len) == 0)
- ret = LLVMInt32Type();
- else if (strncmp("u32", sv.p, sv.len) == 0)
- ret = LLVMInt32Type();
- else if (strncmp("i128", sv.p, sv.len) == 0)
- ret = LLVMInt128Type();
- else
- err("codegen: Unknown type: %.*s", (int)sv.len, sv.p);
- }
+ /* TODO: Temporary allocator */
+ struct strview sv = toks.strs[ast.lexemes[i]];
+ char *name = bufalloc(NULL, sv.len + 1, 1);
+ ((uchar *)memcpy(name, sv.p, sv.len))[sv.len] = 0;
- LLVMTypeRef fnproto = LLVMFunctionType(ret, params, 0, false);
+ LLVMValueRef globl, init;
+ LLVMTypeRef vartype = type2llvm(types[i]);
- struct strview sv = toks.strs[ast.lexemes[i]];
- char *fnname = bufalloc(NULL, sv.len + 1, 1);
- ((char *)memcpy(fnname, sv.p, sv.len))[sv.len] = 0;
+ globl = LLVMAddGlobal(mod, vartype, name);
+ LLVMSetGlobalConstant(globl, ast.kinds[i] == ASTCDECL);
- LLVMValueRef fn = LLVMAddFunction(mod, fnname, fnproto);
- LLVMBasicBlockRef entry = LLVMAppendBasicBlock(fn, "entry");
- LLVMPositionBuilderAtEnd(builder, entry);
+ if (ast.kids[i].rhs != AST_EMPTY) {
+ i = codegenexpr(bob, types, ast, toks, ast.kids[i].rhs, &init);
+ init = LLVMConstTrunc(init, vartype);
+ } else {
+ init = LLVMConstNull(vartype);
+ i += 2;
+ }
- free(fnname);
+ LLVMSetInitializer(globl, init);
+ LLVMSetLinkage(globl, LLVMPrivateLinkage);
- for (i = ast.kids[body].lhs; i <= ast.kids[body].rhs;)
- i = codegenstmt(builder, declvals, types, ast, toks, i);
- break;
- }
- default:
- err("codegen: Expected declaration");
- }
+ free(name);
}
- free(declvals);
- LLVMDisposeBuilder(builder);
+ LLVMDisposeBuilder(bob);
char *error = NULL;
LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
@@ -112,31 +69,9 @@ codegen(const char *file, struct type *types, struct ast ast,
}
size_t
-codegenstmt(LLVMBuilderRef builder, LLVMValueRef *declvals, struct type *types,
- struct ast ast, struct lexemes toks, size_t i)
+codegenexpr(LLVMBuilderRef builder, struct type *types, struct ast ast,
+ struct lexemes toks, size_t i, LLVMValueRef *v)
{
- switch (ast.kinds[i]) {
- case ASTRET:
- if (ast.kids[i].rhs == AST_EMPTY) {
- LLVMBuildRetVoid(builder);
- return i + 1;
- }
- LLVMValueRef v;
- i = codegenexpr(builder, declvals, types, ast, toks, ast.kids[i].rhs,
- &v);
- LLVMBuildRet(builder, v);
- return i;
- }
-
- assert(!"unreachable");
- __builtin_unreachable();
-}
-
-size_t
-codegenexpr(LLVMBuilderRef builder, LLVMValueRef *declvals, struct type *types,
- struct ast ast, struct lexemes toks, size_t i, LLVMValueRef *v)
-{
- (void)declvals;
(void)builder;
switch (ast.kinds[i]) {
case ASTNUMLIT: {
@@ -156,17 +91,18 @@ codegenexpr(LLVMBuilderRef builder, LLVMValueRef *declvals, struct type *types,
*v = LLVMConstIntOfStringAndSize(type2llvm(types[i]), p, len, 10);
free(p);
- } else
+ } else {
*v = LLVMConstIntOfStringAndSize(type2llvm(types[i]), sv.p, sv.len,
10);
+ }
return i + 1;
}
case ASTIDENT:
err("codegen: %s: Not implemented", __func__);
+ default:
+ assert(!"unreachable");
+ __builtin_unreachable();
}
-
- assert(!"unreachable");
- __builtin_unreachable();
}
LLVMTypeRef
@@ -178,15 +114,18 @@ type2llvm(struct type t)
assert(!"codegen: Hit TYPE_UNSET or TYPE_CHECKING");
__builtin_unreachable();
case TYPE_FN:
+ err("codegen: %s: Not implemented", __func__);
case TYPE_F16:
+ return LLVMHalfType();
case TYPE_F32:
+ return LLVMFloatType();
case TYPE_F64:
- err("codegen: %s: Not implemented", __func__);
+ return LLVMDoubleType();
case TYPE_NUM:
assert(t.issigned);
/* TODO: Arbitrary precision */
if (t.size == 0)
- return LLVMInt128Type();
+ return LLVMInt64Type();
return LLVMIntType((unsigned)t.size * 8);
default:
__builtin_unreachable();
diff --git a/src/main.c b/src/main.c
index a61b860..2cfc1d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,7 +30,7 @@ main(int argc, char **argv)
struct lexemes toks = lexstring(src, srclen);
struct ast ast = parsetoks(toks);
struct type *types = analyzeast(ast, toks);
- // codegen(argv[1], types, ast, toks);
+ codegen(argv[1], types, ast, toks);
#if DEBUG
free(types);