[lld] r307132 - [ELF] Introduce Thunk reuse compatibility

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 5 02:36:04 PDT 2017


Author: psmith
Date: Wed Jul  5 02:36:03 2017
New Revision: 307132

URL: http://llvm.org/viewvc/llvm-project?rev=307132&view=rev
Log:
[ELF] Introduce Thunk reuse compatibility

On ARM the interworking thunks are only produced for branch instructions
that can't be changed into a blx instruction so only Thumb callers would
call Thumb thunks and only ARM callers would call ARM thunks. With range
extension thunks branch and link instructions may need a Thunk. These
instructions can be rewritten as a blx and can use either ARM or Thumb
thunks.

We introduce an isCompatibleWith() function so that a caller can check if
an existing Thunk is compatible before reusing it.

Differential Revision: https://reviews.llvm.org/D34035


Modified:
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Thunks.cpp
    lld/trunk/ELF/Thunks.h

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=307132&r1=307131&r2=307132&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jul  5 02:36:03 2017
@@ -1050,7 +1050,7 @@ ThunkSection *ThunkCreator::addThunkSect
 std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
                                                 uint32_t Type) {
   auto res = ThunkedSymbols.insert({&Body, nullptr});
-  if (res.second)
+  if (res.second || !res.first->second->isCompatibleWith(Type))
     res.first->second = addThunk(Type, Body);
   return std::make_pair(res.first->second, res.second);
 }

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=307132&r1=307131&r2=307132&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Wed Jul  5 02:36:03 2017
@@ -57,6 +57,7 @@ public:
   uint32_t size() const override { return 12; }
   void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
   void addSymbols(ThunkSection &IS) override;
+  bool isCompatibleWith(uint32_t RelocType) const override;
 };
 
 class ARMV7PILongThunk final : public Thunk {
@@ -66,6 +67,7 @@ public:
   uint32_t size() const override { return 16; }
   void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
   void addSymbols(ThunkSection &IS) override;
+  bool isCompatibleWith(uint32_t RelocType) const override;
 };
 
 class ThumbV7ABSLongThunk final : public Thunk {
@@ -77,6 +79,7 @@ public:
   uint32_t size() const override { return 10; }
   void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
   void addSymbols(ThunkSection &IS) override;
+  bool isCompatibleWith(uint32_t RelocType) const override;
 };
 
 class ThumbV7PILongThunk final : public Thunk {
@@ -88,6 +91,7 @@ public:
   uint32_t size() const override { return 12; }
   void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
   void addSymbols(ThunkSection &IS) override;
+  bool isCompatibleWith(uint32_t RelocType) const override;
 };
 
 // MIPS LA25 thunk
@@ -128,6 +132,11 @@ void ARMV7ABSLongThunk::addSymbols(Thunk
   addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
 }
 
+bool ARMV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {
+  // Thumb branch relocations can't use BLX
+  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
+}
+
 void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
   const uint8_t Data[] = {
       0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
@@ -147,6 +156,12 @@ void ThumbV7ABSLongThunk::addSymbols(Thu
   addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
 }
 
+bool ThumbV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {
+  // ARM branch relocations can't use BLX
+  return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
+         RelocType != R_ARM_PLT32;
+}
+
 void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
   const uint8_t Data[] = {
       0xf0, 0xcf, 0x0f, 0xe3, // P:  movw ip,:lower16:S - (P + (L1-P) +8)
@@ -168,6 +183,11 @@ void ARMV7PILongThunk::addSymbols(ThunkS
   addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
 }
 
+bool ARMV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
+  // Thumb branch relocations can't use BLX
+  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
+}
+
 void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
   const uint8_t Data[] = {
       0x4f, 0xf6, 0xf4, 0x7c, // P:  movw ip,:lower16:S - (P + (L1-P) + 4)
@@ -189,6 +209,12 @@ void ThumbV7PILongThunk::addSymbols(Thun
   addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
 }
 
+bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
+  // ARM branch relocations can't use BLX
+  return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
+         RelocType != R_ARM_PLT32;
+}
+
 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
 void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
   uint64_t S = Destination.getVA();

Modified: lld/trunk/ELF/Thunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=307132&r1=307131&r2=307132&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.h (original)
+++ lld/trunk/ELF/Thunks.h Wed Jul  5 02:36:03 2017
@@ -41,6 +41,10 @@ public:
   // a branch and fall through to the first Symbol in the Target.
   virtual InputSection *getTargetInputSection() const { return nullptr; }
 
+  // To reuse a Thunk the caller as identified by the RelocType must be
+  // compatible with it.
+  virtual bool isCompatibleWith(uint32_t RelocType) const { return true; }
+
   // The alignment requirement for this Thunk, defaults to the size of the
   // typical code section alignment.
   const SymbolBody &Destination;




More information about the llvm-commits mailing list