diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 254fea6..ae8a934 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -25,6 +25,7 @@ #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/GlobalValue.h" +#include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -1268,6 +1269,48 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { Chain), 0); return CurDAG->SelectNodeTo(N, Reg, MVT::Other, Chain); } + case PPCISD::TOC_ENTRY: { + assert (PPCSubTarget.isPPC64() && "Only supported for 64-bit ABI"); + + // For medium code model, we generate two instructions as described + // below. Otherwise we allow SelectCodeCommon to handle this, selecting + // one of LDtoc, LDtocJTI, and LDtocCPT. + if (TM.getCodeModel() != CodeModel::Medium) + break; + + // The first source operand is a TargetGlobalAddress or a + // TargetJumpTable. If it is an externally defined symbol, a symbol + // with common linkage, a function address, or a jump table address, + // we generate: + // LDtocL(<ga:@sym>, ADDIStocHA(%X2, <ga:@sym>)) + // Otherwise we generate: + // ADDItocL(ADDIStocHA(%X2, <ga:@sym>), <ga:@sym>) + SDValue GA = N->getOperand(0); + SDValue TOCbase = N->getOperand(1); + SDNode *Tmp = CurDAG->getMachineNode(PPC::ADDIStocHA, dl, MVT::i64, + TOCbase, GA); + + if (isa<JumpTableSDNode>(GA)) + return CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, + SDValue(Tmp, 0)); + + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(GA)) { + const GlobalValue *GValue = G->getGlobal(); + const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GValue); + assert((GVar || isa<Function>(GValue)) && + "Unexpected global value subclass!"); + + // An external variable is one without an initializer. For these, + // for variables with common linkage, and for Functions, generate + // the LDtocL form. + if (!GVar || !GVar->hasInitializer() || GValue->hasCommonLinkage()) + return CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, + SDValue(Tmp, 0)); + } + + return CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, + SDValue(Tmp, 0), GA); + } } return SelectCode(N); |