diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8d0ea662dc0..8d070664b1c 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4507,14 +4507,25 @@ X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) { JumpTableSDNode *JT = cast(Op); - // FIXME there isn't really any debug into here - DebugLoc dl = JT->getDebugLoc(); - SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy()); - Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result); + + // In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the + // global base reg. + unsigned char JTFlag = 0; + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + if (Subtarget->isPICStyleStub()) + JTFlag = X86II::MO_PIC_BASE_OFFSET; + else if (Subtarget->isPICStyleGOT()) + JTFlag = X86II::MO_GOTOFF; + } + + SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy(), + JTFlag); + DebugLoc DL = JT->getDebugLoc(); + Result = DAG.getNode(X86ISD::Wrapper, DL, getPointerTy(), Result); + // With PIC, the address is actually $g + Offset. - if (getTargetMachine().getRelocationModel() == Reloc::PIC_ && - !Subtarget->isPICStyleRIPRel()) { - Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), + if (JTFlag) { + Result = DAG.getNode(ISD::ADD, DL, getPointerTy(), DAG.getNode(X86ISD::GlobalBaseReg, DebugLoc::getUnknownLoc(), getPointerTy()), diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index f8b5e5e53ab..b4ba5f0dc00 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -77,9 +77,19 @@ namespace X86II { /// MO_GOT_ABSOLUTE_ADDRESS - On a symbol operand, this represents a /// relocation of: - /// $SYMBOL_LABEL + [. - PICBASELABEL] + /// SYMBOL_LABEL + [. - PICBASELABEL] MO_GOT_ABSOLUTE_ADDRESS = 1, + /// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the + /// immediate should get the value of the symbol minus the PIC base label: + /// SYMBOL_LABEL - PICBASELABEL + MO_PIC_BASE_OFFSET = 2, + + /// MO_GOTOFF - On a symbol operand this indicates that the immediate should + /// the offset to the location of the symbol name from the base of the GOT. + /// SYMBOL_LABEL @GOTOFF + MO_GOTOFF = 3, + //===------------------------------------------------------------------===// // Instruction encodings. These are the standard/most common forms for X86