[llvm] r231475 - [AsmPrinter][TLOF] 32-bit MachO support for replacing GOT equivalents

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Fri Mar 6 05:49:05 PST 2015


Author: bruno
Date: Fri Mar  6 07:49:05 2015
New Revision: 231475

URL: http://llvm.org/viewvc/llvm-project?rev=231475&view=rev
Log:
[AsmPrinter][TLOF] 32-bit MachO support for replacing GOT equivalents

Add MachO 32-bit (i.e. arm and x86) support for replacing global GOT equivalent
symbol accesses. Unlike 64-bit targets, there's no GOTPCREL relocation, and
access through a non_lazy_symbol_pointers section is used instead.

-- before

    _extgotequiv:
       .long _extfoo

    _delta:
       .long _extgotequiv-_delta

-- after

    _delta:
       .long L_extfoo$non_lazy_ptr-_delta

       .section __IMPORT,__pointers,non_lazy_symbol_pointers
    L_extfoo$non_lazy_ptr:
       .indirect_symbol _extfoo
       .long 0

Added:
    llvm/trunk/test/MC/MachO/cstexpr-gotpcrel-32.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
    llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.cpp
    llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.h
    llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp
    llvm/trunk/lib/Target/X86/X86TargetObjectFile.h

Modified: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h Fri Mar  6 07:49:05 2015
@@ -88,6 +88,7 @@ public:
 class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
 public:
   virtual ~TargetLoweringObjectFileMachO() {}
+  TargetLoweringObjectFileMachO();
 
   /// Extract the dependent library name from a linker option string. Returns
   /// StringRef() if the option does not specify a library.
@@ -122,6 +123,12 @@ public:
   MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang,
                                     const TargetMachine &TM,
                                     MachineModuleInfo *MMI) const override;
+
+  /// Get MachO PC relative GOT entry relocation
+  const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+                                          const MCValue &MV, int64_t Offset,
+                                          MachineModuleInfo *MMI,
+                                          MCStreamer &Streamer) const override;
 };
 
 

Modified: llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h Fri Mar  6 07:49:05 2015
@@ -29,19 +29,20 @@ namespace llvm {
   class MCSymbol;
   class MCSymbolRefExpr;
   class MCStreamer;
+  class MCValue;
   class ConstantExpr;
   class GlobalValue;
   class TargetMachine;
 
 class TargetLoweringObjectFile : public MCObjectFileInfo {
   MCContext *Ctx;
-  const DataLayout *DL;
 
   TargetLoweringObjectFile(
     const TargetLoweringObjectFile&) = delete;
   void operator=(const TargetLoweringObjectFile&) = delete;
 
 protected:
+  const DataLayout *DL;
   bool SupportIndirectSymViaGOTPCRel;
   bool SupportGOTPCRelWithOffset;
 
@@ -178,7 +179,9 @@ public:
 
   /// \brief Get the target specific PC relative GOT entry relocation
   virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+                                                  const MCValue &MV,
                                                   int64_t Offset,
+                                                  MachineModuleInfo *MMI,
                                                   MCStreamer &Streamer) const {
     return nullptr;
   }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Fri Mar  6 07:49:05 2015
@@ -2084,7 +2084,9 @@ static void handleIndirectSymViaGOTPCRel
   //
   //    gotpcrelcst := <offset from @foo base> + <cst>
   //
-  // Only encode <cst> if the target supports it.
+  // If gotpcrelcst is positive it means that we can safely fold the pc rel
+  // displacement into the GOTPCREL. We can also can have an extra offset <cst>
+  // if the target knows how to encode it.
   //
   int64_t GOTPCRelCst = Offset + MV.getConstant();
   if (GOTPCRelCst < 0)
@@ -2113,9 +2115,8 @@ static void handleIndirectSymViaGOTPCRel
   unsigned NumUses = Result.second;
   const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
   const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
-  *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(FinalSym,
-                                                          GOTPCRelCst,
-                                                          AP.OutStreamer);
+  *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
+      FinalSym, MV, Offset, AP.MMI, AP.OutStreamer);
 
   // Update GOT equivalent usage information
   --NumUses;

Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Fri Mar  6 07:49:05 2015
@@ -31,6 +31,7 @@
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -431,6 +432,11 @@ TargetLoweringObjectFileELF::InitializeE
 //                                 MachO
 //===----------------------------------------------------------------------===//
 
+TargetLoweringObjectFileMachO::TargetLoweringObjectFileMachO()
+  : TargetLoweringObjectFile() {
+  SupportIndirectSymViaGOTPCRel = true;
+}
+
 /// getDepLibFromLinkerOpt - Extract the dependent library name from a linker
 /// option string. Returns StringRef() if the option does not specify a library.
 StringRef TargetLoweringObjectFileMachO::
@@ -705,6 +711,66 @@ MCSymbol *TargetLoweringObjectFileMachO:
   return SSym;
 }
 
+const MCExpr *TargetLoweringObjectFileMachO::getIndirectSymViaGOTPCRel(
+    const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
+    MachineModuleInfo *MMI, MCStreamer &Streamer) const {
+  // Although MachO 32-bit targets do not explictly have a GOTPCREL relocation
+  // as 64-bit do, we replace the GOT equivalent by accessing the final symbol
+  // through a non_lazy_ptr stub instead. One advantage is that it allows the
+  // computation of deltas to final external symbols. Example:
+  //
+  //    _extgotequiv:
+  //       .long   _extfoo
+  //
+  //    _delta:
+  //       .long   _extgotequiv-_delta
+  //
+  // is transformed to:
+  //
+  //    _delta:
+  //       .long   L_extfoo$non_lazy_ptr-(_delta+0)
+  //
+  //       .section        __IMPORT,__pointers,non_lazy_symbol_pointers
+  //    L_extfoo$non_lazy_ptr:
+  //       .indirect_symbol        _extfoo
+  //       .long   0
+  //
+  MachineModuleInfoMachO &MachOMMI =
+    MMI->getObjFileInfo<MachineModuleInfoMachO>();
+  MCContext &Ctx = getContext();
+
+  // The offset must consider the original displacement from the base symbol
+  // since 32-bit targets don't have a GOTPCREL to fold the PC displacement.
+  Offset = -MV.getConstant();
+  const MCSymbol *BaseSym = &MV.getSymB()->getSymbol();
+
+  // Access the final symbol via sym$non_lazy_ptr and generate the appropriated
+  // non_lazy_ptr stubs.
+  SmallString<128> Name;
+  StringRef Suffix = "$non_lazy_ptr";
+  Name += DL->getPrivateGlobalPrefix();
+  Name += Sym->getName();
+  Name += Suffix;
+  MCSymbol *Stub = Ctx.GetOrCreateSymbol(Name);
+
+  MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(Stub);
+  if (!StubSym.getPointer())
+    StubSym = MachineModuleInfoImpl::
+      StubValueTy(const_cast<MCSymbol *>(Sym), true /* access indirectly */);
+
+  const MCExpr *BSymExpr =
+    MCSymbolRefExpr::Create(BaseSym, MCSymbolRefExpr::VK_None, Ctx);
+  const MCExpr *LHS =
+    MCSymbolRefExpr::Create(Stub, MCSymbolRefExpr::VK_None, Ctx);
+
+  if (!Offset)
+    return MCBinaryExpr::CreateSub(LHS, BSymExpr, Ctx);
+
+  const MCExpr *RHS =
+    MCBinaryExpr::CreateAdd(BSymExpr, MCConstantExpr::Create(Offset, Ctx), Ctx);
+  return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
+}
+
 //===----------------------------------------------------------------------===//
 //                                  COFF
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.cpp?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.cpp Fri Mar  6 07:49:05 2015
@@ -13,6 +13,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/Dwarf.h"
 using namespace llvm;
 using namespace dwarf;
@@ -25,7 +26,6 @@ void AArch64_ELFTargetObjectFile::Initia
 
 AArch64_MachoTargetObjectFile::AArch64_MachoTargetObjectFile()
   : TargetLoweringObjectFileMachO() {
-  SupportIndirectSymViaGOTPCRel = true;
   SupportGOTPCRelWithOffset = false;
 }
 
@@ -58,7 +58,10 @@ MCSymbol *AArch64_MachoTargetObjectFile:
 }
 
 const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
-    const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
+    const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
+    MachineModuleInfo *MMI, MCStreamer &Streamer) const {
+  assert((Offset+MV.getConstant() == 0) &&
+         "Arch64 does not support GOT PC rel with extra offset");
   // On ARM64 Darwin, we can reference symbols with foo at GOT-., which
   // is an indirect pc-relative reference.
   const MCExpr *Res =

Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.h?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64TargetObjectFile.h Fri Mar  6 07:49:05 2015
@@ -36,9 +36,10 @@ public:
                                     const TargetMachine &TM,
                                     MachineModuleInfo *MMI) const override;
 
-  const MCExpr *
-    getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
-                              MCStreamer &Streamer) const override;
+  const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+                                          const MCValue &MV, int64_t Offset,
+                                          MachineModuleInfo *MMI,
+                                          MCStreamer &Streamer) const override;
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp Fri Mar  6 07:49:05 2015
@@ -15,17 +15,13 @@
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Target/TargetLowering.h"
 
 using namespace llvm;
 using namespace dwarf;
 
-X86_64MachoTargetObjectFile::X86_64MachoTargetObjectFile()
-  : TargetLoweringObjectFileMachO() {
-  SupportIndirectSymViaGOTPCRel = true;
-}
-
 const MCExpr *X86_64MachoTargetObjectFile::getTTypeGlobalReference(
     const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
     const TargetMachine &TM, MachineModuleInfo *MMI,
@@ -52,13 +48,15 @@ MCSymbol *X86_64MachoTargetObjectFile::g
 }
 
 const MCExpr *X86_64MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
-    const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
+    const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
+    MachineModuleInfo *MMI, MCStreamer &Streamer) const {
   // On Darwin/X86-64, we need to use foo at GOTPCREL+4 to access the got entry
   // from a data section. In case there's an additional offset, then use
   // foo at GOTPCREL+4+<offset>.
+  unsigned FinalOff = Offset+MV.getConstant()+4;
   const MCExpr *Res =
     MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext());
-  const MCExpr *Off = MCConstantExpr::Create(Offset+4, getContext());
+  const MCExpr *Off = MCConstantExpr::Create(FinalOff, getContext());
   return MCBinaryExpr::CreateAdd(Res, Off, getContext());
 }
 

Modified: llvm/trunk/lib/Target/X86/X86TargetObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetObjectFile.h?rev=231475&r1=231474&r2=231475&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetObjectFile.h (original)
+++ llvm/trunk/lib/Target/X86/X86TargetObjectFile.h Fri Mar  6 07:49:05 2015
@@ -19,8 +19,6 @@ namespace llvm {
   /// x86-64.
   class X86_64MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
   public:
-    X86_64MachoTargetObjectFile();
-
     const MCExpr *
     getTTypeGlobalReference(const GlobalValue *GV, unsigned Encoding,
                             Mangler &Mang, const TargetMachine &TM,
@@ -33,9 +31,10 @@ namespace llvm {
                                       const TargetMachine &TM,
                                       MachineModuleInfo *MMI) const override;
 
-    const MCExpr *
-      getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
-                                MCStreamer &Streamer) const override;
+    const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
+                                            const MCValue &MV, int64_t Offset,
+                                            MachineModuleInfo *MMI,
+                                            MCStreamer &Streamer) const override;
   };
 
   /// \brief This implemenatation is used for X86 ELF targets that don't

Added: llvm/trunk/test/MC/MachO/cstexpr-gotpcrel-32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/cstexpr-gotpcrel-32.ll?rev=231475&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/cstexpr-gotpcrel-32.ll (added)
+++ llvm/trunk/test/MC/MachO/cstexpr-gotpcrel-32.ll Fri Mar  6 07:49:05 2015
@@ -0,0 +1,77 @@
+; RUN: llc -mtriple=i386-apple-darwin %s -o %t
+; RUN:  FileCheck %s < %t
+; RUN:  FileCheck %s -check-prefix=GOT-EQUIV < %t
+; RUN: llc -mtriple=arm-apple-darwin %s -o %t
+; RUN:  FileCheck %s < %t
+; RUN:  FileCheck %s -check-prefix=GOT-EQUIV < %t
+
+; GOT equivalent globals references can be replaced by the GOT entry of the
+; final symbol instead.
+
+%struct.data = type { i32, %struct.anon }
+%struct.anon = type { i32, i32 }
+
+; Check that these got equivalent symbols are never emitted or used
+; GOT-EQUIV-NOT: _localgotequiv
+; GOT-EQUIV-NOT: _extgotequiv
+ at localfoo = global i32 42
+ at localgotequiv = private unnamed_addr constant i32* @localfoo
+
+ at extfoo = external global i32
+ at extgotequiv = private unnamed_addr constant i32* @extfoo
+
+; Don't replace GOT equivalent usage within instructions and emit the GOT
+; equivalent since it can't be replaced by the GOT entry. @bargotequiv is
+; used by an instruction inside @t0.
+;
+; CHECK: l_bargotequiv:
+; CHECK-NEXT:  .long   _extbar
+ at extbar = external global i32
+ at bargotequiv = private unnamed_addr constant i32* @extbar
+
+ at table = global [4 x %struct.data] [
+; CHECK-LABEL: _table
+  %struct.data { i32 1, %struct.anon { i32 2, i32 3 } },
+; Test GOT equivalent usage inside nested constant arrays.
+; CHECK: .long   5
+; CHECK-NOT: l_localgotequiv-(_table+20)
+; CHECK-NEXT: L_localfoo$non_lazy_ptr-(_table+20)
+  %struct.data { i32 4, %struct.anon { i32 5,
+    i32 sub (i32 ptrtoint (i32** @localgotequiv to i32),
+             i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 1, i32 1, i32 1) to i32))}
+  },
+; CHECK: .long   5
+; CHECK-NOT: l_extgotequiv-(_table+32)
+; CHECK-NEXT: L_extfoo$non_lazy_ptr-(_table+32)
+  %struct.data { i32 4, %struct.anon { i32 5,
+    i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
+             i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 2, i32 1, i32 1) to i32))}
+  },
+; Test support for arbitrary constants into the GOTPCREL offset
+; CHECK: .long   5
+; CHECK-NOT: (l_extgotequiv-(_table+44))+24
+; CHECK-NEXT: L_extfoo$non_lazy_ptr-(_table+20)
+  %struct.data { i32 4, %struct.anon { i32 5,
+    i32 add (i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
+                      i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 3, i32 1, i32 1) to i32)),
+                      i32 24)}
+  }
+], align 16
+
+; Test multiple uses of GOT equivalents.
+; CHECK-LABEL: _delta
+; CHECK: .long   L_extfoo$non_lazy_ptr-_delta
+ at delta = global i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
+                         i32 ptrtoint (i32* @delta to i32))
+
+; CHECK-LABEL: _deltaplus:
+; CHECK: .long   L_localfoo$non_lazy_ptr-(_deltaplus-55)
+ at deltaplus = global i32 add (i32 sub (i32 ptrtoint (i32** @localgotequiv to i32),
+                             i32 ptrtoint (i32* @deltaplus to i32)),
+                             i32 55)
+
+define i32 @t0(i32 %a) {
+  %x = add i32 sub (i32 ptrtoint (i32** @bargotequiv to i32),
+                    i32 ptrtoint (i32 (i32)* @t0 to i32)), %a
+  ret i32 %x
+}





More information about the llvm-commits mailing list