JumpTable support!  What this represents is working asm and jit support for
x86 and ppc for 100% dense switch statements when relocations are non-PIC.
This support will be extended and enhanced in the coming days to support
PIC, and less dense forms of jump tables.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27947 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Alpha/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AlphaAsmPrinter.cpp
index 6f45fb5..5d1f522 100644
--- a/lib/Target/Alpha/AlphaAsmPrinter.cpp
+++ b/lib/Target/Alpha/AlphaAsmPrinter.cpp
@@ -115,14 +115,9 @@
     abort();
     return;
 
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << PrivateGlobalPrefix << "LBB"
-      << Mang->getValueName(MBBOp->getParent()->getFunction())
-      << "_" << MBBOp->getNumber() << "\t" << CommentString << " "
-      << MBBOp->getBasicBlock()->getName();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
 
   case MachineOperand::MO_ConstantPoolIndex:
     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp
index fee6457..3c72e7f 100644
--- a/lib/Target/Alpha/AlphaISelLowering.cpp
+++ b/lib/Target/Alpha/AlphaISelLowering.cpp
@@ -193,6 +193,7 @@
   addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass);
   addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass);
   
+  setOperationAction(ISD::BRIND,        MVT::i64,   Expand);
   setOperationAction(ISD::BR_CC,        MVT::Other, Expand);
   setOperationAction(ISD::SELECT_CC,    MVT::Other, Expand);
   
diff --git a/lib/Target/IA64/IA64AsmPrinter.cpp b/lib/Target/IA64/IA64AsmPrinter.cpp
index 2cd1561..359b644 100644
--- a/lib/Target/IA64/IA64AsmPrinter.cpp
+++ b/lib/Target/IA64/IA64AsmPrinter.cpp
@@ -189,14 +189,9 @@
   case MachineOperand::MO_UnextendedImmed:
     O << /*(unsigned int)*/MO.getImmedValue();
     return;
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << PrivateGlobalPrefix << "LBB"
-      << Mang->getValueName(MBBOp->getParent()->getFunction())
-      << "_" << MBBOp->getNumber () << "\t// "
-      << MBBOp->getBasicBlock ()->getName ();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
   case MachineOperand::MO_PCRelativeDisp:
     std::cerr << "Shouldn't use addPCDisp() when building IA64 MachineInstrs";
     abort ();
diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp
index 85e6737..9de5447 100644
--- a/lib/Target/IA64/IA64ISelLowering.cpp
+++ b/lib/Target/IA64/IA64ISelLowering.cpp
@@ -35,6 +35,7 @@
       // register class for predicate registers
       addRegisterClass(MVT::i1, IA64::PRRegisterClass);
 
+      setOperationAction(ISD::BRIND            , MVT::i64,   Expand);
       setOperationAction(ISD::BR_CC            , MVT::Other, Expand);
       setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand);
 
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index b34bf9a..11c0ec0 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -233,6 +233,8 @@
       printOperand(MI, OpNo+1);
     }
     
+    virtual void printBasicBlockLabel(const MachineBasicBlock *MBB) const; 
+    
     virtual bool runOnMachineFunction(MachineFunction &F) = 0;
     virtual bool doFinalization(Module &M) = 0;
     
@@ -277,6 +279,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";
       LCOMMDirective = "\t.lcomm\t";
       StaticCtorsSection = ".mod_init_func";
       StaticDtorsSection = ".mod_term_func";
@@ -373,13 +377,14 @@
     abort();
     return;
 
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << PrivateGlobalPrefix << "BB" << getFunctionNumber() << "_"
-      << MBBOp->getNumber() << "\t; " << MBBOp->getBasicBlock()->getName();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
-
+  case MachineOperand::MO_JumpTableIndex:
+    O << PrivateGlobalPrefix << "JTI" << getFunctionNumber()
+      << '_' << MO.getJumpTableIndex();
+    // FIXME: PIC relocation model
+    return;
   case MachineOperand::MO_ConstantPoolIndex:
     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber()
       << '_' << MO.getConstantPoolIndex();
@@ -500,6 +505,11 @@
   return;
 }
 
+void PPCAsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB) const {
+  O << PrivateGlobalPrefix << "BB" << getFunctionNumber() << "_"
+    << MBB->getNumber() << '\t' << CommentString
+    << MBB->getBasicBlock()->getName();
+}
 
 /// runOnMachineFunction - This uses the printMachineInstruction()
 /// method to print assembly for each instruction.
@@ -514,6 +524,9 @@
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
 
+  // Print out jump tables referenced by the function
+  EmitJumpTableInfo(MF.getJumpTableInfo());
+
   // Print out labels for the function.
   const Function *F = MF.getFunction();
   switch (F->getLinkage()) {
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp
index 8d4e1b6..c7f2acb 100644
--- a/lib/Target/PowerPC/PPCCodeEmitter.cpp
+++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp
@@ -34,7 +34,7 @@
     // Tracks which instruction references which BasicBlock
     std::vector<std::pair<MachineBasicBlock*, unsigned*> > BBRefs;
     // Tracks where each BasicBlock starts
-    std::map<MachineBasicBlock*, long> BBLocations;
+    std::map<MachineBasicBlock*, uint64_t> BBLocations;
 
     /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
     ///
@@ -91,8 +91,10 @@
          "JIT relocation model must be set to static or default!");
   MCE.startFunction(MF);
   MCE.emitConstantPool(MF.getConstantPool());
+  MCE.initJumpTableInfo(MF.getJumpTableInfo());
   for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
     emitBasicBlock(*BB);
+  MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BBLocations);
   MCE.finishFunction(MF);
 
   // Resolve branches to BasicBlocks for the entire function
@@ -192,10 +194,13 @@
   } else if (MO.isMachineBasicBlock()) {
     unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
     BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC));
-  } else if (MO.isConstantPoolIndex()) {
-    unsigned index = MO.getConstantPoolIndex();
+  } else if (MO.isConstantPoolIndex() || MO.isJumpTableIndex()) {
+    if (MO.isConstantPoolIndex())
+      rv = MCE.getConstantPoolEntryAddress(MO.getConstantPoolIndex());
+    else
+      rv = MCE.getJumpTableEntryAddress(MO.getJumpTableIndex());
+
     unsigned Opcode = MI.getOpcode();
-    rv = MCE.getConstantPoolEntryAddress(index);
     if (Opcode == PPC::LIS || Opcode == PPC::ADDIS) {
       // lis wants hi16(addr)
       if ((short)rv < 0) rv += 1 << 16;
@@ -206,7 +211,7 @@
       // These load opcodes want lo16(addr)
       rv &= 0xffff;
     } else {
-      assert(0 && "Unknown constant pool using instruction!");
+      assert(0 && "Unknown constant pool or jump table using instruction!");
     }
   } else {
     std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index b699b92..10f074f 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -520,7 +520,8 @@
              && "Cannot handle constant offsets yet!");
       Disp = N.getOperand(1).getOperand(0);  // The global address.
       assert(Disp.getOpcode() == ISD::TargetGlobalAddress ||
-             Disp.getOpcode() == ISD::TargetConstantPool);
+             Disp.getOpcode() == ISD::TargetConstantPool ||
+             Disp.getOpcode() == ISD::TargetJumpTable);
       Base = N.getOperand(0);
       return true;  // [&g+r]
     }
@@ -661,7 +662,8 @@
              && "Cannot handle constant offsets yet!");
       Disp = N.getOperand(1).getOperand(0);  // The global address.
       assert(Disp.getOpcode() == ISD::TargetGlobalAddress ||
-             Disp.getOpcode() == ISD::TargetConstantPool);
+             Disp.getOpcode() == ISD::TargetConstantPool ||
+             Disp.getOpcode() == ISD::TargetJumpTable);
       Base = N.getOperand(0);
       return true;  // [&g+r]
     }
@@ -1241,6 +1243,15 @@
                                   N->getOperand(4), Chain);
     return;
   }
+  case ISD::BRIND: {
+    SDOperand Chain, Target;
+    Select(Chain, N->getOperand(0));
+    Select(Target,N->getOperand(1));
+    Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, Target,
+                                            Chain), 0);
+    Result = CurDAG->SelectNodeTo(N, PPC::BCTR, MVT::Other, Chain);
+    return;
+  }
   }
   
   SelectCode(Result, Op);
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 18404fc..fac2806 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -123,6 +123,7 @@
   // appropriate instructions to materialize the address.
   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
   setOperationAction(ISD::ConstantPool,  MVT::i32, Custom);
+  setOperationAction(ISD::JumpTable,     MVT::i32, Custom);
 
   // RET must be custom lowered, to meet ABI requirements
   setOperationAction(ISD::RET               , MVT::Other, Custom);
@@ -605,6 +606,36 @@
   return Lo;
 }
 
+static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
+  JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+  SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
+  SDOperand Zero = DAG.getConstant(0, MVT::i32);
+  
+  const TargetMachine &TM = DAG.getTarget();
+  
+  // If this is a non-darwin platform, we don't support non-static relo models
+  // yet.
+  if (TM.getRelocationModel() == Reloc::Static ||
+      !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
+    // Generate non-pic code that has direct accesses to the constant pool.
+    // The address of the global is just (hi(&g)+lo(&g)).
+    SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, JTI, Zero);
+    SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, JTI, Zero);
+    return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
+  }
+  
+  SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, JTI, Zero);
+  if (TM.getRelocationModel() == Reloc::PIC) {
+    // With PIC, the first instruction is actually "GR+hi(&G)".
+    Hi = DAG.getNode(ISD::ADD, MVT::i32,
+                     DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
+  }
+  
+  SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, JTI, Zero);
+  Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
+  return Lo;
+}
+
 static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
   GlobalValue *GV = GSDN->getGlobal();
@@ -1652,6 +1683,7 @@
   default: assert(0 && "Wasn't expecting to be able to lower this!"); 
   case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
+  case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
   case ISD::SETCC:              return LowerSETCC(Op, DAG);
   case ISD::VASTART:            return LowerVASTART(Op, DAG, VarArgsFrameIndex);
   case ISD::RET:                return LowerRET(Op, DAG);
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 449c3bd..8333873 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -702,7 +702,7 @@
 
 def MTLR  : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>,
             PPC970_DGroup_First, PPC970_Unit_FXU;
-def MFLR  : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT",  SprMFSPR>,
+def MFLR  : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT", SprMFSPR>,
             PPC970_DGroup_First, PPC970_Unit_FXU;
 
 // Move to/from VRSAVE: despite being a SPR, the VRSAVE register is renamed like
@@ -1015,10 +1015,14 @@
 def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
 def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
 def : Pat<(PPClo tconstpool:$in, 0), (LI tconstpool:$in)>;
+def : Pat<(PPChi tjumptable:$in, 0), (LIS tjumptable:$in)>;
+def : Pat<(PPClo tjumptable:$in, 0), (LI tjumptable:$in)>;
 def : Pat<(add GPRC:$in, (PPChi tglobaladdr:$g, 0)),
           (ADDIS GPRC:$in, tglobaladdr:$g)>;
 def : Pat<(add GPRC:$in, (PPChi tconstpool:$g, 0)),
           (ADDIS GPRC:$in, tconstpool:$g)>;
+def : Pat<(add GPRC:$in, (PPChi tjumptable:$g, 0)),
+          (ADDIS GPRC:$in, tjumptable:$g)>;
 
 // Fused negative multiply subtract, alternate pattern
 def : Pat<(fsub F8RC:$B, (fmul F8RC:$A, F8RC:$C)),
diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp
index 4565a99..dc1ab54 100644
--- a/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -163,13 +163,9 @@
   case MachineOperand::MO_UnextendedImmed:
     O << (int)MO.getImmedValue();
     break;
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
-      << "_" << MBBOp->getNumber () << "\t! "
-      << MBBOp->getBasicBlock ()->getName ();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
   case MachineOperand::MO_PCRelativeDisp:
     std::cerr << "Shouldn't use addPCDisp() when building Sparc MachineInstrs";
     abort ();
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index 0390238..a910b3e 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -167,6 +167,7 @@
   
   // Sparc doesn't have BRCOND either, it has BR_CC.
   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+  setOperationAction(ISD::BRIND, MVT::i32, Expand);
   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
   setOperationAction(ISD::BR_CC, MVT::f32, Custom);
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td
index 61283ae..f37e53c 100644
--- a/lib/Target/TargetSelectionDAG.td
+++ b/lib/Target/TargetSelectionDAG.td
@@ -150,6 +150,10 @@
   SDTCisInt<0>, SDTCisVT<1, OtherVT>
 ]>;
 
+def SDTBrind : SDTypeProfile<0, 1, [ // brind
+  SDTCisPtrTy<0>
+]>;
+
 def SDTRet : SDTypeProfile<0, 0, []>; // ret
 
 def SDTLoad : SDTypeProfile<1, 1, [ // load
@@ -217,6 +221,10 @@
                          "ConstantPoolSDNode">;
 def tconstpool  : SDNode<"ISD::TargetConstantPool",   SDTPtrLeaf, [],
                          "ConstantPoolSDNode">;
+def jumptable   : SDNode<"ISD::JumpTable",            SDTPtrLeaf, [],
+                         "JumpTableSDNode">;
+def tjumptable  : SDNode<"ISD::TargetJumpTable",      SDTPtrLeaf, [],
+                         "JumpTableSDNode">;
 def frameindex  : SDNode<"ISD::FrameIndex",           SDTPtrLeaf, [],
                          "FrameIndexSDNode">;
 def tframeindex : SDNode<"ISD::TargetFrameIndex",     SDTPtrLeaf, [],
@@ -293,6 +301,7 @@
 def selectcc   : SDNode<"ISD::SELECT_CC"  , SDTSelectCC>;
 
 def brcond     : SDNode<"ISD::BRCOND"     , SDTBrcond, [SDNPHasChain]>;
+def brind      : SDNode<"ISD::BRIND"      , SDTBrind,  [SDNPHasChain]>;
 def br         : SDNode<"ISD::BR"         , SDTBr,     [SDNPHasChain]>;
 def ret        : SDNode<"ISD::RET"        , SDTRet,    [SDNPHasChain]>;
 
diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp
index 5a3490a..e3c4818 100755
--- a/lib/Target/X86/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/X86ATTAsmPrinter.cpp
@@ -38,6 +38,9 @@
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
 
+  // Print out jump tables referenced by the function
+  EmitJumpTableInfo(MF.getJumpTableInfo());
+  
   // Print out labels for the function.
   const Function *F = MF.getFunction();
   switch (F->getLinkage()) {
@@ -120,18 +123,21 @@
       O << '$';
     O << (int)MO.getImmedValue();
     return;
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << PrivateGlobalPrefix << "BB"
-      << Mang->getValueName(MBBOp->getParent()->getFunction())
-      << "_" << MBBOp->getNumber () << "\t# "
-      << MBBOp->getBasicBlock ()->getName ();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
   case MachineOperand::MO_PCRelativeDisp:
     std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
     abort ();
     return;
+  case MachineOperand::MO_JumpTableIndex: {
+    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
+    if (!isMemOp) O << '$';
+    O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << "_"
+      << MO.getJumpTableIndex();
+    // FIXME: PIC relocation model
+    return;
+  }
   case MachineOperand::MO_ConstantPoolIndex: {
     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
     if (!isMemOp) O << '$';
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 990951e..ee1383e 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -54,6 +54,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
     LCOMMDirective = "\t.lcomm\t";
     COMMDirectiveTakesAlignment = false;
     HasDotTypeDotSizeDirective = false;
@@ -205,6 +206,14 @@
   return false; // success
 }
 
+void X86SharedAsmPrinter::printBasicBlockLabel(const MachineBasicBlock *MBB) 
+     const {
+  O << PrivateGlobalPrefix << "BB" 
+  << Mang->getValueName(MBB->getParent()->getFunction())
+  << "_" << MBB->getNumber() << '\t' << CommentString
+  << MBB->getBasicBlock()->getName();
+}
+
 /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
 /// for a MachineFunction to the given output stream, using the given target
 /// machine description.
diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h
index c4d67b6..fa84c9e 100755
--- a/lib/Target/X86/X86AsmPrinter.h
+++ b/lib/Target/X86/X86AsmPrinter.h
@@ -88,6 +88,8 @@
        MI->getOperand(Op+3).isGlobalAddress() ||
        MI->getOperand(Op+3).isConstantPoolIndex());
   }
+
+  virtual void printBasicBlockLabel(const MachineBasicBlock *MBB) const; 
 };
 
 } // end namespace llvm
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp
index 51be7b8..bac310c 100644
--- a/lib/Target/X86/X86CodeEmitter.cpp
+++ b/lib/Target/X86/X86CodeEmitter.cpp
@@ -35,8 +35,8 @@
   class Emitter : public MachineFunctionPass {
     const X86InstrInfo  *II;
     MachineCodeEmitter  &MCE;
-    std::map<const MachineBasicBlock*, unsigned> BasicBlockAddrs;
-    std::vector<std::pair<const MachineBasicBlock *, unsigned> > BBRefs;
+    std::map<MachineBasicBlock*, uint64_t> BasicBlockAddrs;
+    std::vector<std::pair<MachineBasicBlock *, unsigned> > BBRefs;
   public:
     explicit Emitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {}
     Emitter(MachineCodeEmitter &mce, const X86InstrInfo& ii)
@@ -51,9 +51,8 @@
     void emitInstruction(const MachineInstr &MI);
 
   private:
-    void emitBasicBlock(const MachineBasicBlock &MBB);
-
-    void emitPCRelativeBlockAddress(const MachineBasicBlock *BB);
+    void emitBasicBlock(MachineBasicBlock &MBB);
+    void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
     void emitPCRelativeValue(unsigned Address);
     void emitGlobalAddressForCall(GlobalValue *GV, bool isTailCall);
     void emitGlobalAddressForPtr(GlobalValue *GV, int Disp = 0);
@@ -84,8 +83,10 @@
 
   MCE.startFunction(MF);
   MCE.emitConstantPool(MF.getConstantPool());
+  MCE.initJumpTableInfo(MF.getJumpTableInfo());
   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
     emitBasicBlock(*I);
+  MCE.emitJumpTableInfo(MF.getJumpTableInfo(), BasicBlockAddrs);
   MCE.finishFunction(MF);
 
   // Resolve all forward branches now...
@@ -99,7 +100,7 @@
   return false;
 }
 
-void Emitter::emitBasicBlock(const MachineBasicBlock &MBB) {
+void Emitter::emitBasicBlock(MachineBasicBlock &MBB) {
   if (uint64_t Addr = MCE.getCurrentPCValue())
     BasicBlockAddrs[&MBB] = Addr;
 
@@ -119,11 +120,10 @@
 /// (because this is a forward branch), it keeps track of the information
 /// necessary to resolve this address later (and emits a dummy value).
 ///
-void Emitter::emitPCRelativeBlockAddress(const MachineBasicBlock *MBB) {
+void Emitter::emitPCRelativeBlockAddress(MachineBasicBlock *MBB) {
   // If this is a backwards branch, we already know the address of the target,
   // so just emit the value.
-  std::map<const MachineBasicBlock*, unsigned>::iterator I =
-    BasicBlockAddrs.find(MBB);
+  std::map<MachineBasicBlock*,uint64_t>::iterator I = BasicBlockAddrs.find(MBB);
   if (I != BasicBlockAddrs.end()) {
     emitPCRelativeValue(I->second);
   } else {
@@ -242,6 +242,8 @@
   } else if (Op3.isConstantPoolIndex()) {
     DispVal += MCE.getConstantPoolEntryAddress(Op3.getConstantPoolIndex());
     DispVal += Op3.getOffset();
+  } else if (Op3.isJumpTableIndex()) {
+    DispVal += MCE.getJumpTableEntryAddress(Op3.getJumpTableIndex());
   } else {
     DispVal = Op3.getImmedValue();
   }
@@ -445,6 +447,10 @@
         assert(sizeOfImm(Desc) == 4 &&
                "Don't know how to emit non-pointer values!");
         emitExternalSymbolAddress(MO1.getSymbolName(), false, false);
+      } else if (MO1.isJumpTableIndex()) {
+        assert(sizeOfImm(Desc) == 4 &&
+               "Don't know how to emit non-pointer values!");
+        emitConstant(MCE.getJumpTableEntryAddress(MO1.getJumpTableIndex()), 4);
       } else {
         emitConstant(MO1.getImmedValue(), sizeOfImm(Desc));
       }
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index db2b5dd..3861fc3 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -169,6 +169,7 @@
   setOperationAction(ISD::RET             , MVT::Other, Custom);
   // Darwin ABI issue.
   setOperationAction(ISD::ConstantPool    , MVT::i32  , Custom);
+  setOperationAction(ISD::JumpTable       , MVT::i32  , Custom);
   setOperationAction(ISD::GlobalAddress   , MVT::i32  , Custom);
   setOperationAction(ISD::ExternalSymbol  , MVT::i32  , Custom);
   // 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
@@ -2792,8 +2793,8 @@
     return Chain;
   }
 
-  // ConstantPool, GlobalAddress, and ExternalSymbol are lowered as their
-  // target countpart wrapped in the X86ISD::Wrapper node. Suppose N is
+  // ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as 
+  // their target countpart wrapped in the X86ISD::Wrapper node. Suppose N is
   // one of the above mentioned nodes. It has to be wrapped because otherwise
   // Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only
   // be used to form addressing mode. These wrapped nodes will be selected
@@ -2812,6 +2813,20 @@
 
     return Result;
   }
+  case ISD::JumpTable: {
+    JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+    SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
+                                   DAG.getTargetJumpTable(JT->getIndex(),
+                                                          getPointerTy()));
+    if (Subtarget->isTargetDarwin()) {
+      // With PIC, the address is actually $g + Offset.
+      if (getTargetMachine().getRelocationModel() == Reloc::PIC)
+        Result = DAG.getNode(ISD::ADD, getPointerTy(),
+                DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);    
+    }
+
+    return Result;
+  }
   case ISD::GlobalAddress: {
     GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
     SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 172f33e..84d824d 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -365,10 +365,18 @@
   class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
         I<opcode, RawFrm, ops, asm, pattern>;
 
-// Conditional branches
+// Indirect branches
 let isBarrier = 1 in
   def JMP : IBr<0xE9, (ops brtarget:$dst), "jmp $dst", [(br bb:$dst)]>;
 
+let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in {
+  def JMP32r     : I<0xFF, MRM4r, (ops R32:$dst), "jmp{l} {*}$dst",
+                     [(brind R32:$dst)]>;
+  def JMP32m     : I<0xFF, MRM4m, (ops i32mem:$dst), "jmp{l} {*}$dst",
+                     [(brind (loadi32 addr:$dst))]>;
+}
+
+// Conditional branches
 def JE  : IBr<0x84, (ops brtarget:$dst), "je $dst",
               [(X86brcond bb:$dst, X86_COND_E)]>, TB;
 def JNE : IBr<0x85, (ops brtarget:$dst), "jne $dst",
@@ -2302,16 +2310,20 @@
 
 // ConstantPool GlobalAddress, ExternalSymbol
 def : Pat<(i32 (X86Wrapper tconstpool  :$dst)), (MOV32ri tconstpool  :$dst)>;
+def : Pat<(i32 (X86Wrapper tjumptable  :$dst)), (MOV32ri tjumptable  :$dst)>;
 def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>;
 def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>;
 
 def : Pat<(add R32:$src1, (X86Wrapper tconstpool:$src2)),
           (ADD32ri R32:$src1, tconstpool:$src2)>;
+def : Pat<(add R32:$src1, (X86Wrapper tjumptable:$src2)),
+          (ADD32ri R32:$src1, tjumptable:$src2)>;
 def : Pat<(add R32:$src1, (X86Wrapper tglobaladdr :$src2)),
           (ADD32ri R32:$src1, tglobaladdr:$src2)>;
 def : Pat<(add R32:$src1, (X86Wrapper texternalsym:$src2)),
           (ADD32ri R32:$src1, texternalsym:$src2)>;
 
+// FIXME: can you really ever store to a constant pool?
 def : Pat<(store (X86Wrapper tconstpool:$src), addr:$dst),
           (MOV32mi addr:$dst, tconstpool:$src)>;
 def : Pat<(store (X86Wrapper tglobaladdr:$src), addr:$dst),
diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp
index 718a95b..5f75855 100755
--- a/lib/Target/X86/X86IntelAsmPrinter.cpp
+++ b/lib/Target/X86/X86IntelAsmPrinter.cpp
@@ -112,14 +112,9 @@
   case MachineOperand::MO_UnextendedImmed:
     O << (int)MO.getImmedValue();
     return;
-  case MachineOperand::MO_MachineBasicBlock: {
-    MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
-    O << PrivateGlobalPrefix << "BB"
-      << Mang->getValueName(MBBOp->getParent()->getFunction())
-      << "_" << MBBOp->getNumber () << "\t# "
-      << MBBOp->getBasicBlock ()->getName ();
+  case MachineOperand::MO_MachineBasicBlock:
+    printBasicBlockLabel(MO.getMachineBasicBlock());
     return;
-  }
   case MachineOperand::MO_PCRelativeDisp:
     assert(0 && "Shouldn't use addPCDisp() when building X86 MachineInstrs");
     abort ();