From 44ad4d00b497d0931c73136ca0ce14882a4a60e0 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Fri, 7 Feb 2014 04:24:35 +0000 Subject: [PATCH] [Sparc] Emit correct relocations for PIC code when integrated assembler is used. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200961 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 24 ++++++++++ .../MCTargetDesc/SparcELFObjectWriter.cpp | 37 +++++++++++++++- .../Sparc/MCTargetDesc/SparcFixupKinds.h | 15 +++++++ .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 44 +++++-------------- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp | 31 ++++++++++++- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h | 10 +++++ lib/Target/Sparc/SparcAsmPrinter.cpp | 4 +- lib/Target/Sparc/SparcISelLowering.cpp | 17 ++++--- test/CodeGen/SPARC/obj-relocs.ll | 33 ++++++++++++++ 9 files changed, 172 insertions(+), 43 deletions(-) create mode 100644 test/CodeGen/SPARC/obj-relocs.ll diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 6a42d281178..6c14e5adfc8 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -26,14 +26,19 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_Data_4: case FK_Data_8: return Value; + case Sparc::fixup_sparc_wplt30: case Sparc::fixup_sparc_call30: return (Value >> 2) & 0x3fffffff; case Sparc::fixup_sparc_br22: return (Value >> 2) & 0x3fffff; case Sparc::fixup_sparc_br19: return (Value >> 2) & 0x7ffff; + case Sparc::fixup_sparc_pc22: + case Sparc::fixup_sparc_got22: case Sparc::fixup_sparc_hi22: return (Value >> 10) & 0x3fffff; + case Sparc::fixup_sparc_pc10: + case Sparc::fixup_sparc_got10: case Sparc::fixup_sparc_lo10: return Value & 0x3ff; case Sparc::fixup_sparc_h44: @@ -72,6 +77,11 @@ namespace { { "fixup_sparc_l44", 20, 12, 0 }, { "fixup_sparc_hh", 10, 22, 0 }, { "fixup_sparc_hm", 22, 10, 0 }, + { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_got22", 10, 22, 0 }, + { "fixup_sparc_got10", 22, 10, 0 }, + { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel } }; if (Kind < FirstTargetFixupKind) @@ -82,6 +92,20 @@ namespace { return Infos[Kind - FirstTargetFixupKind]; } + void processFixupValue(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFixup &Fixup, + const MCFragment *DF, + MCValue & Target, + uint64_t &Value, + bool &IsResolved) { + switch ((Sparc::Fixups)Fixup.getKind()) { + default: break; + case Sparc::fixup_sparc_wplt30: IsResolved = false; break; + } + } + + bool mayNeedRelaxation(const MCInst &Inst) const { // FIXME. return false; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp index 7410c9395bc..da1b9999c13 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "MCTargetDesc/SparcMCTargetDesc.h" #include "MCTargetDesc/SparcFixupKinds.h" +#include "MCTargetDesc/SparcMCExpr.h" +#include "MCTargetDesc/SparcMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" @@ -31,6 +32,11 @@ namespace { bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const; + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const; }; } @@ -40,6 +46,12 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const { + + if (const SparcMCExpr *SExpr = dyn_cast(Fixup.getValue())) { + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32) + return ELF::R_SPARC_DISP32; + } + if (IsPCRel) { switch((unsigned)Fixup.getKind()) { default: @@ -51,6 +63,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; + case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; + case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; + case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; } } @@ -74,10 +89,30 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; + case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; + case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; } + return ELF::R_SPARC_NONE; } +const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + + if (!Target.getSymA()) + return NULL; + switch((unsigned)Fixup.getKind()) { + default: break; + case Sparc::fixup_sparc_got22: + case Sparc::fixup_sparc_got10: + return &Target.getSymA()->getSymbol().AliasedSymbol(); + } + return NULL; +} + MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI) { diff --git a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h index 48b5f905497..ff6e6cbadd7 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -48,6 +48,21 @@ namespace llvm { /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo) fixup_sparc_hm, + /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo) + fixup_sparc_pc22, + + /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo) + fixup_sparc_pc10, + + /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo) + fixup_sparc_got22, + + /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo) + fixup_sparc_got10, + + /// fixup_sparc_wplt30 + fixup_sparc_wplt30, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp index 8c318274a45..0328b3f7376 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -101,37 +101,8 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, assert(MO.isExpr()); const MCExpr *Expr = MO.getExpr(); if (const SparcMCExpr *SExpr = dyn_cast(Expr)) { - switch(SExpr->getKind()) { - default: assert(0 && "Unhandled sparc expression!"); break; - case SparcMCExpr::VK_Sparc_LO: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_lo10)); - break; - case SparcMCExpr::VK_Sparc_HI: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_hi22)); - break; - case SparcMCExpr::VK_Sparc_H44: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_h44)); - break; - case SparcMCExpr::VK_Sparc_M44: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_m44)); - break; - case SparcMCExpr::VK_Sparc_L44: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_l44)); - break; - case SparcMCExpr::VK_Sparc_HH: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_hh)); - break; - case SparcMCExpr::VK_Sparc_HM: - Fixups.push_back(MCFixup::Create(0, Expr, - (MCFixupKind)Sparc::fixup_sparc_hm)); - break; - } + MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); + Fixups.push_back(MCFixup::Create(0, Expr, Kind)); return 0; } @@ -151,8 +122,15 @@ getCallTargetOpValue(const MCInst &MI, unsigned OpNo, if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)Sparc::fixup_sparc_call30)); + MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; + + if (const SparcMCExpr *SExpr = dyn_cast(MO.getExpr())) { + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) + fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; + } + + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind)); + return 0; } diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp index f38e3118184..4a83c96a924 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -17,6 +17,7 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCELF.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Object/ELF.h" @@ -54,6 +55,13 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) case VK_Sparc_L44: OS << "%l44("; break; case VK_Sparc_HH: OS << "%hh("; break; case VK_Sparc_HM: OS << "%hm("; break; + // FIXME: use %pc22/%pc10, if system assembler supports them. + case VK_Sparc_PC22: OS << "%hi("; break; + case VK_Sparc_PC10: OS << "%lo("; break; + // FIXME: use %got22/%got10, if system assembler supports them. + case VK_Sparc_GOT22: OS << "%hi("; break; + case VK_Sparc_GOT10: OS << "%lo("; break; + case VK_Sparc_WPLT30: closeParen = false; break; case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; @@ -87,6 +95,10 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) .Case("l44", VK_Sparc_L44) .Case("hh", VK_Sparc_HH) .Case("hm", VK_Sparc_HM) + .Case("pc22", VK_Sparc_PC22) + .Case("pc10", VK_Sparc_PC10) + .Case("got22", VK_Sparc_GOT22) + .Case("got10", VK_Sparc_GOT10) .Case("r_disp32", VK_Sparc_R_DISP32) .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) @@ -109,9 +121,26 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) .Default(VK_Sparc_None); } +Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { + switch (Kind) { + default: assert(0 && "Unhandled SparcMCExpr::VariantKind"); + case VK_Sparc_LO: return Sparc::fixup_sparc_lo10; + case VK_Sparc_HI: return Sparc::fixup_sparc_hi22; + case VK_Sparc_H44: return Sparc::fixup_sparc_h44; + case VK_Sparc_M44: return Sparc::fixup_sparc_m44; + case VK_Sparc_L44: return Sparc::fixup_sparc_l44; + case VK_Sparc_HH: return Sparc::fixup_sparc_hh; + case VK_Sparc_HM: return Sparc::fixup_sparc_hm; + case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22; + case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; + case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; + case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; + } +} + bool SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const { + const MCAsmLayout *Layout) const { if (!Layout) return false; return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h index ebe3a752a6f..be6526e8ade 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -15,6 +15,7 @@ #ifndef LLVM_SPARCMCEXPR_H #define LLVM_SPARCMCEXPR_H +#include "SparcFixupKinds.h" #include "llvm/MC/MCExpr.h" namespace llvm { @@ -31,6 +32,11 @@ public: VK_Sparc_L44, VK_Sparc_HH, VK_Sparc_HM, + VK_Sparc_PC22, + VK_Sparc_PC10, + VK_Sparc_GOT22, + VK_Sparc_GOT10, + VK_Sparc_WPLT30, VK_Sparc_R_DISP32, VK_Sparc_TLS_GD_HI22, VK_Sparc_TLS_GD_LO10, @@ -75,6 +81,9 @@ public: /// getSubExpr - Get the child of this expression. const MCExpr *getSubExpr() const { return Expr; } + /// getFixupKind - Get the fixup kind of this expression. + Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); } + /// @} void PrintImpl(raw_ostream &OS) const; bool EvaluateAsRelocatableImpl(MCValue &Res, @@ -94,6 +103,7 @@ public: static VariantKind parseVariantKind(StringRef name); static bool printVariantKind(raw_ostream &OS, VariantKind Kind); + static Sparc::Fixups getFixupKind(VariantKind Kind); }; } // end namespace llvm. diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index c76d5e940e8..50506a68476 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -242,12 +242,12 @@ void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, MCOperand Callee = createPCXCallOP(EndLabel, OutContext); EmitCall(OutStreamer, Callee, STI); OutStreamer.EmitLabel(SethiLabel); - MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI, + MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22, GOTLabel, StartLabel, SethiLabel, OutContext); EmitSETHI(OutStreamer, hiImm, MCRegOP, STI); OutStreamer.EmitLabel(EndLabel); - MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO, + MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10, GOTLabel, StartLabel, EndLabel, OutContext); EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP, STI); diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index e48c2e7df07..7ad87b34af6 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -897,10 +897,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. + unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) + ? SparcMCExpr::VK_Sparc_WPLT30 : 0); if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF); // Returns a chain & a flag for retval copy to use SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); @@ -1211,10 +1213,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // Likewise ExternalSymbol -> TargetExternalSymbol. SDValue Callee = CLI.Callee; bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); + unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) + ? SparcMCExpr::VK_Sparc_WPLT30 : 0); if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy()); + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, + TF); else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy()); + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF); // Build the operands for the call instruction itself. SmallVector Ops; @@ -1798,8 +1803,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { // Handle PIC mode first. if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { // This is the pic32 code model, the GOT is known to be smaller than 4GB. - SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, - SparcMCExpr::VK_Sparc_LO, DAG); + SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, + SparcMCExpr::VK_Sparc_GOT10, DAG); SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo); // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this diff --git a/test/CodeGen/SPARC/obj-relocs.ll b/test/CodeGen/SPARC/obj-relocs.ll new file mode 100644 index 00000000000..62bafafb974 --- /dev/null +++ b/test/CodeGen/SPARC/obj-relocs.ll @@ -0,0 +1,33 @@ +; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=static | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-ABS +; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=pic | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-PIC + +;CHECK-ABS: Relocations [ +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_H44 AGlobalVar 0x0 +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_M44 AGlobalVar 0x0 +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_L44 AGlobalVar 0x0 +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0 +;CHECK-ABS:] + +; CHECK-PIC: Relocations [ +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0 +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0 +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0 +; CHECK-PIC: ] + + +@AGlobalVar = global i64 0, align 8 + +; CHECK-ASM: sethi %h44(AGlobalVar), [[R:%[goli][0-7]]] +; CHECK-ASM: add [[R]], %m44(AGlobalVar), [[R]] +define i64 @foo(i64 %a) { +entry: + %0 = load i64* @AGlobalVar, align 4 + %1 = add i64 %a, %0 + %2 = call i64 @bar(i64 %1) + ret i64 %2 +} + + +declare i64 @bar(i64)