diff options
author | Rui Ueyama <ruiu@google.com> | 2015-06-28 04:30:54 +0300 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2015-06-28 04:30:54 +0300 |
commit | 871847e32d7e8faddcdc4e0e8c40ab0a6511f3d1 (patch) | |
tree | e4cbc4d249cf2f03c2f4a2fb1d53fbe7bab78bb1 /lld/COFF | |
parent | 45c4812851436ea3e762b0ac2fc3102c8ee48fa0 (diff) |
COFF: Fix ICF correctness bug.
When comparing two COMDAT sections, we need to take section values
and associative sections into account. This patch fixes that bug.
It fixes a crash bug of llvm-tblgen when linked with /opt:lldicf.
One thing I don't understand yet is that this logic seems to be
too strict. MSVC linker is able to create more compact executables
(which of course work correctly). With this ICF algorithm, LLD is
able to make executable smaller, but the outputs are larger than
MSVC's. There must be something I'm missing here.
llvm-svn: 240897
Diffstat (limited to 'lld/COFF')
-rw-r--r-- | lld/COFF/Chunks.cpp | 15 | ||||
-rw-r--r-- | lld/COFF/Chunks.h | 2 | ||||
-rw-r--r-- | lld/COFF/Symbols.h | 1 |
3 files changed, 14 insertions, 4 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index aa2c0be3ef51..7a068eebf102 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -173,6 +173,13 @@ bool SectionChunk::equals(const SectionChunk *X) const { if (getContents() != X->getContents()) return false; + // Compare associative sections + if (AssocChildren.size() != X->AssocChildren.size()) + return false; + for (size_t I = 0, E = AssocChildren.size(); I != E; ++I) + if (AssocChildren[I]->Ptr != X->AssocChildren[I]->Ptr) + return false; + // Compare relocations auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { if (R1.Type != R2.Type) @@ -181,11 +188,13 @@ bool SectionChunk::equals(const SectionChunk *X) const { return false; SymbolBody *B1 = File->getSymbolBody(R1.SymbolTableIndex); SymbolBody *B2 = X->File->getSymbolBody(R2.SymbolTableIndex); + if (B1 == B2) + return true; auto *D1 = dyn_cast<DefinedRegular>(B1); auto *D2 = dyn_cast<DefinedRegular>(B2); - if (D1 && D2 && D1->getChunk() == D2->getChunk()) - return true; - return B1 == B2; + return (D1 && D2 && + D1->getValue() == D2->getValue() && + D1->getChunk() == D2->getChunk()); }; return std::equal(Relocs.begin(), Relocs.end(), X->Relocs.begin(), Eq); } diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 37a6003cf8ec..3b6bf5f7700b 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -151,7 +151,7 @@ private: const coff_section *Header; StringRef SectionName; - std::vector<Chunk *> AssocChildren; + std::vector<SectionChunk *> AssocChildren; llvm::iterator_range<const coff_relocation *> Relocs; size_t NumRelocs; diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index e0cb7b16acb0..f87b8f12d378 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -137,6 +137,7 @@ public: bool isLive() const { return (*Data)->isLive(); } void markLive() { (*Data)->markLive(); } Chunk *getChunk() { return *Data; } + uint64_t getValue() { return Sym.getValue(); } private: StringRef Name; |