forked from OSchip/llvm-project
Revert r301678: Remove LinkerScript::flush.
This reverts commit r301678 since that change significantly slowed down the linker. Before this patch, LLD could link clang in 8 seconds, but with this patch it took 40 seconds. llvm-svn: 301709
This commit is contained in:
parent
6ee72d743b
commit
216aa11cc5
|
@ -475,15 +475,10 @@ void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
|
||||||
return Cmd->Name == Name;
|
return Cmd->Name == Name;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
if (I == Opt.Commands.end()) {
|
if (I == Opt.Commands.end())
|
||||||
Factory.addInputSec(S, Name);
|
Factory.addInputSec(S, Name);
|
||||||
} else {
|
else
|
||||||
auto *Cmd = cast<OutputSectionCommand>(*I);
|
Factory.addInputSec(S, Name, cast<OutputSectionCommand>(*I)->Sec);
|
||||||
Factory.addInputSec(S, Name, Cmd->Sec);
|
|
||||||
auto *ISD = make<InputSectionDescription>("");
|
|
||||||
ISD->Sections.push_back(S);
|
|
||||||
Cmd->Commands.push_back(ISD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,6 +487,8 @@ static bool isTbss(OutputSection *Sec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerScript::output(InputSection *S) {
|
void LinkerScript::output(InputSection *S) {
|
||||||
|
if (!AlreadyOutputIS.insert(S).second)
|
||||||
|
return;
|
||||||
bool IsTbss = isTbss(CurOutSec);
|
bool IsTbss = isTbss(CurOutSec);
|
||||||
|
|
||||||
uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
|
uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
|
||||||
|
@ -523,9 +520,19 @@ void LinkerScript::output(InputSection *S) {
|
||||||
Dot = Pos;
|
Dot = Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkerScript::flush() {
|
||||||
|
assert(CurOutSec);
|
||||||
|
if (!AlreadyOutputOS.insert(CurOutSec).second)
|
||||||
|
return;
|
||||||
|
for (InputSection *I : CurOutSec->Sections)
|
||||||
|
output(I);
|
||||||
|
}
|
||||||
|
|
||||||
void LinkerScript::switchTo(OutputSection *Sec) {
|
void LinkerScript::switchTo(OutputSection *Sec) {
|
||||||
if (CurOutSec == Sec)
|
if (CurOutSec == Sec)
|
||||||
return;
|
return;
|
||||||
|
if (AlreadyOutputOS.count(Sec))
|
||||||
|
return;
|
||||||
|
|
||||||
CurOutSec = Sec;
|
CurOutSec = Sec;
|
||||||
|
|
||||||
|
@ -576,7 +583,7 @@ void LinkerScript::process(BaseCommand &Base) {
|
||||||
|
|
||||||
if (!Sec->Live)
|
if (!Sec->Live)
|
||||||
continue;
|
continue;
|
||||||
assert(CurOutSec == Sec->OutSec);
|
assert(CurOutSec == Sec->OutSec || AlreadyOutputOS.count(Sec->OutSec));
|
||||||
output(cast<InputSection>(Sec));
|
output(cast<InputSection>(Sec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,8 +642,19 @@ void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
|
||||||
Dot = CurMemRegion->Offset;
|
Dot = CurMemRegion->Offset;
|
||||||
switchTo(Sec);
|
switchTo(Sec);
|
||||||
|
|
||||||
for (BaseCommand *C : Cmd->Commands)
|
// flush() may add orphan sections, so the order of flush() and
|
||||||
process(*C);
|
// symbol assignments is important. We want to call flush() first so
|
||||||
|
// that symbols pointing the end of the current section points to
|
||||||
|
// the location after orphan sections.
|
||||||
|
auto Mid =
|
||||||
|
std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
|
||||||
|
[](BaseCommand *Cmd) { return !isa<SymbolAssignment>(Cmd); })
|
||||||
|
.base();
|
||||||
|
for (auto I = Cmd->Commands.begin(); I != Mid; ++I)
|
||||||
|
process(**I);
|
||||||
|
flush();
|
||||||
|
for (auto I = Mid, E = Cmd->Commands.end(); I != E; ++I)
|
||||||
|
process(**I);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerScript::removeEmptyCommands() {
|
void LinkerScript::removeEmptyCommands() {
|
||||||
|
@ -806,24 +824,15 @@ void LinkerScript::placeOrphanSections() {
|
||||||
++CmdIndex;
|
++CmdIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is no command corresponding to this output section,
|
|
||||||
// create one and put a InputSectionDescription in it so that both
|
|
||||||
// representations agree on which input sections to use.
|
|
||||||
auto Pos = std::find_if(CmdIter, E, [&](BaseCommand *Base) {
|
auto Pos = std::find_if(CmdIter, E, [&](BaseCommand *Base) {
|
||||||
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
|
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
|
||||||
return Cmd && Cmd->Name == Name;
|
return Cmd && Cmd->Name == Name;
|
||||||
});
|
});
|
||||||
if (Pos == E) {
|
if (Pos == E) {
|
||||||
auto *Cmd = make<OutputSectionCommand>(Name);
|
auto *Cmd = make<OutputSectionCommand>(Name);
|
||||||
|
Cmd->Sec = Sec;
|
||||||
Opt.Commands.insert(CmdIter, Cmd);
|
Opt.Commands.insert(CmdIter, Cmd);
|
||||||
++CmdIndex;
|
++CmdIndex;
|
||||||
|
|
||||||
Cmd->Sec = Sec;
|
|
||||||
auto *ISD = make<InputSectionDescription>("");
|
|
||||||
for (InputSection *IS : Sec->Sections)
|
|
||||||
ISD->Sections.push_back(IS);
|
|
||||||
Cmd->Commands.push_back(ISD);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,49 +850,6 @@ void LinkerScript::processNonSectionCommands() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a last effort at synchronizing the linker script "AST" and the section
|
|
||||||
// list. This is needed to account for last minute changes, like adding a
|
|
||||||
// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections.
|
|
||||||
//
|
|
||||||
// FIXME: We should instead create the "AST" earlier and the above changes would
|
|
||||||
// be done directly in the "AST".
|
|
||||||
//
|
|
||||||
// This can only handle new sections being added and sections being reordered.
|
|
||||||
void LinkerScript::synchronize() {
|
|
||||||
for (BaseCommand *Base : Opt.Commands) {
|
|
||||||
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
|
|
||||||
if (!Cmd)
|
|
||||||
continue;
|
|
||||||
ArrayRef<InputSection *> Sections = Cmd->Sec->Sections;
|
|
||||||
std::vector<InputSectionBase **> ScriptSections;
|
|
||||||
for (BaseCommand *Base : Cmd->Commands) {
|
|
||||||
auto *ISD = dyn_cast<InputSectionDescription>(Base);
|
|
||||||
if (!ISD)
|
|
||||||
continue;
|
|
||||||
for (InputSectionBase *&IS : ISD->Sections)
|
|
||||||
if (IS->Live)
|
|
||||||
ScriptSections.push_back(&IS);
|
|
||||||
}
|
|
||||||
std::vector<InputSectionBase *> Missing;
|
|
||||||
for (InputSection *IS : Sections)
|
|
||||||
if (std::find_if(ScriptSections.begin(), ScriptSections.end(),
|
|
||||||
[=](InputSectionBase **Base) { return *Base == IS; }) ==
|
|
||||||
ScriptSections.end())
|
|
||||||
Missing.push_back(IS);
|
|
||||||
if (!Missing.empty()) {
|
|
||||||
auto ISD = make<InputSectionDescription>("");
|
|
||||||
ISD->Sections = Missing;
|
|
||||||
Cmd->Commands.push_back(ISD);
|
|
||||||
for (InputSectionBase *&IS : ISD->Sections)
|
|
||||||
if (IS->Live)
|
|
||||||
ScriptSections.push_back(&IS);
|
|
||||||
}
|
|
||||||
assert(ScriptSections.size() == Sections.size());
|
|
||||||
for (int I = 0, N = Sections.size(); I < N; ++I)
|
|
||||||
*ScriptSections[I] = Sections[I];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
|
void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
|
||||||
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
||||||
Dot = 0;
|
Dot = 0;
|
||||||
|
|
|
@ -228,6 +228,7 @@ protected:
|
||||||
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
|
MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
|
||||||
|
|
||||||
void switchTo(OutputSection *Sec);
|
void switchTo(OutputSection *Sec);
|
||||||
|
void flush();
|
||||||
void output(InputSection *Sec);
|
void output(InputSection *Sec);
|
||||||
void process(BaseCommand &Base);
|
void process(BaseCommand &Base);
|
||||||
|
|
||||||
|
@ -241,6 +242,9 @@ protected:
|
||||||
OutputSection *CurOutSec = nullptr;
|
OutputSection *CurOutSec = nullptr;
|
||||||
MemoryRegion *CurMemRegion = nullptr;
|
MemoryRegion *CurMemRegion = nullptr;
|
||||||
|
|
||||||
|
llvm::DenseSet<OutputSection *> AlreadyOutputOS;
|
||||||
|
llvm::DenseSet<InputSectionBase *> AlreadyOutputIS;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
|
bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
|
||||||
uint64_t getDot() { return Dot; }
|
uint64_t getDot() { return Dot; }
|
||||||
|
@ -267,7 +271,6 @@ public:
|
||||||
void assignOffsets(OutputSectionCommand *Cmd);
|
void assignOffsets(OutputSectionCommand *Cmd);
|
||||||
void placeOrphanSections();
|
void placeOrphanSections();
|
||||||
void processNonSectionCommands();
|
void processNonSectionCommands();
|
||||||
void synchronize();
|
|
||||||
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
|
void assignAddresses(std::vector<PhdrEntry> &Phdrs);
|
||||||
int getSectionIndex(StringRef Name);
|
int getSectionIndex(StringRef Name);
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,6 @@ template <class ELFT> void Writer<ELFT>::run() {
|
||||||
fixSectionAlignments();
|
fixSectionAlignments();
|
||||||
Script->fabricateDefaultCommands(Config->MaxPageSize);
|
Script->fabricateDefaultCommands(Config->MaxPageSize);
|
||||||
}
|
}
|
||||||
Script->synchronize();
|
|
||||||
Script->assignAddresses(Phdrs);
|
Script->assignAddresses(Phdrs);
|
||||||
|
|
||||||
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
// Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
|
||||||
|
@ -1081,7 +1080,6 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) {
|
||||||
|
|
||||||
SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(),
|
SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(),
|
||||||
SS->OutSec->Sections.end(), SS));
|
SS->OutSec->Sections.end(), SS));
|
||||||
SS->Live = false;
|
|
||||||
// If there are no other sections in the output section, remove it from the
|
// If there are no other sections in the output section, remove it from the
|
||||||
// output.
|
// output.
|
||||||
if (SS->OutSec->Sections.empty())
|
if (SS->OutSec->Sections.empty())
|
||||||
|
|
Loading…
Reference in New Issue