diff --git a/src/codegen.zig b/src/codegen.zig index b0d652a..5ca193b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -7,6 +7,8 @@ fn sliceify(non_slice: ?[*]const u8) []const u8 { return non_slice.?[0..std.mem.len(u8, non_slice.?)]; } +pub const CompileError = error{LLVMError}; + pub const Codegen = struct { allocator: *std.mem.Allocator, @@ -14,6 +16,43 @@ pub const Codegen = struct { return Codegen{ .allocator = allocator }; } + fn genExpr(self: *Codegen, builder: var, expr: *const ast.Expr) !llvm.LLVMValueRef { + // TODO if expr is Variable, we should do a variable lookup + // in a symbol table, going up in scope, etc. + + // TODO VarDecl add things to the symbol table + // TODO Assign modify symbol table + + // TODO Calls fetch symbol table, check arity of it at codegen level + switch (expr.*) { + + // TODO handle all literals, construct llvm values for them + .Literal => |literal| {}, + .Binary => |binary| { + var left = try self.genExpr(builder, binary.left); + var right = try self.genExpr(builder, binary.right); + + return switch (binary.op.lexeme[0]) { + // TODO other operators + '+' => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), + + // TODO codegen errors + else => @panic("invalid binary operator"), + }; + }, + + // TODO codegen errors + else => @panic("invalid expr"), + } + } + + fn genFuncStmt(self: *Codegen, builder: var, stmt: *const ast.Stmt) !void { + switch (stmt.*) { + .Expr => |expr| try self.genExpr(builder, expr), + else => unreachable, + } + } + fn genNode( self: *Codegen, mod: llvm.LLVMModuleRef, @@ -48,6 +87,11 @@ pub const Codegen = struct { var builder = llvm.LLVMCreateBuilder(); llvm.LLVMPositionBuilderAtEnd(builder, entry); + for (decl.body.toSlice()) |stmt| { + // TODO custom function context for us + try self.genFuncStmt(builder, stmt); + } + // TODO codegen decl.body var tmp = llvm.LLVMBuildAdd( builder, @@ -89,23 +133,19 @@ pub const Codegen = struct { if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); - - // TODO return error value - @panic("compile error"); + return CompileError.LLVMError; } - //llvm.InitializeAllTargetInfos(); - //llvm.InitializeAllTargets(); - //llvm.InitializeAllTargetMCs(); - //llvm.InitializeAllAsmParsers(); - //llvm.InitializeAllAsmPrinters(); + llvm.LLVMInitializeAllTargetInfos(); + llvm.LLVMInitializeAllTargets(); + llvm.LLVMInitializeAllTargetMCs(); + llvm.LLVMInitializeAllAsmParsers(); + llvm.LLVMInitializeAllAsmPrinters(); var engine: llvm.LLVMExecutionEngineRef = undefined; if (llvm.LLVMCreateExecutionEngineForModule(&engine, mod, &err) != 0) { std.debug.warn("failed to create execution engine: {}\n", sliceify(err)); - - // TODO return error value - @panic("compile error"); + return CompileError.LLVMError; } var machine = llvm.LLVMGetExecutionEngineTargetMachine(engine); @@ -119,6 +159,9 @@ pub const Codegen = struct { var outpath = try std.mem.dupe(self.allocator, u8, "output.o"); var outpath_cstr = try std.cstr.addNullByte(self.allocator, outpath); + //var asmpath = try std.mem.dupe(self.allocator, u8, "output.S"); + //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, asmpath); + var desc = llvm.LLVMGetTargetDescription(target); var features = llvm.LLVMGetTargetMachineFeatureString(machine); var triple = llvm.LLVMGetTargetMachineTriple(machine); @@ -127,6 +170,17 @@ pub const Codegen = struct { std.debug.warn("triple: {}\n", sliceify(triple)); std.debug.warn("features: {}\n", sliceify(features)); + //if (llvm.LLVMTargetMachineEmitToFile( + // machine, + // mod, + // asmpath_cstr.ptr, + // llvm.LLVMCodeGenFileType.LLVMAssemblyFile, + // &err, + //) != 0) { + // std.debug.warn("failed to emit to assembly file: {}\n", sliceify(err)); + // return CompileError.LLVMError; + //} + if (llvm.LLVMTargetMachineEmitToFile( machine, mod, @@ -135,9 +189,7 @@ pub const Codegen = struct { &err, ) != 0) { std.debug.warn("failed to emit to file: {}\n", sliceify(err)); - - // TODO return error value - @panic("compile error"); + return CompileError.LLVMError; } } }; diff --git a/src/main.zig b/src/main.zig index ea05a3b..1000164 100644 --- a/src/main.zig +++ b/src/main.zig @@ -46,6 +46,9 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { std.debug.warn("parse tree\n"); printer.printNode(root.?, 0); + // TODO type pass + // TODO variable pass + var cgen = codegen.Codegen.init(allocator); try cgen.gen(root.?);