From 9e80ad4c23a8e604d6e459d35c80efc8af17b584 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 24 Sep 2019 18:49:35 -0300 Subject: [PATCH] fix if statement emitting - don't emit br instructions (or any other) if branch emits ret - remove phi node (ifs are statements, not exprs) - emit to testfile (even if ir is broken) --- src/codegen.zig | 67 ++++++++++++++++++++++++++++++++++++------------- src/parsers.zig | 1 + 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index f28943a..b45d355 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -114,11 +114,10 @@ pub const Codegen = struct { var insert = llvm.LLVMGetInsertBlock(builder); var function = llvm.LLVMGetBasicBlockParent(insert); - var global_ctx = llvm.LLVMGetGlobalContext(); var then_bb = llvm.LLVMAppendBasicBlock(function, c"then"); - var else_bb = llvm.LLVMCreateBasicBlockInContext(global_ctx, c"else"); - var merge_bb = llvm.LLVMCreateBasicBlockInContext(global_ctx, c"ifcont"); + var else_bb = llvm.LLVMAppendBasicBlock(function, c"else"); + var merge_bb = llvm.LLVMAppendBasicBlock(function, c"ifcont"); var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb); @@ -126,11 +125,27 @@ pub const Codegen = struct { // roughly translating to kaleidoscope's // 'Value *ThenV = Then->codegen();' + var then_rets = false; + var else_rets = false; + for (ifstmt.then_branch.toSlice()) |then_stmt| { - try self.emitStmt(builder, &then_stmt); + + // keep emitting until branch has ret + if (!then_rets) + try self.emitStmt(builder, &then_stmt); + + switch (then_stmt) { + .Return => then_rets = true, + else => {}, + } } - _ = llvm.LLVMBuildBr(builder, merge_bb); + // only build the br instruction if we didn't ret, because + // there can't be any instruction after a terminator + // same applies for the else branch + if (!then_rets) + _ = llvm.LLVMBuildBr(builder, merge_bb); + then_bb = llvm.LLVMGetInsertBlock(builder); llvm.LLVMPositionBuilderAtEnd(builder, else_bb); @@ -139,22 +154,34 @@ pub const Codegen = struct { // 'Else *ElseV = Else->codegen();' if (ifstmt.else_branch) |else_block| { for (else_block.toSlice()) |else_stmt| { - try self.emitStmt(builder, &else_stmt); + // keep emitting until branch has ret + if (!else_rets) + try self.emitStmt(builder, &else_stmt); + + switch (else_stmt) { + .Return => else_rets = true, + else => {}, + } } } - _ = llvm.LLVMBuildBr(builder, merge_bb); + if (!else_rets) + _ = llvm.LLVMBuildBr(builder, merge_bb); + else_bb = llvm.LLVMGetInsertBlock(builder); llvm.LLVMPositionBuilderAtEnd(builder, merge_bb); - var phi = llvm.LLVMBuildPhi(builder, llvm.LLVMVoidType(), c"iftmp"); + if (then_rets and else_rets) + _ = llvm.LLVMBuildUnreachable(builder); - var then_bb_val = llvm.LLVMBasicBlockAsValue(then_bb); - var else_bb_val = llvm.LLVMBasicBlockAsValue(else_bb); + // phis aren't needed since our ifs arent expressions - llvm.LLVMAddIncoming(phi, &then_bb_val, &then_bb, 1); - llvm.LLVMAddIncoming(phi, &else_bb_val, &else_bb, 1); + //var phi = llvm.LLVMBuildPhi(builder, llvm.LLVMVoidType(), c"iftmp"); + //var then_bb_val = llvm.LLVMBasicBlockAsValue(then_bb); + //var else_bb_val = llvm.LLVMBasicBlockAsValue(else_bb); + //llvm.LLVMAddIncoming(phi, &then_bb_val, &then_bb, 1); + //llvm.LLVMAddIncoming(phi, &else_bb_val, &else_bb, 1); }, else => { @@ -250,17 +277,23 @@ pub const Codegen = struct { var err: ?[*]u8 = null; defer llvm.LLVMDisposeMessage(err); - _ = llvm.LLVMVerifyModule( - mod, - llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, - &err, - ); + if (llvm.LLVMPrintModuleToFile(mod, c"testfile", &err) != 0) { + std.debug.warn("error printing module to file: {}\n", sliceify(err)); + return CompileError.LLVMError; + } if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); return CompileError.LLVMError; } + std.debug.warn("cgen: verify llvm module\n"); + _ = llvm.LLVMVerifyModule( + mod, + llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, + &err, + ); + llvm.LLVMInitializeAllTargetInfos(); llvm.LLVMInitializeAllTargets(); llvm.LLVMInitializeAllTargetMCs(); diff --git a/src/parsers.zig b/src/parsers.zig index 900a1d1..3e0dc91 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -798,6 +798,7 @@ pub const Parser = struct { fn parseReturn(self: *@This()) !*Stmt { const tok = try self.consumeSingle(.Return); + // TODO if (self.check(.Semicolon)) insert a void literal? const expr = try self.parseExpr(); return try Stmt.mkReturn(self.allocator, tok, expr); }