Support jump tables when in PIC relocation model


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29318 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index c90a3ee..802fe6d 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -156,9 +156,15 @@
     /// before emitting the constant pool for a function.
     const char *ConstantPoolSection;     // Defaults to "\t.section .rodata\n"
 
-    /// JumpTableSection - This is the section that we SwitchToSection right
-    /// before emitting the jump tables for a function.
-    const char *JumpTableSection;     // Defaults to "\t.section .rodata\n"
+    /// JumpTableDataSection - This is the section that we SwitchToSection right
+    /// before emitting the jump tables for a function when the relocation model
+    /// is not PIC.
+    const char *JumpTableDataSection;     // Defaults to "\t.section .rodata\n"
+    
+    /// JumpTableTextSection - This is the section that we SwitchToSection right
+    /// before emitting the jump tables for a function when the relocation model
+    /// is PIC.
+    const char *JumpTableTextSection;     // Defaults to "\t.text\n"
     
     /// StaticCtorsSection - This is the directive that is emitted to switch to
     /// a section to emit the static constructor list.
diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp
index 6e5dab7..a0f377c 100644
--- a/lib/CodeGen/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter.cpp
@@ -52,7 +52,8 @@
   DataSectionStartSuffix(""),
   SectionEndDirectiveSuffix(0),
   ConstantPoolSection("\t.section .rodata\n"),
-  JumpTableSection("\t.section .rodata\n"),
+  JumpTableDataSection("\t.section .rodata\n"),
+  JumpTableTextSection("\t.text\n"),
   StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"),
   StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"),
   FourByteConstantSection(0),
@@ -89,7 +90,7 @@
     O << CurrentSection << TextSectionStartSuffix << '\n';
 }
 
-/// SwitchToTextSection - Switch to the specified text section of the executable
+/// SwitchToDataSection - Switch to the specified data section of the executable
 /// if we are not already in it!
 ///
 void AsmPrinter::SwitchToDataSection(const char *NewSection,
@@ -209,29 +210,30 @@
   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
   if (JT.empty()) return;
   const TargetData *TD = TM.getTargetData();
+  const char *PtrDataDirective = Data32bitsDirective;
   
-  // FIXME: someday we need to handle PIC jump tables
-  assert((TM.getRelocationModel() == Reloc::Static ||
-          TM.getRelocationModel() == Reloc::DynamicNoPIC) &&
-         "Unhandled relocation model emitting jump table information!");
-  
-  SwitchToDataSection(JumpTableSection, 0);
+  // Pick the directive to use to print the jump table entries, and switch to 
+  // the appropriate section.
+  if (TM.getRelocationModel() == Reloc::PIC_) {
+    SwitchToTextSection(JumpTableTextSection, 0);
+  } else {
+    SwitchToDataSection(JumpTableDataSection, 0);
+    if (TD->getPointerSize() == 8)
+      PtrDataDirective = Data64bitsDirective;
+  }
   EmitAlignment(Log2_32(TD->getPointerAlignment()));
   
-  // Pick the directive to use based on the pointer size. FIXME: when we support
-  // PIC jumptables, this should always use the 32-bit directive for label
-  // differences. 
-  const char *PtrDataDirective = Data32bitsDirective;
-  if (TD->getPointerSize() == 8)
-    PtrDataDirective = Data64bitsDirective;
-
   for (unsigned i = 0, e = JT.size(); i != e; ++i) {
     O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << '_' << i 
       << ":\n";
     const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs;
     for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
       O << PtrDataDirective << ' ';
-      printBasicBlockLabel(JTBBs[ii]);
+      printBasicBlockLabel(JTBBs[ii], false, false);
+      if (TM.getRelocationModel() == Reloc::PIC_) {
+        O << '-' << PrivateGlobalPrefix << "JTI" << getFunctionNumber() 
+          << '_' << i;
+      }
       O << '\n';
     }
   }
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index e8e7a47..76510f3 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -850,9 +850,15 @@
   SDOperand Copy = DAG.getCopyFromReg(getRoot(), JT.Reg, PTy);
   SDOperand IDX = DAG.getNode(ISD::MUL, PTy, Copy,
                               DAG.getConstant(PTyBytes, PTy));
-  SDOperand ADD = DAG.getNode(ISD::ADD, PTy, IDX, DAG.getJumpTable(JT.JTI,PTy));
+  SDOperand TAB = DAG.getJumpTable(JT.JTI,PTy);
+  SDOperand ADD = DAG.getNode(ISD::ADD, PTy, IDX, TAB);
   SDOperand LD  = DAG.getLoad(PTy, Copy.getValue(1), ADD, DAG.getSrcValue(0));
-  DAG.setRoot(DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), LD));
+  if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+    ADD = DAG.getNode(ISD::ADD, PTy, LD.getValue(0), TAB);
+    DAG.setRoot(DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), ADD));
+  } else {
+    DAG.setRoot(DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), LD));
+  }
 }
 
 void SelectionDAGLowering::visitSwitch(SwitchInst &I) {
@@ -896,20 +902,20 @@
   // to represent the switch.
   MachineFunction *CurMF = CurMBB->getParent();
   const BasicBlock *LLVMBB = CurMBB->getBasicBlock();
-  Reloc::Model Relocs = TLI.getTargetMachine().getRelocationModel();
 
   // If the switch has more than 5 blocks, and at least 31.25% dense, and the 
   // target supports indirect branches, then emit a jump table rather than 
   // lowering the switch to a binary tree of conditional branches.
   // FIXME: Make this work with PIC code
   if (TLI.isOperationLegal(ISD::BRIND, TLI.getPointerTy()) &&
-      (Relocs == Reloc::Static || Relocs == Reloc::DynamicNoPIC) &&
       Cases.size() > 5) {
     uint64_t First = cast<ConstantIntegral>(Cases.front().first)->getRawValue();
     uint64_t Last  = cast<ConstantIntegral>(Cases.back().first)->getRawValue();
     double Density = (double)Cases.size() / (double)((Last - First) + 1ULL);
     
     if (Density >= 0.3125) {
+      Reloc::Model Relocs = TLI.getTargetMachine().getRelocationModel();
+      
       // Create a new basic block to hold the code for loading the address
       // of the jump table, and jumping to it.  Update successor information;
       // we will either branch to the default case for the switch, or the jump
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 6e75f3c..bf9c608 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -282,8 +282,8 @@
         Data64bitsDirective = 0;       // we can't emit a 64-bit unit
       AlignmentIsInBytes = false;    // Alignment is by power of 2.
       ConstantPoolSection = "\t.const\t";
-      // FIXME: Conditionalize jump table section based on PIC
-      JumpTableSection = ".const";
+      JumpTableDataSection = ".const";
+      JumpTableTextSection = "\t.text";
       LCOMMDirective = "\t.lcomm\t";
       StaticCtorsSection = ".mod_init_func";
       StaticDtorsSection = ".mod_term_func";
diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp
index 769aa73..712f34a 100755
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -143,7 +143,9 @@
     if (!isMemOp) O << '$';
     O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << "_"
       << MO.getJumpTableIndex();
-    // FIXME: PIC relocation model
+    if (Subtarget->TargetType == X86Subtarget::isDarwin && 
+        TM.getRelocationModel() == Reloc::PIC_)
+      O << "-\"L" << getFunctionNumber() << "$pb\"";
     return;
   }
   case MachineOperand::MO_ConstantPoolIndex: {
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 069b047..2c4b110 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -62,7 +62,7 @@
     ZeroDirective = "\t.space\t";  // ".space N" emits N zeros.
     PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
     ConstantPoolSection = "\t.const\n";
-    JumpTableSection = "\t.const\n"; // FIXME: depends on PIC mode
+    JumpTableDataSection = "\t.const\n"; // FIXME: depends on PIC mode
     FourByteConstantSection = "\t.literal4\n";
     EightByteConstantSection = "\t.literal8\n";
     LCOMMDirective = "\t.lcomm\t";