aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.c
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-19 20:16:49 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-19 20:16:49 +0200
commitcb358312c86c6fe13631fb4022cefccee8bba91e (patch)
tree6bec6a2a98a6df93084b39f6a2e51e163764e9fc /src/codegen.c
parent4486b6eccd96784cc9423b41e5b6dce7c9a3d740 (diff)
Various parser fixes
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c120
1 files changed, 87 insertions, 33 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 4253bd4..504291a 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -12,67 +13,120 @@
#include "parser.h"
#include "types.h"
-static size_t codegenexpr(LLVMBuilderRef, struct type *, struct ast,
+struct cgctx {
+ LLVMModuleRef mod;
+ LLVMBuilderRef bob;
+ struct strview namespace;
+};
+
+static size_t codegendecl(struct cgctx, struct type *, struct ast,
+ struct lexemes, size_t)
+ __attribute__((nonnull));
+static size_t codegenexpr(struct cgctx, struct type *, struct ast,
struct lexemes, size_t, LLVMValueRef *)
__attribute__((nonnull));
static LLVMTypeRef type2llvm(struct type);
+/* TODO: Don’t do this? */
+#define lengthof(xs) (sizeof(xs) / sizeof(*(xs)))
+static struct {
+ struct strview key;
+ LLVMValueRef val;
+} constants[1024];
+static size_t constcnt;
+
void
codegen(const char *file, struct type *types, struct ast ast,
struct lexemes toks)
{
- LLVMModuleRef mod = LLVMModuleCreateWithName("oryx");
- LLVMSetSourceFileName(mod, file, strlen(file));
- LLVMBuilderRef bob = LLVMCreateBuilder();
+ struct cgctx ctx = {0};
+ ctx.mod = LLVMModuleCreateWithName("oryx");
+ ctx.bob = LLVMCreateBuilder();
+ LLVMSetSourceFileName(ctx.mod, file, strlen(file));
for (size_t i = 0; i < ast.len;) {
// 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);
+ i = codegendecl(ctx, types, ast, toks, i);
/* 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;
-
- LLVMValueRef globl, init;
- LLVMTypeRef vartype = type2llvm(types[i]);
+ // 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;
+ //
+ // LLVMValueRef globl, init;
+ // LLVMTypeRef vartype = type2llvm(types[i]);
+ //
+ // globl = LLVMAddGlobal(mod, vartype, name);
+ // LLVMSetGlobalConstant(globl, ast.kinds[i] == ASTCDECL);
+ //
+ // 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 = fwdnode(ast, i);
+ // }
+ //
+ // LLVMSetInitializer(globl, init);
+ // LLVMSetLinkage(globl, LLVMPrivateLinkage);
+ //
+ // free(name);
+ }
- globl = LLVMAddGlobal(mod, vartype, name);
- LLVMSetGlobalConstant(globl, ast.kinds[i] == ASTCDECL);
+ LLVMDisposeBuilder(ctx.bob);
- 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;
- }
+ char *error = NULL;
+ LLVMVerifyModule(ctx.mod, LLVMAbortProcessAction, &error);
+ LLVMDisposeMessage(error);
- LLVMSetInitializer(globl, init);
- LLVMSetLinkage(globl, LLVMPrivateLinkage);
+ LLVMDumpModule(ctx.mod);
+ LLVMDisposeModule(ctx.mod);
+}
- free(name);
+size_t
+codegendecl(struct cgctx ctx, struct type *types, struct ast ast,
+ struct lexemes toks, size_t i)
+{
+ struct strview ident = toks.strs[ast.lexemes[i]];
+
+ char *name;
+ if (ctx.namespace.len != 0) {
+ size_t namelen = ident.len + ctx.namespace.len + 1;
+ name = bufalloc(NULL, namelen + 1, 1);
+ sprintf(name, "%.*s.%.*s", (int)ctx.namespace.len, ctx.namespace.p,
+ (int)ident.len, ident.p);
+ } else {
+ name = bufalloc(NULL, ident.len + 1, 1);
+ memcpy(name, ident.p, ident.len);
+ name[ident.len] = 0;
}
- LLVMDisposeBuilder(bob);
+ LLVMValueRef val;
+ LLVMTypeRef vartype = type2llvm(types[i]);
- char *error = NULL;
- LLVMVerifyModule(mod, LLVMAbortProcessAction, &error);
- LLVMDisposeMessage(error);
+ if (ast.kids[i].rhs != AST_EMPTY) {
+ i = codegenexpr(ctx, types, ast, toks, ast.kids[i].rhs, &val);
+ val = LLVMConstTrunc(val, vartype);
+ } else {
+ i = fwdnode(ast, i);
+ val = LLVMConstNull(vartype);
+ }
+
+ LLVMValueRef globl = LLVMAddGlobal(ctx.mod, vartype, name);
+ LLVMSetInitializer(globl, val);
+ LLVMSetLinkage(globl, LLVMLinkerPrivateLinkage);
- LLVMDumpModule(mod);
- LLVMDisposeModule(mod);
+ free(name);
+ return i;
}
size_t
-codegenexpr(LLVMBuilderRef builder, struct type *types, struct ast ast,
+codegenexpr(struct cgctx ctx, struct type *types, struct ast ast,
struct lexemes toks, size_t i, LLVMValueRef *v)
{
- (void)builder;
+ (void)ctx;
switch (ast.kinds[i]) {
case ASTNUMLIT: {
/* TODO: Arbitrary precision? */