diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 18404fcfef..fac2806c12 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -123,6 +123,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) // 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 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) { 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 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { 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); |