From 21d32fc70fbf1832b234340e313cf9400740b161 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Tue, 18 Jun 2024 20:35:09 +0200 Subject: More code to codegen --- src/analyzer.c | 16 +++++-- src/codegen.c | 139 ++++++++++++++++----------------------------------------- src/main.c | 2 +- 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); -- cgit v1.2.3