const std = @import("std"); const ast = @import("ast.zig"); const llvm = @import("llvm.zig"); pub const Codegen = struct { allocator: *std.mem.Allocator, pub fn init(allocator: *std.mem.Allocator) Codegen { return Codegen{ .allocator = allocator }; } fn genNode( self: *Codegen, mod: llvm.LLVMModuleRef, node: *const ast.Node, ) !void { switch (node.*) { .Root => @panic("Should not have gotten Root"), .FnDecl => |decl| { const name = decl.func_name.lexeme; const name_cstr = try std.cstr.addNullByte(self.allocator, name); errdefer self.allocator.free(name_cstr); //const ret_type = decl.return_type.lexeme; var param_types = llvm.LLVMTypeList.init(self.allocator); errdefer param_types.deinit(); for (decl.params.toSlice()) |param| { try param_types.append(llvm.LLVMInt32Type()); } var ret_type = llvm.LLVMFunctionType( llvm.LLVMInt32Type(), param_types.toSlice().ptr, @intCast(c_uint, param_types.len), 0, ); var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, ret_type); var entry = llvm.LLVMAppendBasicBlock(func, c"entry"); var builder = llvm.LLVMCreateBuilder(); llvm.LLVMPositionBuilderAtEnd(builder, entry); // TODO codegen decl.body var tmp = llvm.LLVMBuildAdd( builder, llvm.LLVMGetParam(func, 0), llvm.LLVMGetParam(func, 1), c"tmp", ); _ = llvm.LLVMBuildRet(builder, tmp); std.debug.warn("cgen: fn decl done\n"); }, else => { std.debug.warn("got unhandled Node {}\n", node.*); unreachable; }, } } pub fn gen(self: *Codegen, root: *ast.Node) !void { std.debug.warn("cgen: start gen\n"); var mod = llvm.LLVMModuleCreateWithName(c"awoo"); defer llvm.LLVMDisposeModule(mod); std.debug.warn("cgen: got mod\n"); for (root.Root.toSlice()) |child| { std.debug.warn("cgen: gen child {}\n", child); try self.genNode(mod, &child); } std.debug.warn("cgen: done\n"); var err: ?[*]u8 = null; _ = llvm.LLVMVerifyModule( mod, llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, &err, ); llvm.LLVMDisposeMessage(err); } };