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 8c6d510..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/ast.zig b/src/ast.zig index d5f8346..95d59c0 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -284,6 +284,28 @@ pub const Node = union(NodeType) { return node; } + pub fn mkFnDecl( + allocator: *std.mem.Allocator, + name: Token, + params: ParamList, + return_type: Token, + block: StmtList, + method: ?*MethodData, + ) !*Node { + var node = try allocator.create(Node); + + node.* = Node{ + .FnDecl = FnDecl{ + .func_name = name, + .params = params, + .return_type = return_type, + .body = block, + .method = method, + }, + }; + return node; + } + pub fn mkStructDecl(allocator: *std.mem.Allocator, name: Token, fields: FieldList) !*Node { var node = try allocator.create(Node); node.* = Node{ 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; } diff --git a/src/parsers.zig b/src/parsers.zig index 3542261..d31c611 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -175,27 +175,6 @@ pub const Parser = struct { // TODO maybe move helper functions to ast_helper.zig? - fn mkFnDecl( - self: *Parser, - name: Token, - params: ast.ParamList, - return_type: Token, - block: ast.StmtList, - method: ?*ast.MethodData, - ) !*ast.Node { - var node = try self.allocator.create(Node); - node.* = Node{ - .FnDecl = ast.FnDecl{ - .func_name = name, - .params = params, - .return_type = return_type, - .body = block, - .method = method, - }, - }; - return node; - } - fn mkConstDecl(self: *Parser, consts: ast.ConstList) !*ast.Node { var node = try self.allocator.create(Node); node.* = Node{ .ConstDecl = consts }; @@ -486,7 +465,14 @@ pub const Parser = struct { } var block_node = try self.parseBlock(); - return try self.mkFnDecl(name, param_list, return_type, block_node.Block, method); + return try Node.mkFnDecl( + self.allocator, + name, + param_list, + return_type, + block_node.Block, + method, + ); } /// parse the (v [mut] T) part of the method (defined here