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 | |
parent | 5cbf985dcbc89fba3208e7baf8b6f488b06d3ec9 (diff) |
- 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')
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.cpp | 28 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantPoolValue.cpp | 30 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantPoolValue.h | 21 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 36 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 5 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 21 |
7 files changed, 96 insertions, 47 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index dee4640d2e..e61b5a2764 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -122,10 +122,15 @@ namespace { ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV; GlobalValue *GV = ACPV->getGV(); - std::string Name = Mang->getValueName(GV); + std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); + if (!GV) + Name += ACPV->getSymbol(); if (ACPV->isNonLazyPointer()) { GVNonLazyPtrs.insert(Name); O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; + } else if (ACPV->isStub()) { + FnStubs.insert(Name); + O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; } else O << Name; if (ACPV->getPCAdjustment() != 0) @@ -136,7 +141,7 @@ namespace { // If the constant pool value is a extern weak symbol, remember to emit // the weak reference. - if (GV->hasExternalWeakLinkage()) + if (GV && GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); } @@ -680,18 +685,29 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) { ++EmittedInsts; - if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) { + int Opc = MI->getOpcode(); + switch (Opc) { + case ARM::CONSTPOOL_ENTRY: if (!InCPMode && AFI->isThumbFunction()) { EmitAlignment(2); InCPMode = true; } - } else { + break; + default: { if (InCPMode && AFI->isThumbFunction()) { EmitAlignment(1); InCPMode = false; } - O << "\t"; - } + switch (Opc) { + case ARM::PICADD: + case ARM::PICLD: + case ARM::tPICADD: + break; + default: + O << "\t"; + break; + } + }} // Call the autogenerated instruction printer routines. printInstruction(MI); diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index 97cca07d33..a219c352ba 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -14,12 +14,20 @@ #include "ARMConstantPoolValue.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/GlobalValue.h" +#include "llvm/Type.h" using namespace llvm; ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id, - bool isNonLazy, unsigned char PCAdj) + ARMCP::ARMCPKind k, + unsigned char PCAdj) : MachineConstantPoolValue((const Type*)gv->getType()), - GV(gv), LabelId(id), isNonLazyPtr(isNonLazy), PCAdjust(PCAdj) {} + GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj) {} + +ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id, + ARMCP::ARMCPKind k, + unsigned char PCAdj) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj) {} int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) { @@ -30,8 +38,11 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, (Constants[i].Offset & AlignMask) == 0) { ARMConstantPoolValue *CPV = (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; - if (CPV->GV == GV && CPV->LabelId == LabelId && - CPV->isNonLazyPtr == isNonLazyPtr) + if (CPV->GV == GV && + CPV->S == S && + CPV->LabelId == LabelId && + CPV->Kind == Kind && + CPV->PCAdjust == PCAdjust) return i; } } @@ -42,14 +53,19 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, void ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { ID.AddPointer(GV); + ID.AddPointer(S); ID.AddInteger(LabelId); - ID.AddInteger((unsigned)isNonLazyPtr); + ID.AddInteger((unsigned)Kind); ID.AddInteger(PCAdjust); } void ARMConstantPoolValue::print(std::ostream &O) const { - O << GV->getName(); - if (isNonLazyPtr) O << "$non_lazy_ptr"; + if (GV) + O << GV->getName(); + else + O << S; + if (isNonLazyPointer()) O << "$non_lazy_ptr"; + else if (isStub()) O << "$stub"; if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+" << (unsigned)PCAdjust << ")"; } diff --git a/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h index a9143d4ddc..a614bec60f 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.h +++ b/lib/Target/ARM/ARMConstantPoolValue.h @@ -18,23 +18,38 @@ namespace llvm { +namespace ARMCP { + enum ARMCPKind { + CPValue, + CPNonLazyPtr, + CPStub + }; +} + /// ARMConstantPoolValue - ARM specific constantpool value. This is used to /// represent PC relative displacement between the address of the load /// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)). class ARMConstantPoolValue : public MachineConstantPoolValue { GlobalValue *GV; // GlobalValue being loaded. + const char *S; // ExtSymbol being loaded. unsigned LabelId; // Label id of the load. - bool isNonLazyPtr; // True if loading a Mac OS X non_lazy_ptr stub. + ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub? unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative. // 8 for ARM, 4 for Thumb. public: - ARMConstantPoolValue(GlobalValue *gv, unsigned id, bool isNonLazy = false, + ARMConstantPoolValue(GlobalValue *gv, unsigned id, + ARMCP::ARMCPKind Kind = ARMCP::CPValue, + unsigned char PCAdj = 0); + ARMConstantPoolValue(const char *s, unsigned id, + ARMCP::ARMCPKind Kind = ARMCP::CPValue, unsigned char PCAdj = 0); GlobalValue *getGV() const { return GV; } + const char *getSymbol() const { return S; } unsigned getLabelId() const { return LabelId; } - bool isNonLazyPointer() const { return isNonLazyPtr; } + bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; } + bool isStub() const { return Kind == ARMCP::CPStub; } unsigned char getPCAdjustment() const { return PCAdjust; } virtual int getExistingMachineCPValue(MachineConstantPool *CP, 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); diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 5f7ed65a3e..0dbc3d6b32 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -31,8 +31,6 @@ namespace llvm { Wrapper, // Wrapper - A wrapper node for TargetConstantPool, // TargetExternalSymbol, and TargetGlobalAddress. - WrapperCall, // WrapperCall - Same as wrapper, but mark the wrapped - // node as call operand. WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable CALL, // Function call. diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 63aea02d68..b83cdca6df 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -41,7 +41,6 @@ def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, // Node definitions. def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; -def ARMWrapperCall : SDNode<"ARMISD::WrapperCall", SDTIntUnaryOp>; def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>; def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeq, @@ -514,11 +513,11 @@ PseudoInst<(ops i32imm:$line, i32imm:$col, i32imm:$file), [(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>; def PICADD : AI1<(ops GPR:$dst, GPR:$a, pclabel:$cp), - "\n$cp:\n\tadd $dst, pc, $a", + "$cp:\n\tadd $dst, pc, $a", [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; let AddedComplexity = 10 in def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr), - "\n${addr:label}:\n\tldr $dst, $addr", + "${addr:label}:\n\tldr $dst, $addr", [(set GPR:$dst, (load addrmodepc:$addr))]>; //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index f806754fd5..c5a48fcd0d 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -158,7 +158,7 @@ def t_addrmode_sp : Operand<i32>, // def tPICADD : TIt<(ops GPR:$dst, GPR:$lhs, pclabel:$cp), - "\n$cp:\n\tadd $dst, pc", + "$cp:\n\tadd $dst, pc", [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>; //===----------------------------------------------------------------------===// @@ -475,25 +475,18 @@ let usesCustomDAGSchedInserter = 1 in // Expanded by the scheduler. // tLEApcrel - Load a pc-relative address into a register without offending the // assembler. -def tLEApcrel : TI<(ops GPR:$dst, i32imm:$label), +def tLEApcrel : TIx2<(ops GPR:$dst, i32imm:$label), !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(", "${:private}PCRELL${:uid}+4))\n"), !strconcat("${:private}PCRELL${:uid}:\n\t", - "add $dst, pc, #PCRELV${:uid}")), + "mov $dst, #PCRELV${:uid}\n\tadd $dst, pc")), []>; -def tLEApcrelCall : TI<(ops GPR:$dst, i32imm:$label), - !strconcat(!strconcat(".set PCRELV${:uid}, (${label:call}-(", - "${:private}PCRELL${:uid}+4))\n"), - !strconcat("${:private}PCRELL${:uid}:\n\t", - "add $dst, pc, #PCRELV${:uid}")), - []>; - -def tLEApcrelJT : TI<(ops GPR:$dst, i32imm:$label, i32imm:$id), +def tLEApcrelJT : TIx2<(ops GPR:$dst, i32imm:$label, i32imm:$id), !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(", "${:private}PCRELL${:uid}+4))\n"), !strconcat("${:private}PCRELL${:uid}:\n\t", - "add $dst, pc, #PCRELV${:uid}")), + "mov $dst, #PCRELV${:uid}\n\tadd $dst, pc")), []>; //===----------------------------------------------------------------------===// @@ -503,10 +496,6 @@ def tLEApcrelJT : TI<(ops GPR:$dst, i32imm:$label, i32imm:$id), // ConstantPool, GlobalAddress def : ThumbPat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>; def : ThumbPat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>; -def : ThumbPat<(ARMWrapperCall tglobaladdr :$dst), - (tLEApcrelCall tglobaladdr :$dst)>; -def : ThumbPat<(ARMWrapperCall texternalsym:$dst), - (tLEApcrelCall texternalsym:$dst)>; // JumpTable def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id), |