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)
This commit is contained in:
parent
c1d6939c43
commit
9e80ad4c23
2 changed files with 51 additions and 17 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue