Add CodeGen support for indirect goto.
- Follows emission scheme used by llvm-gcc, i.e. invent an id for
each label whose address is taken and replace each indirect goto by
a switch to each possible target.
- Currently we emit a switch for each indirect goto instead of
merging them as llvm-gcc does.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54318 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 9743c7c..a5cf946 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -62,6 +62,8 @@
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
+ case Stmt::IndirectGotoStmtClass:
+ EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
@@ -157,7 +159,25 @@
Builder.SetInsertPoint(llvm::BasicBlock::Create("", CurFn));
}
+void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
+ // Emit initial switch which will be patched up later by
+ // EmitIndirectSwitches(). We need a default dest, so we use the
+ // current BB, but this is overwritten.
+ llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
+ llvm::Type::Int32Ty,
+ "addr");
+ llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock());
+ IndirectSwitches.push_back(I);
+
+ // Emit a block after the branch so that dead code after a goto has some place
+ // to go.
+ Builder.SetInsertPoint(llvm::BasicBlock::Create("", CurFn));
+}
+
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
+ // FIXME: It would probably be nice for us to skip emission of if
+ // (0) code here.
+
// C99 6.8.4.1: The first substatement is executed if the expression compares
// unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());