diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.cpp | 8 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantPoolValue.cpp | 20 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantPoolValue.h | 10 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 53 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 4 |
5 files changed, 83 insertions, 12 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 109ae215ad..625dd9d885 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -133,6 +133,7 @@ namespace { O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; } else O << Name; + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; if (ACPV->getPCAdjustment() != 0) O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" << utostr(ACPV->getLabelId()) @@ -284,7 +285,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, FnStubs.insert(Name); } else O << Name; - + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); break; @@ -299,6 +302,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum, FnStubs.insert(Name); } else O << Name; + if (isCallOp && Subtarget->isTargetELF() && + TM.getRelocationModel() == Reloc::PIC_) + O << "(PLT)"; break; } case MachineOperand::MO_ConstantPoolIndex: diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index a219c352ba..1fe66fb174 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -19,15 +19,26 @@ using namespace llvm; ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id, ARMCP::ARMCPKind k, - unsigned char PCAdj) + unsigned char PCAdj, + const char *Modif) : MachineConstantPoolValue((const Type*)gv->getType()), - GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj) {} + GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif) {} ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id, ARMCP::ARMCPKind k, - unsigned char PCAdj) + unsigned char PCAdj, + const char *Modif) : MachineConstantPoolValue((const Type*)Type::Int32Ty), - GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj) {} + GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif) {} + +ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, + ARMCP::ARMCPKind k, + const char *Modif) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0), + Modifier(Modif) {} int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) { @@ -66,6 +77,7 @@ void ARMConstantPoolValue::print(std::ostream &O) const { O << S; if (isNonLazyPointer()) O << "$non_lazy_ptr"; else if (isStub()) O << "$stub"; + if (Modifier) O << "(" << Modifier << ")"; if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+" << (unsigned)PCAdjust << ")"; } diff --git a/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h index a614bec60f..b7511aa8dd 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.h +++ b/lib/Target/ARM/ARMConstantPoolValue.h @@ -36,17 +36,23 @@ class ARMConstantPoolValue : public MachineConstantPoolValue { ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub? unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative. // 8 for ARM, 4 for Thumb. + const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) public: ARMConstantPoolValue(GlobalValue *gv, unsigned id, ARMCP::ARMCPKind Kind = ARMCP::CPValue, - unsigned char PCAdj = 0); + unsigned char PCAdj = 0, const char *Modifier = NULL); ARMConstantPoolValue(const char *s, unsigned id, ARMCP::ARMCPKind Kind = ARMCP::CPValue, - unsigned char PCAdj = 0); + unsigned char PCAdj = 0, const char *Modifier = NULL); + ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind, + const char *Modifier); + GlobalValue *getGV() const { return GV; } const char *getSymbol() const { return S; } + const char *getModifier() const { return Modifier; } + bool hasModifier() const { return Modifier != NULL; } unsigned getLabelId() const { return LabelId; } bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; } bool isStub() const { return Kind == ARMCP::CPStub; } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 0cef4cce68..780e49058f 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -179,6 +179,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::RET, MVT::Other, Custom); setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom); // Expand mem operations genericly. setOperationAction(ISD::MEMSET , MVT::Other, Expand); @@ -694,6 +695,31 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) { return DAG.getNode(ARMISD::Wrapper, MVT::i32, Res); } +SDOperand ARMTargetLowering::LowerGlobalAddressELF(SDOperand Op, + SelectionDAG &DAG) { + MVT::ValueType PtrVT = getPointerTy(); + GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + if (RelocM == Reloc::PIC_) { + bool UseGOTOFF = GV->hasInternalLinkage(); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, ARMCP::CPValue, UseGOTOFF ? "GOTOFF":"GOT"); + SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2); + CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); + SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); + SDOperand Chain = Result.getValue(1); + SDOperand GOT = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, PtrVT); + Result = DAG.getNode(ISD::ADD, PtrVT, Result, GOT); + if (!UseGOTOFF) + Result = DAG.getLoad(PtrVT, Chain, Result, NULL, 0); + return Result; + } else { + SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); + CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); + return DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); + } +} + /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol /// even in dynamic-no-pic mode. static bool GVIsIndirectSymbol(GlobalValue *GV) { @@ -701,12 +727,12 @@ static bool GVIsIndirectSymbol(GlobalValue *GV) { (GV->isDeclaration() && !GV->hasNotBeenReadFromBytecode())); } -SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op, - SelectionDAG &DAG) { +SDOperand ARMTargetLowering::LowerGlobalAddressDarwin(SDOperand Op, + SelectionDAG &DAG) { MVT::ValueType PtrVT = getPointerTy(); GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); Reloc::Model RelocM = getTargetMachine().getRelocationModel(); - bool IsIndirect = Subtarget->isTargetDarwin() && GVIsIndirectSymbol(GV); + bool IsIndirect = GVIsIndirectSymbol(GV); SDOperand CPAddr; if (RelocM == Reloc::Static) CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); @@ -734,6 +760,22 @@ SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op, return Result; } +SDOperand ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDOperand Op, + SelectionDAG &DAG){ + assert(Subtarget->isTargetELF() && + "GLOBAL OFFSET TABLE not implemented for non-ELF targets"); + MVT::ValueType PtrVT = getPointerTy(); + unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = new ARMConstantPoolValue("_GLOBAL_OFFSET_TABLE_", + ARMPCLabelIndex, + ARMCP::CPValue, PCAdj); + SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2); + CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); + SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0); + SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); + return DAG.getNode(ARMISD::PIC_ADD, PtrVT, Result, PICLabel); +} + static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG, unsigned VarArgsFrameIndex) { // vastart just stores the address of the VarArgsFrameIndex slot into the @@ -1198,7 +1240,9 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Don't know how to custom lower this!"); abort(); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); - case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalAddress: + return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : + LowerGlobalAddressELF(Op, DAG); case ISD::CALL: return LowerCALL(Op, DAG); case ISD::RET: return LowerRET(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, Subtarget); @@ -1220,6 +1264,7 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { return LowerFORMAL_ARGUMENTS(Op, DAG); case ISD::RETURNADDR: break; case ISD::FRAMEADDR: break; + case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG); } return SDOperand(); } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 90964315d3..5b182f9b5b 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -123,7 +123,9 @@ namespace llvm { unsigned ARMPCLabelIndex; SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); - SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGlobalAddressDarwin(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGlobalAddressELF(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG); SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG); }; |