From: Peter Smith Date: Wed, 5 Apr 2017 10:30:09 +0000 (+0000) Subject: [ELF] Make createThunks a class [NFC] X-Git-Tag: llvmorg-5.0.0-rc1~8464 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56abf209c21f63dc57ac182563cb0f0a743d74ae;p=platform%2Fupstream%2Fllvm.git [ELF] Make createThunks a class [NFC] For range extension thunks we will need to repeatedly call createThunks() until no more thunks are created. We will need to retain the state of Thunks that we have created so far to avoid recreating them on later passes. This change does not change the functionality of createThunks(). Differential Revision: https://reviews.llvm.org/D31654 llvm-svn: 299530 --- diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 2b85cc61b57a..494aa7771dae 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -932,8 +932,9 @@ template void elf::scanRelocations(InputSectionBase &S) { // in the Sections vector, and recalculate the InputSection output section // offsets. // This may invalidate any output section offsets stored outside of InputSection -static void mergeThunks(OutputSection *OS, - std::vector &Thunks) { +template +void ThunkCreator::mergeThunks(OutputSection *OS, + std::vector &Thunks) { // Order Thunks in ascending OutSecOff auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) { return A->OutSecOff < B->OutSecOff; @@ -961,6 +962,44 @@ static void mergeThunks(OutputSection *OS, OS->assignOffsets(); } +template +ThunkSection *ThunkCreator::getOSThunkSec(ThunkSection *&TS, + OutputSection *OS) { + if (TS == nullptr) { + uint32_t Off = 0; + for (auto *IS : OS->Sections) { + Off = IS->OutSecOff + IS->getSize(); + if ((IS->Flags & SHF_EXECINSTR) == 0) + break; + } + TS = make(OS, Off); + ThunkSections[OS].push_back(TS); + } + return TS; +} + +template +ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, + OutputSection *OS) { + ThunkSection *TS = ThunkedSections.lookup(IS); + if (TS) + return TS; + auto *TOS = cast(IS->OutSec); + TS = make(TOS, IS->OutSecOff); + ThunkSections[TOS].push_back(TS); + ThunkedSections[IS] = TS; + return TS; +} + +template +std::pair ThunkCreator::getThunk(SymbolBody &Body, + uint32_t Type) { + auto res = ThunkedSymbols.insert({&Body, nullptr}); + if (res.second) + res.first->second = addThunk(Type, Body); + return std::make_pair(res.first->second, res.second); +} + // Process all relocations from the InputSections that have been assigned // to OutputSections and redirect through Thunks if needed. // @@ -972,48 +1011,8 @@ static void mergeThunks(OutputSection *OS, // FIXME: All Thunks are assumed to be in range of the relocation. Range // extension Thunks are not yet supported. template -bool elf::createThunks(ArrayRef OutputSections) { - // Track Symbols that already have a Thunk - DenseMap ThunkedSymbols; - // Track InputSections that have a ThunkSection placed in front - DenseMap ThunkedSections; - // Track the ThunksSections that need to be inserted into an OutputSection - std::map> ThunkSections; - - // Find or create a Thunk for Body for relocation Type - auto GetThunk = [&](SymbolBody &Body, uint32_t Type) { - auto res = ThunkedSymbols.insert({&Body, nullptr}); - if (res.second == true) - res.first->second = addThunk(Type, Body); - return std::make_pair(res.first->second, res.second); - }; - - // Find or create a ThunkSection to be placed immediately before IS - auto GetISThunkSec = [&](InputSection *IS, OutputSection *OS) { - ThunkSection *TS = ThunkedSections.lookup(IS); - if (TS) - return TS; - auto *TOS = cast(IS->OutSec); - TS = make(TOS, IS->OutSecOff); - ThunkSections[TOS].push_back(TS); - ThunkedSections[IS] = TS; - return TS; - }; - // Find or create a ThunkSection to be placed as last executable section in - // OS. - auto GetOSThunkSec = [&](ThunkSection *&TS, OutputSection *OS) { - if (TS == nullptr) { - uint32_t Off = 0; - for (auto *IS : OS->Sections) { - Off = IS->OutSecOff + IS->getSize(); - if ((IS->Flags & SHF_EXECINSTR) == 0) - break; - } - TS = make(OS, Off); - ThunkSections[OS].push_back(TS); - } - return TS; - }; +bool ThunkCreator::createThunks( + ArrayRef OutputSections) { // Create all the Thunks and insert them into synthetic ThunkSections. The // ThunkSections are later inserted back into the OutputSection. @@ -1025,23 +1024,23 @@ bool elf::createThunks(ArrayRef OutputSections) { for (InputSection *IS : OS->Sections) { for (Relocation &Rel : IS->Relocations) { SymbolBody &Body = *Rel.Sym; - if (Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) { - Thunk *T; - bool IsNew; - std::tie(T, IsNew) = GetThunk(Body, Rel.Type); - if (IsNew) { - // Find or create a ThunkSection for the new Thunk - ThunkSection *TS; - if (auto *TIS = T->getTargetInputSection()) - TS = GetISThunkSec(TIS, OS); - else - TS = GetOSThunkSec(OSTS, OS); - TS->addThunk(T); - } - // Redirect relocation to Thunk, we never go via the PLT to a Thunk - Rel.Sym = T->ThunkSym; - Rel.Expr = fromPlt(Rel.Expr); + if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) + continue; + Thunk *T; + bool IsNew; + std::tie(T, IsNew) = getThunk(Body, Rel.Type); + if (IsNew) { + // Find or create a ThunkSection for the new Thunk + ThunkSection *TS; + if (auto *TIS = T->getTargetInputSection()) + TS = getISThunkSec(TIS, OS); + else + TS = getOSThunkSec(OSTS, OS); + TS->addThunk(T); } + // Redirect relocation to Thunk, we never go via the PLT to a Thunk + Rel.Sym = T->ThunkSym; + Rel.Expr = fromPlt(Rel.Expr); } } } @@ -1057,7 +1056,7 @@ template void elf::scanRelocations(InputSectionBase &); template void elf::scanRelocations(InputSectionBase &); template void elf::scanRelocations(InputSectionBase &); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); -template bool elf::createThunks(ArrayRef); +template class elf::ThunkCreator; +template class elf::ThunkCreator; +template class elf::ThunkCreator; +template class elf::ThunkCreator; diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index b798dc3b29d0..f8f0f11e14a9 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -11,6 +11,9 @@ #define LLD_ELF_RELOCATIONS_H #include "lld/Core/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include +#include namespace lld { namespace elf { @@ -113,8 +116,29 @@ struct Relocation { template void scanRelocations(InputSectionBase &); -template -bool createThunks(ArrayRef OutputSections); +class ThunkSection; +class Thunk; + +template class ThunkCreator { +public: + // Return true if Thunks have been added to OutputSections + bool createThunks(ArrayRef OutputSections); + +private: + void mergeThunks(OutputSection *OS, std::vector &Thunks); + ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS); + ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); + std::pair getThunk(SymbolBody &Body, uint32_t Type); + + // Track Symbols that already have a Thunk + llvm::DenseMap ThunkedSymbols; + + // Track InputSections that have a ThunkSection placed in front + llvm::DenseMap ThunkedSections; + + // Track the ThunksSections that need to be inserted into an OutputSection + std::map> ThunkSections; +}; // Return a int64_t to make sure we get the sign extension out of the way as // early as possible. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index deacc736d25b..53b2353539fa 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1180,7 +1180,8 @@ template void Writer::finalizeSections() { // we need to assign addresses so that we can tell if jump instructions // are out of range. This will need to turn into a loop that converges // when no more Thunks are added - if (createThunks(OutputSections)) + ThunkCreator TC; + if (TC.createThunks(OutputSections)) applySynthetic({In::MipsGot}, [](SyntheticSection *SS) { SS->updateAllocSize(); }); }