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 insert = llvm.LLVMGetInsertBlock(builder);
|
||||||
var function = llvm.LLVMGetBasicBlockParent(insert);
|
var function = llvm.LLVMGetBasicBlockParent(insert);
|
||||||
var global_ctx = llvm.LLVMGetGlobalContext();
|
|
||||||
|
|
||||||
var then_bb = llvm.LLVMAppendBasicBlock(function, c"then");
|
var then_bb = llvm.LLVMAppendBasicBlock(function, c"then");
|
||||||
var else_bb = llvm.LLVMCreateBasicBlockInContext(global_ctx, c"else");
|
var else_bb = llvm.LLVMAppendBasicBlock(function, c"else");
|
||||||
var merge_bb = llvm.LLVMCreateBasicBlockInContext(global_ctx, c"ifcont");
|
var merge_bb = llvm.LLVMAppendBasicBlock(function, c"ifcont");
|
||||||
|
|
||||||
var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb);
|
var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb);
|
||||||
|
|
||||||
|
@ -126,11 +125,27 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
// roughly translating to kaleidoscope's
|
// roughly translating to kaleidoscope's
|
||||||
// 'Value *ThenV = Then->codegen();'
|
// 'Value *ThenV = Then->codegen();'
|
||||||
|
var then_rets = false;
|
||||||
|
var else_rets = false;
|
||||||
|
|
||||||
for (ifstmt.then_branch.toSlice()) |then_stmt| {
|
for (ifstmt.then_branch.toSlice()) |then_stmt| {
|
||||||
|
|
||||||
|
// keep emitting until branch has ret
|
||||||
|
if (!then_rets)
|
||||||
try self.emitStmt(builder, &then_stmt);
|
try self.emitStmt(builder, &then_stmt);
|
||||||
|
|
||||||
|
switch (then_stmt) {
|
||||||
|
.Return => then_rets = true,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
_ = llvm.LLVMBuildBr(builder, merge_bb);
|
||||||
|
|
||||||
then_bb = llvm.LLVMGetInsertBlock(builder);
|
then_bb = llvm.LLVMGetInsertBlock(builder);
|
||||||
|
|
||||||
llvm.LLVMPositionBuilderAtEnd(builder, else_bb);
|
llvm.LLVMPositionBuilderAtEnd(builder, else_bb);
|
||||||
|
@ -139,22 +154,34 @@ pub const Codegen = struct {
|
||||||
// 'Else *ElseV = Else->codegen();'
|
// 'Else *ElseV = Else->codegen();'
|
||||||
if (ifstmt.else_branch) |else_block| {
|
if (ifstmt.else_branch) |else_block| {
|
||||||
for (else_block.toSlice()) |else_stmt| {
|
for (else_block.toSlice()) |else_stmt| {
|
||||||
|
// keep emitting until branch has ret
|
||||||
|
if (!else_rets)
|
||||||
try self.emitStmt(builder, &else_stmt);
|
try self.emitStmt(builder, &else_stmt);
|
||||||
|
|
||||||
|
switch (else_stmt) {
|
||||||
|
.Return => else_rets = true,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!else_rets)
|
||||||
_ = llvm.LLVMBuildBr(builder, merge_bb);
|
_ = llvm.LLVMBuildBr(builder, merge_bb);
|
||||||
|
|
||||||
else_bb = llvm.LLVMGetInsertBlock(builder);
|
else_bb = llvm.LLVMGetInsertBlock(builder);
|
||||||
|
|
||||||
llvm.LLVMPositionBuilderAtEnd(builder, merge_bb);
|
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);
|
// phis aren't needed since our ifs arent expressions
|
||||||
var else_bb_val = llvm.LLVMBasicBlockAsValue(else_bb);
|
|
||||||
|
|
||||||
llvm.LLVMAddIncoming(phi, &then_bb_val, &then_bb, 1);
|
//var phi = llvm.LLVMBuildPhi(builder, llvm.LLVMVoidType(), c"iftmp");
|
||||||
llvm.LLVMAddIncoming(phi, &else_bb_val, &else_bb, 1);
|
//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 => {
|
else => {
|
||||||
|
@ -250,17 +277,23 @@ pub const Codegen = struct {
|
||||||
var err: ?[*]u8 = null;
|
var err: ?[*]u8 = null;
|
||||||
defer llvm.LLVMDisposeMessage(err);
|
defer llvm.LLVMDisposeMessage(err);
|
||||||
|
|
||||||
_ = llvm.LLVMVerifyModule(
|
if (llvm.LLVMPrintModuleToFile(mod, c"testfile", &err) != 0) {
|
||||||
mod,
|
std.debug.warn("error printing module to file: {}\n", sliceify(err));
|
||||||
llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction,
|
return CompileError.LLVMError;
|
||||||
&err,
|
}
|
||||||
);
|
|
||||||
|
|
||||||
if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) {
|
if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) {
|
||||||
std.debug.warn("error writing bitcode to file: {}\n", sliceify(err));
|
std.debug.warn("error writing bitcode to file: {}\n", sliceify(err));
|
||||||
return CompileError.LLVMError;
|
return CompileError.LLVMError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std.debug.warn("cgen: verify llvm module\n");
|
||||||
|
_ = llvm.LLVMVerifyModule(
|
||||||
|
mod,
|
||||||
|
llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction,
|
||||||
|
&err,
|
||||||
|
);
|
||||||
|
|
||||||
llvm.LLVMInitializeAllTargetInfos();
|
llvm.LLVMInitializeAllTargetInfos();
|
||||||
llvm.LLVMInitializeAllTargets();
|
llvm.LLVMInitializeAllTargets();
|
||||||
llvm.LLVMInitializeAllTargetMCs();
|
llvm.LLVMInitializeAllTargetMCs();
|
||||||
|
|
|
@ -798,6 +798,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
fn parseReturn(self: *@This()) !*Stmt {
|
fn parseReturn(self: *@This()) !*Stmt {
|
||||||
const tok = try self.consumeSingle(.Return);
|
const tok = try self.consumeSingle(.Return);
|
||||||
|
// TODO if (self.check(.Semicolon)) insert a void literal?
|
||||||
const expr = try self.parseExpr();
|
const expr = try self.parseExpr();
|
||||||
return try Stmt.mkReturn(self.allocator, tok, expr);
|
return try Stmt.mkReturn(self.allocator, tok, expr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue