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/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index e153ad9..9814ae7 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -68,7 +68,10 @@
 void CodeGenFunction::GenerateFunction(const Stmt *Body) {
   // Emit the function body.
   EmitStmt(Body);
-  
+
+  // Finish emission of indirect switches.
+  EmitIndirectSwitches();
+
   // Emit debug descriptor for function end.
   CGDebugInfo *DI = CGM.getDebugInfo(); 
   if (DI) {
@@ -179,3 +182,33 @@
   CGM.WarnUnsupported(S, Type);
 }
 
+unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
+  // Use LabelIDs.size() as the new ID if one hasn't been assigned.
+  return LabelIDs.insert(std::make_pair(L, LabelIDs.size())).first->second;
+}
+
+void CodeGenFunction::EmitIndirectSwitches() {
+  llvm::BasicBlock *Default;
+  
+  if (!LabelIDs.empty()) {
+    Default = getBasicBlockForLabel(LabelIDs.begin()->first);
+  } else {
+    // No possible targets for indirect goto, just emit an infinite
+    // loop.
+    Default = llvm::BasicBlock::Create("indirectgoto.loop", CurFn);
+    llvm::BranchInst::Create(Default, Default);
+  }
+
+  for (std::vector<llvm::SwitchInst*>::iterator i = IndirectSwitches.begin(),
+         e = IndirectSwitches.end(); i != e; ++i) {
+    llvm::SwitchInst *I = *i;
+    
+    I->setSuccessor(0, Default);
+    for (std::map<const LabelStmt*,unsigned>::iterator LI = LabelIDs.begin(), 
+           LE = LabelIDs.end(); LI != LE; ++LI) {
+      I->addCase(llvm::ConstantInt::get(llvm::Type::Int32Ty,
+                                        LI->second), 
+                 getBasicBlockForLabel(LI->first));
+    }
+  }         
+}