[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