From 0ae4a3357a556261f25b1584a2d9914637c69e65 Mon Sep 17 00:00:00 2001 From: Lauro Ramos Venancio Date: Sun, 22 Apr 2007 00:04:12 +0000 Subject: [PATCH] Implement PIC for arm-linux. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36324 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMAsmPrinter.cpp | 8 +++- lib/Target/ARM/ARMConstantPoolValue.cpp | 20 ++++++++-- lib/Target/ARM/ARMConstantPoolValue.h | 10 ++++- lib/Target/ARM/ARMISelLowering.cpp | 53 +++++++++++++++++++++++-- lib/Target/ARM/ARMISelLowering.h | 4 +- test/CodeGen/ARM/call.ll | 2 + test/CodeGen/ARM/load-global.ll | 4 +- 7 files changed, 88 insertions(+), 13 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 109ae215ad8..625dd9d8856 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 a219c352ba5..1fe66fb174b 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 a614bec60fe..b7511aa8dd6 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 0cef4cce68f..780e49058f5 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(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(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 90964315d3b..5b182f9b5b0 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); }; diff --git a/test/CodeGen/ARM/call.ll b/test/CodeGen/ARM/call.ll index c270d7e53b9..c7e10b13e8f 100644 --- a/test/CodeGen/ARM/call.ll +++ b/test/CodeGen/ARM/call.ll @@ -1,5 +1,7 @@ ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep {mov lr, pc} ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mattr=+v5t | grep blx +; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mtriple=arm-linux-gnueabi\ +; RUN: -relocation-model=pic | grep {PLT} %t = weak global int ()* null declare void %g(int, int, int, int) diff --git a/test/CodeGen/ARM/load-global.ll b/test/CodeGen/ARM/load-global.ll index 3c287d473a4..1afa9e993d6 100644 --- a/test/CodeGen/ARM/load-global.ll +++ b/test/CodeGen/ARM/load-global.ll @@ -1,10 +1,12 @@ -; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm ; RUN: llvm-upgrade < %s | llvm-as | \ ; RUN: llc -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic | \ ; RUN: grep {L_G\$non_lazy_ptr} | wc -l | grep 2 ; RUN: llvm-upgrade < %s | llvm-as | \ ; RUN: llc -mtriple=arm-apple-darwin -relocation-model=pic | \ ; RUN: grep {ldr.*pc} | wc -l | grep 1 +; RUN: llvm-upgrade < %s | llvm-as | \ +; RUN: llc -mtriple=arm-linux-gnueabi -relocation-model=pic | \ +; RUN: grep {GOT} | wc -l | grep 1 %G = external global int -- 2.34.1