diff options
Diffstat (limited to 'src/codegen.c')
-rw-r--r-- | src/codegen.c | 139 |
1 files changed, 39 insertions, 100 deletions
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(); |