GC entries of SHF_MERGE sections.
It is a fairly direct extension of the gc algorithm. For merge sections
instead of remembering just a live bit, we remember which offsets were
used.
This reduces the .rodata sections in chromium from 9648861 to 9477472
bytes.
llvm-svn: 267164
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 2511fc1..93d12a0 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -40,20 +40,29 @@
// Calls Fn for each section that Sec refers to via relocations.
template <class ELFT>
-static void forEachSuccessor(InputSection<ELFT> *Sec,
- std::function<void(InputSectionBase<ELFT> *)> Fn) {
+static void forEachSuccessor(
+ InputSection<ELFT> *Sec,
+ std::function<void(InputSectionBase<ELFT> *, typename ELFT::uint Offset)>
+ Fn) {
typedef typename ELFT::Rel Elf_Rel;
typedef typename ELFT::Rela Elf_Rela;
typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::uint uintX_t;
ELFFile<ELFT> &Obj = Sec->getFile()->getObj();
for (const Elf_Shdr *RelSec : Sec->RelocSections) {
if (RelSec->sh_type == SHT_RELA) {
- for (const Elf_Rela &RI : Obj.relas(RelSec))
- Fn(Sec->getRelocTarget(RI));
+ for (const Elf_Rela &RI : Obj.relas(RelSec)) {
+ std::pair<InputSectionBase<ELFT> *, uintX_t> P =
+ Sec->getRelocTarget(RI);
+ Fn(P.first, P.second);
+ }
} else {
- for (const Elf_Rel &RI : Obj.rels(RelSec))
- Fn(Sec->getRelocTarget(RI));
+ for (const Elf_Rel &RI : Obj.rels(RelSec)) {
+ std::pair<InputSectionBase<ELFT> *, uintX_t> P =
+ Sec->getRelocTarget(RI);
+ Fn(P.first, P.second);
+ }
}
}
}
@@ -85,10 +94,18 @@
// Starting from GC-root sections, this function visits all reachable
// sections to set their "Live" bits.
template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) {
+ typedef typename ELFT::uint uintX_t;
SmallVector<InputSection<ELFT> *, 256> Q;
- auto Enqueue = [&](InputSectionBase<ELFT> *Sec) {
- if (!Sec || Sec->Live)
+ auto Enqueue = [&](InputSectionBase<ELFT> *Sec, uintX_t Offset) {
+ if (!Sec)
+ return;
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(Sec)) {
+ std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T =
+ MS->getRangeAndSize(Offset);
+ T.first->second = 0;
+ }
+ if (Sec->Live)
return;
Sec->Live = true;
if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(Sec))
@@ -98,7 +115,7 @@
auto MarkSymbol = [&](SymbolBody *Sym) {
if (Sym)
if (auto *D = dyn_cast<DefinedRegular<ELFT>>(Sym))
- Enqueue(D->Section);
+ Enqueue(D->Section, D->Value);
};
// Add GC root symbols.
@@ -125,7 +142,7 @@
for (InputSectionBase<ELFT> *Sec : F->getSections())
if (Sec && Sec != &InputSection<ELFT>::Discarded)
if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec))
- Enqueue(Sec);
+ Enqueue(Sec, 0);
// Mark all reachable sections.
while (!Q.empty())