From bd1f0630a8f6d0ac7df9da1a08d7c247ceb9674a Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sun, 20 Nov 2016 02:39:59 +0000 Subject: [PATCH] Do not expose ICF class from the file. Also this patch uses file-scope functions instead of class member function. Now that ICF class is not visible from outside, InputSection class can no longer be "friend" of it. So I removed the friend relation and just make it expose the features to public. llvm-svn: 287480 --- lld/ELF/ICF.cpp | 116 +++++++++++++---------------------------- lld/ELF/InputSection.h | 12 ++--- 2 files changed, 40 insertions(+), 88 deletions(-) diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index c9a7911fc624..77f1c9ab96f3 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -57,13 +57,11 @@ #include "ICF.h" #include "Config.h" -#include "OutputSections.h" #include "SymbolTable.h" #include "llvm/ADT/Hashing.h" #include "llvm/Object/ELF.h" #include "llvm/Support/ELF.h" -#include "llvm/Support/raw_ostream.h" #include using namespace lld; @@ -72,81 +70,46 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; -namespace lld { -namespace elf { +namespace { template class ICF { - typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::Sym Elf_Sym; - typedef typename ELFT::uint uintX_t; - typedef Elf_Rel_Impl Elf_Rel; - - using Comparator = std::function *, - const InputSection *)>; - public: void run(); private: uint64_t NextId = 1; - static void setLive(SymbolTable *S); - static uint64_t relSize(InputSection *S); - static uint64_t getHash(InputSection *S); - static bool isEligible(InputSectionBase *Sec); - static std::vector *> getSections(); + using Comparator = std::function *, + const InputSection *)>; void segregate(MutableArrayRef *> Arr, Comparator Eq); void forEachGroup(std::vector *> &V, std::function *>)> Fn); - - template - static bool relocationEq(ArrayRef RA, ArrayRef RB); - - template - static bool variableEq(const InputSection *A, ArrayRef RA, - const InputSection *B, ArrayRef RB); - - static bool equalsConstant(const InputSection *A, - const InputSection *B); - - static bool equalsVariable(const InputSection *A, - const InputSection *B); }; } -} // Returns a hash value for S. Note that the information about // relocation targets is not included in the hash value. -template uint64_t ICF::getHash(InputSection *S) { +template static uint64_t getHash(InputSection *S) { return hash_combine(S->Flags, S->getSize(), S->NumRelocations); } -// Returns true if Sec is subject of ICF. -template bool ICF::isEligible(InputSectionBase *Sec) { - if (!Sec->Live) - return false; - auto *S = dyn_cast>(Sec); - if (!S) - return false; - +// Returns true if section S is subject of ICF. +template static bool isEligible(InputSection *S) { // .init and .fini contains instructions that must be executed to // initialize and finalize the process. They cannot and should not // be merged. - StringRef Name = S->Name; - if (Name == ".init" || Name == ".fini") - return false; - - return (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE); + return S->Live && (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE) && + S->Name != ".init" && S->Name != ".fini"; } -template -std::vector *> ICF::getSections() { +template static std::vector *> getSections() { std::vector *> V; - for (InputSectionBase *S : Symtab::X->Sections) - if (isEligible(S)) - V.push_back(cast>(S)); + for (InputSectionBase *Sec : Symtab::X->Sections) + if (auto *S = dyn_cast>(Sec)) + if (isEligible(S)) + V.push_back(S); return V; } @@ -188,9 +151,8 @@ void ICF::forEachGroup( } // Compare two lists of relocations. -template -template -bool ICF::relocationEq(ArrayRef RelsA, ArrayRef RelsB) { +template +static bool relocationEq(ArrayRef RelsA, ArrayRef RelsB) { auto Eq = [](const RelTy &A, const RelTy &B) { return A.r_offset == B.r_offset && A.getType(Config->Mips64EL) == B.getType(Config->Mips64EL) && @@ -204,30 +166,23 @@ bool ICF::relocationEq(ArrayRef RelsA, ArrayRef RelsB) { // Compare "non-moving" part of two InputSections, namely everything // except relocation targets. template -bool ICF::equalsConstant(const InputSection *A, - const InputSection *B) { - if (A->NumRelocations != B->NumRelocations) +static bool equalsConstant(const InputSection *A, + const InputSection *B) { + if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags || + A->getSize() != B->getSize() || A->Data != B->Data) return false; - if (A->AreRelocsRela) { - if (!relocationEq(A->relas(), B->relas())) - return false; - } else { - if (!relocationEq(A->rels(), B->rels())) - return false; - } - - return A->Flags == B->Flags && A->getSize() == B->getSize() && - A->Data == B->Data; + if (A->AreRelocsRela) + return relocationEq(A->relas(), B->relas()); + return relocationEq(A->rels(), B->rels()); } -template -template -bool ICF::variableEq(const InputSection *A, ArrayRef RelsA, - const InputSection *B, ArrayRef RelsB) { +template +static bool variableEq(const InputSection *A, ArrayRef RelsA, + const InputSection *B, ArrayRef RelsB) { auto Eq = [&](const RelTy &RA, const RelTy &RB) { - SymbolBody &SA = A->File->getRelocTargetSym(RA); - SymbolBody &SB = B->File->getRelocTargetSym(RB); + SymbolBody &SA = A->getFile()->getRelocTargetSym(RA); + SymbolBody &SB = B->getFile()->getRelocTargetSym(RB); if (&SA == &SB) return true; @@ -249,8 +204,8 @@ bool ICF::variableEq(const InputSection *A, ArrayRef RelsA, // Compare "moving" part of two InputSections, namely relocation targets. template -bool ICF::equalsVariable(const InputSection *A, - const InputSection *B) { +static bool equalsVariable(const InputSection *A, + const InputSection *B) { if (A->AreRelocsRela) return variableEq(A, A->relas(), B, B->relas()); return variableEq(A, A->rels(), B, B->rels()); @@ -261,7 +216,7 @@ template void ICF::run() { // Initially, we use hash values as section group IDs. Therefore, // if two sections have the same ID, they are likely (but not // guaranteed) to have the same static contents in terms of ICF. - std::vector *> Sections = getSections(); + std::vector *> Sections = getSections(); for (InputSection *S : Sections) // Set MSB on to avoid collisions with serial group IDs S->GroupId = getHash(S) | (uint64_t(1) << 63); @@ -279,7 +234,7 @@ template void ICF::run() { // Compare static contents and assign unique IDs for each static content. forEachGroup(Sections, [&](MutableArrayRef *> V) { - segregate(V, equalsConstant); + segregate(V, equalsConstant); }); // Split groups by comparing relocations until we get a convergence. @@ -288,7 +243,7 @@ template void ICF::run() { ++Cnt; uint64_t Id = NextId; forEachGroup(Sections, [&](MutableArrayRef *> V) { - segregate(V, equalsVariable); + segregate(V, equalsVariable); }); if (Id == NextId) break; @@ -296,12 +251,11 @@ template void ICF::run() { log("ICF needed " + Twine(Cnt) + " iterations."); // Merge sections in the same group. - forEachGroup(Sections, [&](MutableArrayRef *> V) { - InputSection *Head = V[0]; - log("selected " + Head->Name); + forEachGroup(Sections, [](MutableArrayRef *> V) { + log("selected " + V[0]->Name); for (InputSection *S : V.slice(1)) { log(" removed " + S->Name); - Head->replace(S); + V[0]->replace(S); } }); } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 444e77777702..5b0c6fc89897 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -26,7 +26,6 @@ class DefinedCommon; class SymbolBody; struct SectionPiece; -template class ICF; template class DefinedRegular; template class ObjectFile; template class OutputSection; @@ -238,7 +237,6 @@ public: // This corresponds to a non SHF_MERGE section of an input file. template class InputSection : public InputSectionBase { - friend ICF; typedef InputSectionBase Base; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Rela Elf_Rela; @@ -285,15 +283,15 @@ public: template void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); -private: - template - void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); + // Used by ICF. + uint64_t GroupId = 0; // Called by ICF to merge two input sections. void replace(InputSection *Other); - // Used by ICF. - uint64_t GroupId = 0; +private: + template + void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); llvm::TinyPtrVector *> Thunks; };