Implement codegen support for labels and gotos. We now compile:
void test1() {
foo:
goto foo;
goto foo;
goto foo;
}
void test() {
goto l;
l:
;
}
into:
define void @test1() {
entry:
br label %foo
foo: ; preds = %0, %foo, %entry
br label %foo
; No predecessors!
br label %foo
; No predecessors!
}
define void @test() {
entry:
br label %l
l: ; preds = %entry
}
llvm-svn: 39524
diff --git a/clang/CodeGen/CodeGenFunction.cpp b/clang/CodeGen/CodeGenFunction.cpp
index ff31a83..4061b41 100644
--- a/clang/CodeGen/CodeGenFunction.cpp
+++ b/clang/CodeGen/CodeGenFunction.cpp
@@ -25,6 +25,15 @@
: CGM(cgm), Target(CGM.getContext().Target) {}
+llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) {
+ BasicBlock *&BB = LabelMap[S];
+ if (BB) return BB;
+
+ // Create, but don't insert, the new block.
+ return BB = new BasicBlock(S->getName());
+}
+
+
/// ConvertType - Convert the specified type to its LLVM form.
const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
// FIXME: Cache these, move the CodeGenModule, expand, etc.
@@ -104,11 +113,11 @@
void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
const llvm::Type *Ty = ConvertType(FD->getType(), FD->getLocation());
- llvm::Function *F = new Function(cast<llvm::FunctionType>(Ty),
- Function::ExternalLinkage,
- FD->getName(), &CGM.getModule());
+ CurFn = new Function(cast<llvm::FunctionType>(Ty),
+ Function::ExternalLinkage,
+ FD->getName(), &CGM.getModule());
- BasicBlock *EntryBB = new BasicBlock("entry", F);
+ BasicBlock *EntryBB = new BasicBlock("entry", CurFn);
// TODO: Walk the decls, creating allocas etc.
@@ -132,6 +141,8 @@
break;
case Stmt::NullStmtClass: break;
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
+ case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
+ case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
}
}
@@ -143,3 +154,29 @@
EmitStmt(*I);
}
+void CodeGenFunction::EmitBlock(BasicBlock *BB) {
+ // Emit a branch from this block to the next one if this was a real block. If
+ // this was just a fall-through block after a terminator, don't emit it.
+ if (!Builder.GetInsertBlock()->empty() ||
+ Builder.GetInsertBlock()->getValueName()) {
+ Builder.CreateBr(BB);
+ } else {
+ // TODO: cache and reuse these.
+ Builder.GetInsertBlock()->eraseFromParent();
+ }
+ CurFn->getBasicBlockList().push_back(BB);
+ Builder.SetInsertPoint(BB);
+}
+
+void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
+ llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
+
+ EmitBlock(NextBB);
+}
+
+void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
+ Builder.CreateBr(getBasicBlockForLabel(S.getLabel()));
+
+ Builder.SetInsertPoint(new BasicBlock("", CurFn));
+}
+