diff options
Diffstat (limited to 'src/codegen.c')
-rw-r--r-- | src/codegen.c | 111 |
1 files changed, 93 insertions, 18 deletions
diff --git a/src/codegen.c b/src/codegen.c index a9e5006..4f10e61 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1,38 +1,113 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + #include <llvm-c/Analysis.h> #include <llvm-c/Core.h> +#include "alloc.h" #include "codegen.h" +#include "errors.h" + +#define AST_EMPTY ((size_t)-1) + +static size_t codegenstmt(LLVMBuilderRef, struct ast_soa, struct lexemes_soa, + size_t); +static size_t codegenexpr(LLVMBuilderRef, struct ast_soa, struct lexemes_soa, + size_t, LLVMValueRef *) + __attribute__((nonnull)); void codegen(struct ast_soa ast, struct lexemes_soa toks) { - (void)ast; - (void)toks; - - /* Create a new module */ LLVMModuleRef mod = LLVMModuleCreateWithName("oryx"); - /* Declare the function ‘sum :: (int, int) int’ */ - LLVMTypeRef param_types[] = {LLVMInt32Type(), LLVMInt32Type()}; - LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, 0); - LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); + for (size_t i = 0; i < ast.len;) { + if (ast.kinds[i] != ASTCDECL) + err("codegen: Expected constant declaration"); + + size_t expr = ast.kids[i].rhs; + if (ast.kinds[expr] != ASTFN) + assert(!"not implemented"); + + size_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]]; + + /* TODO: Make int 32bit on 32bit platforms */ + if (strncmp("int", sv.p, sv.len) == 0) + ret = LLVMInt64Type(); + else + err("codegen: Unknown type: %.*s", (int)sv.len, sv.p); + + } + + LLVMTypeRef fnproto = LLVMFunctionType(ret, params, 0, false); - /* Create an entry block, and a builder */ - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, entry); + 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; - /* Generate an ADD instruction */ - LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), - LLVMGetParam(sum, 1), "tmpadd"); - LLVMBuildRet(builder, tmp); + LLVMValueRef fn = LLVMAddFunction(mod, fnname, fnproto); + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(fn, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + + free(fnname); + + for (i = ast.kids[body].lhs; i <= ast.kids[body].rhs;) + i = codegenstmt(builder, ast, toks, i); + + LLVMDisposeBuilder(builder); + } - /* Verify that all went well and if not we abort */ char *error = NULL; LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMDumpModule(mod); +} + +size_t +codegenstmt(LLVMBuilderRef builder, struct ast_soa ast, struct lexemes_soa toks, + size_t i) +{ + switch (ast.kinds[i]) { + case ASTRET: + if (ast.kids[i].rhs == AST_EMPTY) { + LLVMBuildRetVoid(builder); + return i + 1; + } + LLVMValueRef v; + i = codegenexpr(builder, ast, toks, ast.kids[i].rhs, &v); + LLVMBuildRet(builder, v); + return i; + } + + assert(!"unreachable"); +} + +size_t +codegenexpr(LLVMBuilderRef builder, struct ast_soa ast, struct lexemes_soa toks, + size_t i, LLVMValueRef *v) +{ + (void)builder; + switch (ast.kinds[i]) { + case ASTNUMLIT: { + /* TODO: Arbitrary precision? */ + struct strview sv = toks.strs[ast.lexemes[i]]; + *v = LLVMConstIntOfStringAndSize(LLVMInt64Type(), sv.p, sv.len, 10); + return i + 1; + } + } - LLVMDisposeBuilder(builder); + assert(!"unreachable"); } |