From 637d89fe0eca4fa2b9c95f6c15eb69a99bae83bc Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 22 Sep 2010 23:27:36 +0000 Subject: [PATCH] Add support for ELF PLT references for ARM MC asm printing. Adding a new VariantKind to the MCSymbolExpr seems like overkill, but I'm not sure there's a more straightforward way to get the printing difference captured. (i.e., x86 uses @PLT, ARM uses (PLT)). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114613 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCExpr.h | 1 + lib/MC/MCExpr.cpp | 9 ++++++--- lib/Target/ARM/ARMBaseInfo.h | 6 +++++- lib/Target/ARM/ARMISelLowering.cpp | 20 +++++++++++++++---- lib/Target/ARM/ARMMCInstLower.cpp | 31 +++++++++++++++++++++--------- lib/Target/ARM/ARMMCInstLower.h | 3 ++- 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 1f9b8f25674..06f9cd3bc42 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -137,6 +137,7 @@ public: VK_TPOFF, VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the asm file) VK_ARM_LO16, // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the asm file) + VK_ARM_PLT, // ARM-style PLT symbol references. i.e., (PLT) instead of @PLT VK_TLVP // Mach-O thread local variable relocation }; diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 343f3347523..ddd82f3f622 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -50,9 +50,11 @@ void MCExpr::print(raw_ostream &OS) const { else OS << Sym; - if (SRE.getKind() != MCSymbolRefExpr::VK_None && - SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 && - SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16) + if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT) + OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + else if (SRE.getKind() != MCSymbolRefExpr::VK_None && + SRE.getKind() != MCSymbolRefExpr::VK_ARM_HI16 && + SRE.getKind() != MCSymbolRefExpr::VK_ARM_LO16) OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); return; @@ -177,6 +179,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_TPOFF: return "TPOFF"; case VK_ARM_HI16: return ":upper16:"; case VK_ARM_LO16: return ":lower16:"; + case VK_ARM_PLT: return "(PLT)"; case VK_TLVP: return "TLVP"; } } diff --git a/lib/Target/ARM/ARMBaseInfo.h b/lib/Target/ARM/ARMBaseInfo.h index a460a5c05ca..2da7be25a13 100644 --- a/lib/Target/ARM/ARMBaseInfo.h +++ b/lib/Target/ARM/ARMBaseInfo.h @@ -181,7 +181,11 @@ namespace ARMII { /// MO_HI16 - On a symbol operand, this represents a relocation containing /// higher 16 bit of the address. Used only via movt instruction. - MO_HI16 + MO_HI16, + + /// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a + /// call operand. + MO_PLT }; } // end namespace ARMII diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index dc68d3980f6..ae1fead462d 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1195,8 +1195,14 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); Callee = DAG.getNode(ARMISD::PIC_ADD, dl, getPointerTy(), Callee, PICLabel); - } else - Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy()); + } else { + // On ELF targets for PIC code, direct calls should go through the PLT + unsigned OpFlags = 0; + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_) + OpFlags = ARMII::MO_PLT; + Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), 0, OpFlags); + } } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { isDirect = true; bool isStub = Subtarget->isTargetDarwin() && @@ -1217,8 +1223,14 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); Callee = DAG.getNode(ARMISD::PIC_ADD, dl, getPointerTy(), Callee, PICLabel); - } else - Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy()); + } else { + unsigned OpFlags = 0; + // On ELF targets for PIC code, direct calls should go through the PLT + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_) + OpFlags = ARMII::MO_PLT; + Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), OpFlags); + } } // FIXME: handle tail calls differently. diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp index ecd289c7962..e2155f1a02a 100644 --- a/lib/Target/ARM/ARMMCInstLower.cpp +++ b/lib/Target/ARM/ARMMCInstLower.cpp @@ -33,7 +33,6 @@ MCSymbol *ARMMCInstLower::GetGlobalAddressSymbol(const GlobalValue *GV) const { const MCSymbolRefExpr *ARMMCInstLower:: GetSymbolRef(const MachineOperand &MO) const { assert(MO.isGlobal() && "Isn't a global address reference?"); - // FIXME: HANDLE PLT references how?? const MCSymbolRefExpr *SymRef; const MCSymbol *Symbol = GetGlobalAddressSymbol(MO.getGlobal()); @@ -49,22 +48,36 @@ GetSymbolRef(const MachineOperand &MO) const { case ARMII::MO_HI16: SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx); break; + case ARMII::MO_PLT: + SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); + break; } return SymRef; } -MCSymbol *ARMMCInstLower:: +const MCSymbolRefExpr *ARMMCInstLower:: GetExternalSymbolSymbol(const MachineOperand &MO) const { - // FIXME: HANDLE PLT references how?? - // FIXME: This probably needs to be merged with the above SymbolRef stuff - // to handle :lower16: and :upper16: (?) + const MCSymbolRefExpr *SymRef; + const MCSymbol *Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName()); + switch (MO.getTargetFlags()) { - default: assert(0 && "Unknown target flag on GV operand"); - case 0: break; + default: assert(0 && "Unknown target flag on external symbol operand"); + case 0: + SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); + break; + case ARMII::MO_LO16: + SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx); + break; + case ARMII::MO_HI16: + SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx); + break; + case ARMII::MO_PLT: + SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); + break; } - return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); + return SymRef; } @@ -157,7 +170,7 @@ void ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { MCOp = LowerSymbolRefOperand(MO, GetSymbolRef(MO)); break; case MachineOperand::MO_ExternalSymbol: - MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + MCOp = LowerSymbolRefOperand(MO, GetExternalSymbolSymbol(MO)); break; case MachineOperand::MO_JumpTableIndex: MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); diff --git a/lib/Target/ARM/ARMMCInstLower.h b/lib/Target/ARM/ARMMCInstLower.h index 79ed2e9c484..c4d27f88df1 100644 --- a/lib/Target/ARM/ARMMCInstLower.h +++ b/lib/Target/ARM/ARMMCInstLower.h @@ -43,7 +43,8 @@ public: //MCSymbol *GetPICBaseSymbol() const; MCSymbol *GetGlobalAddressSymbol(const GlobalValue *GV) const; const MCSymbolRefExpr *GetSymbolRef(const MachineOperand &MO) const; - MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + const MCSymbolRefExpr *GetExternalSymbolSymbol(const MachineOperand &MO) + const; MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; MCOperand LowerSymbolRefOperand(const MachineOperand &MO,