summaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
authorLauro Ramos Venancio <lauro.venancio@gmail.com>2007-04-22 00:04:12 +0000
committerLauro Ramos Venancio <lauro.venancio@gmail.com>2007-04-22 00:04:12 +0000
commit0ae4a3357a556261f25b1584a2d9914637c69e65 (patch)
tree50dc3483a2a5d6535fd82ad1f354d5df756395e5 /lib/Target/ARM/ARMISelLowering.cpp
parent88894b6c40cf2d94a1c9ab8435cf6ed6c622692a (diff)
downloadllvm-0ae4a3357a556261f25b1584a2d9914637c69e65.tar.gz
llvm-0ae4a3357a556261f25b1584a2d9914637c69e65.tar.bz2
llvm-0ae4a3357a556261f25b1584a2d9914637c69e65.tar.xz
Implement PIC for arm-linux.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36324 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp53
1 files changed, 49 insertions, 4 deletions
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();
}