diff options
| author | Peter Collingbourne <peter@pcc.me.uk> | 2018-03-15 21:14:02 +0000 |
|---|---|---|
| committer | Peter Collingbourne <peter@pcc.me.uk> | 2018-03-15 21:14:02 +0000 |
| commit | f1a11f87a04672d1b0d8e355ece1516a40477362 (patch) | |
| tree | b8461d85cd50d8880cd5c2224185a9d1819964bc /lld/COFF/Chunks.cpp | |
| parent | 435b0991156363022223e8ff480fbb66b6bb257d (diff) | |
| download | bcm5719-llvm-f1a11f87a04672d1b0d8e355ece1516a40477362.tar.gz bcm5719-llvm-f1a11f87a04672d1b0d8e355ece1516a40477362.zip | |
COFF: Implement string tail merging.
In COFF, duplicate string literals are merged by placing them in a
comdat whose leader symbol name contains a specific prefix followed
by the hash and partial contents of the string literal. This gives
us an easy way to identify sections containing string literals in
the linker: check for leader symbol names with the given prefix.
Any sections that are identified in this way as containing string
literals may be tail merged. We do so using the StringTableBuilder
class, which is also used to tail merge string literals in the ELF
linker. Tail merging is enabled only if ICF is enabled, as this
provides a signal as to whether the user cares about binary size.
Differential Revision: https://reviews.llvm.org/D44504
llvm-svn: 327668
Diffstat (limited to 'lld/COFF/Chunks.cpp')
| -rw-r--r-- | lld/COFF/Chunks.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 6da121ef40c..451e18a600b 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -571,5 +571,47 @@ uint8_t Baserel::getDefaultType() { } } +std::map<uint32_t, MergeChunk *> MergeChunk::Instances; + +MergeChunk::MergeChunk(uint32_t Alignment) + : Builder(StringTableBuilder::RAW, Alignment) { + this->Alignment = Alignment; +} + +void MergeChunk::addSection(SectionChunk *C) { + auto *&MC = Instances[C->Alignment]; + if (!MC) + MC = make<MergeChunk>(C->Alignment); + MC->Sections.push_back(C); +} + +void MergeChunk::finalizeContents() { + for (SectionChunk *C : Sections) + if (C->isLive()) + Builder.add(toStringRef(C->getContents())); + Builder.finalize(); + + for (SectionChunk *C : Sections) { + if (!C->isLive()) + continue; + size_t Off = Builder.getOffset(toStringRef(C->getContents())); + C->setOutputSection(Out); + C->setRVA(RVA + Off); + C->OutputSectionOff = OutputSectionOff + Off; + } +} + +uint32_t MergeChunk::getPermissions() const { + return IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA; +} + +size_t MergeChunk::getSize() const { + return Builder.getSize(); +} + +void MergeChunk::writeTo(uint8_t *Buf) const { + Builder.write(Buf + OutputSectionOff); +} + } // namespace coff } // namespace lld |

