From 6c3d20bbbbe775b81e247c4a617afe3237596e74 Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 20 Sep 2019 23:40:21 -0300 Subject: [PATCH] add the basics of llvm codegen --- build.zig | 2 ++ examples/hello.ry | 8 ++--- src/codegen.zig | 85 +++++++++++++++++++++++++++++++++++++++++++++++ src/llvm.zig | 26 +++++++++++++++ src/main.zig | 4 +++ 5 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/codegen.zig create mode 100644 src/llvm.zig diff --git a/build.zig b/build.zig index 2b7df4b..d7502d4 100644 --- a/build.zig +++ b/build.zig @@ -6,6 +6,8 @@ pub fn build(b: *Builder) void { exe.setBuildMode(mode); exe.install(); + exe.linkSystemLibrary("LLVM-8"); + const run_cmd = exe.run(); run_cmd.step.dependOn(b.getInstallStep()); diff --git a/examples/hello.ry b/examples/hello.ry index d7eaae6..5c23845 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -5,7 +5,7 @@ fn add(a: i32, b: i32) i32 { } // type is void by default -fn main() { - std.fmt.print("piss\n"); - std.fmt.print("2 + 2 = %d\n", add(1, 2)); -} +//fn main() { +// print("piss\n"); +// // print("2 + 2 = %d\n", add(1, 2)); +//} diff --git a/src/codegen.zig b/src/codegen.zig new file mode 100644 index 0000000..3e5661c --- /dev/null +++ b/src/codegen.zig @@ -0,0 +1,85 @@ +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); + } +}; diff --git a/src/llvm.zig b/src/llvm.zig new file mode 100644 index 0000000..8e79786 --- /dev/null +++ b/src/llvm.zig @@ -0,0 +1,26 @@ +const std = @import("std"); + +pub const llvm = @cImport({ + @cInclude("llvm-c/Core.h"); + @cInclude("llvm-c/ExecutionEngine.h"); + @cInclude("llvm-c/Target.h"); + @cInclude("llvm-c/Analysis.h"); + @cInclude("llvm-c/BitWriter.h"); +}); + +usingnamespace llvm; + +//pub const LLVMModuleRef = llvm.LLVMModuleRef; +//pub const LLVMInt32Type = llvm.LLVMInt32Type; +//pub const LLVMModuleCreateWithName = llvm.LLVMModuleCreateWithName; +//pub const LLVMFunctionType = llvm.LLVMFunctionType; +//pub const LLVMAddFunction = llvm.LLVMAddFunction; +// +//pub const LLVMBasicBlockRef = llvm.LLVMBasicBlockRef; +//pub const LLVMAppendBasicBlock = llvm.LLVMAppendBasicBlock; +// +//pub const LLVMBuilderRef = llvm.LLVMBuilderRef; +//pub const LLVMCreateBuilder = llvm.LLVMCreateBuilder; +//pub const LLVMPositionBuilderAtEnd = llvm.LLVMPositionBuilderAtEnd; + +pub const LLVMTypeList = std.ArrayList(llvm.LLVMTypeRef); diff --git a/src/main.zig b/src/main.zig index cf09d7c..ea05a3b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3,6 +3,7 @@ const std = @import("std"); const scanners = @import("scanners.zig"); const parsers = @import("parsers.zig"); const printer = @import("ast_printer.zig"); +const codegen = @import("codegen.zig"); pub const Result = enum { Ok, @@ -45,6 +46,9 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { std.debug.warn("parse tree\n"); printer.printNode(root.?, 0); + var cgen = codegen.Codegen.init(allocator); + try cgen.gen(root.?); + return Result.Ok; }