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.h b/lib/CodeGen/CodeGenFunction.h
index 38e10e9..374cdf6 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -22,6 +22,7 @@
 #include "clang/AST/ExprObjC.h"
 
 #include <vector>
+#include <map>
 
 namespace llvm {
   class Module;
@@ -240,11 +241,21 @@
   /// AllocaInsertPoint - This is an instruction in the entry block before which
   /// we prefer to insert allocas.
   llvm::Instruction *AllocaInsertPt;
-  
+
   const llvm::Type *LLVMIntTy;
   uint32_t LLVMPointerWidth;
   
 private:
+  /// LabelIDs - Track arbitrary ids assigned to labels for use in
+  /// implementing the GCC address-of-label extension and indirect
+  /// goto. IDs are assigned to labels inside getIDForAddrOfLabel().
+  std::map<const LabelStmt*, unsigned> LabelIDs;
+
+  /// IndirectSwitches - Record the list of switches for indirect
+  /// gotos. Emission of the actual switching code needs to be delayed
+  /// until all AddrLabelExprs have been seen.
+  std::vector<llvm::SwitchInst*> IndirectSwitches;
+
   /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
   /// decls.
   llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
@@ -342,6 +353,8 @@
   /// the input field number being accessed.
   static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
 
+  unsigned GetIDForAddrOfLabel(const LabelStmt *L);
+
   //===--------------------------------------------------------------------===//
   //                            Declaration Emission
   //===--------------------------------------------------------------------===//
@@ -363,6 +376,7 @@
   void EmitLabel(const LabelStmt &S); // helper for EmitLabelStmt.
   void EmitLabelStmt(const LabelStmt &S);
   void EmitGotoStmt(const GotoStmt &S);
+  void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
   void EmitIfStmt(const IfStmt &S);
   void EmitWhileStmt(const WhileStmt &S);
   void EmitDoStmt(const DoStmt &S);
@@ -502,6 +516,15 @@
   llvm::GlobalValue *GenerateStaticBlockVarDecl(const VarDecl &D,
                                                 bool NoInit,
                                                 const char *Separator);
+
+  //===--------------------------------------------------------------------===//
+  //                             Internal Helpers
+  //===--------------------------------------------------------------------===//
+ 
+private:
+  /// EmitIndirectSwitches - Emit code for all of the switch
+  /// instructions in IndirectSwitches.
+  void EmitIndirectSwitches();
 };
 }  // end namespace CodeGen
 }  // end namespace clang