diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-01-30 20:37:08 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-01-30 20:37:08 +0000 |
commit | c60e76d139a96cc8bb7454929172cdb992e16971 (patch) | |
tree | fe8d8431e2477af5a3c4ab2b2ead8b931904071a /lib/Target/ARM/ARMISelLowering.cpp | |
parent | 5cbf985dcbc89fba3208e7baf8b6f488b06d3ec9 (diff) | |
download | llvm-c60e76d139a96cc8bb7454929172cdb992e16971.tar.gz llvm-c60e76d139a96cc8bb7454929172cdb992e16971.tar.bz2 llvm-c60e76d139a96cc8bb7454929172cdb992e16971.tar.xz |
- Fix codegen for pc relative constant (e.g. JT) in thumb mode:
.set PCRELV0, (LJTI1_0_0-(LPCRELL0+4))
LPCRELL0:
add r1, pc, #PCRELV0
This is not legal since add r1, pc, #c requires the constant be a multiple of 4.
Do the following instead:
.set PCRELV0, (LJTI1_0_0-(LPCRELL0+4))
LPCRELL0:
mov r1, #PCRELV0
add r1, pc
- In thumb mode, it's not possible to use .set generate a pc relative stub
address. The stub is ARM code which is in a different section from the thumb
code. Load the value from a constpool instead.
- Some asm printing clean up.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33664 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 24357cfe16..0b1c3ac629 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -230,7 +230,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return 0; case ARMISD::Wrapper: return "ARMISD::Wrapper"; - case ARMISD::WrapperCall: return "ARMISD::WrapperCall"; case ARMISD::WrapperJT: return "ARMISD::WrapperJT"; case ARMISD::CALL: return "ARMISD::CALL"; case ARMISD::CALL_NOLINK: return "ARMISD::CALL_NOLINK"; @@ -465,25 +464,40 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) { bool isARMFunc = false; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { GlobalValue *GV = G->getGlobal(); - Callee = DAG.getTargetGlobalAddress(GV, getPointerTy()); isDirect = true; bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()); bool isStub = (isExt && Subtarget->isTargetDarwin()) && getTargetMachine().getRelocationModel() != Reloc::Static; isARMFunc = !Subtarget->isThumb() || isStub; - // Wrap it since tBX takes a register source operand. - if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) - Callee = DAG.getNode(ARMISD::WrapperCall, MVT::i32, Callee); + // tBX takes a register source operand. + if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) { + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex, + ARMCP::CPStub, 4); + SDOperand CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 2); + CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), CPAddr, NULL, 0); + SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, getPointerTy(), Callee, PICLabel); + } else + Callee = DAG.getTargetGlobalAddress(GV, getPointerTy()); } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); isDirect = true; bool isStub = Subtarget->isTargetDarwin() && getTargetMachine().getRelocationModel() != Reloc::Static; isARMFunc = !Subtarget->isThumb() || isStub; - // Wrap it since tBX takes a register source operand. - if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) - Callee = DAG.getNode(ARMISD::WrapperCall, MVT::i32, Callee); + // tBX takes a register source operand. + const char *Sym = S->getSymbol(); + if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) { + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(Sym, ARMPCLabelIndex, + ARMCP::CPStub, 4); + SDOperand CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 2); + CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), CPAddr, NULL, 0); + SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, getPointerTy(), Callee, PICLabel); + } else + Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy()); } std::vector<MVT::ValueType> NodeTys; @@ -647,8 +661,10 @@ SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op, else { unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb() ? 4 : 8); + ARMCP::ARMCPKind Kind = IsIndirect ? ARMCP::CPNonLazyPtr + : ARMCP::CPValue; ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex, - IsIndirect, PCAdj); + Kind, PCAdj); CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2); } CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr); |