From 6b2748104bbb34fcb245edd3f3a51494038e0441 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Mon, 25 Jul 2016 22:51:07 +0000 Subject: [PATCH] Split LinkerScript::createSections into small functions. createSections function is getting longer, so it is time to split it into small functions. The reason why the function is long is because it has deeply nested for-loops. This patch constructs temporary data to reduce nesting level. Differential Revision: https://reviews.llvm.org/D22786 llvm-svn: 276706 --- lld/ELF/LinkerScript.cpp | 85 +++++++++++++++++++++++----------------- lld/ELF/LinkerScript.h | 5 +++ 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 333c46714b45..1d51a70819f9 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -74,65 +74,76 @@ static bool match(ArrayRef Patterns, StringRef S) { return false; } +// Create a vector of (, ). +// For example, if a returned vector contains (".text" (".foo.*" ".bar.*")), +// input sections start with ".foo." or ".bar." should be added to +// ".text" section. +template +std::vector>> +LinkerScript::getSectionMap() { + std::vector>> Ret; + + for (const std::unique_ptr &Base1 : Opt.Commands) + if (auto *Cmd1 = dyn_cast(Base1.get())) + for (const std::unique_ptr &Base2 : Cmd1->Commands) + if (auto *Cmd2 = dyn_cast(Base2.get())) + Ret.emplace_back(Cmd1->Name, Cmd2->Patterns); + + return Ret; +} + +// Returns input sections filtered by given glob patterns. +template +std::vector *> +LinkerScript::getInputSections(ArrayRef Patterns) { + std::vector *> Ret; + for (const std::unique_ptr> &F : + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec && match(Patterns, S->getSectionName())) + Ret.push_back(S); + return Ret; +} + template std::vector *> LinkerScript::createSections(OutputSectionFactory &Factory) { - typedef const std::unique_ptr> ObjectFile; - std::vector *> Result; + std::vector *> Ret; // Add input section to output section. If there is no output section yet, // then create it and add to output section list. - auto AddInputSec = [&](InputSectionBase *C, StringRef Name) { + auto Add = [&](InputSectionBase *C, StringRef Name) { OutputSectionBase *Sec; bool IsNew; std::tie(Sec, IsNew) = Factory.create(C, Name); if (IsNew) - Result.push_back(Sec); + Ret.push_back(Sec); Sec->addSection(C); }; - // Select input sections matching rule and add them to corresponding - // output section. Section rules are processed in order they're listed - // in script, so correct input section order is maintained by design. - for (const std::unique_ptr &Base : Opt.Commands) { - auto *OutCmd = dyn_cast(Base.get()); - if (!OutCmd) - continue; - - for (const std::unique_ptr &Cmd : OutCmd->Commands) { - auto *InCmd = dyn_cast(Cmd.get()); - if (!InCmd) + for (auto &P : getSectionMap()) { + StringRef OutputName = P.first; + ArrayRef InputPatterns = P.second; + for (InputSectionBase *S : getInputSections(InputPatterns)) { + if (OutputName == "/DISCARD/") { + S->Live = false; + reportDiscarded(S); continue; - - for (ObjectFile &F : Symtab::X->getObjectFiles()) { - for (InputSectionBase *S : F->getSections()) { - if (isDiscarded(S) || S->OutSec) - continue; - - if (match(InCmd->Patterns, S->getSectionName())) { - if (OutCmd->Name == "/DISCARD/") - S->Live = false; - else - AddInputSec(S, OutCmd->Name); - } - } } + Add(S, OutputName); } } // Add all other input sections, which are not listed in script. - for (ObjectFile &F : Symtab::X->getObjectFiles()) - for (InputSectionBase *S : F->getSections()) { - if (!isDiscarded(S)) { - if (!S->OutSec) - AddInputSec(S, getOutputSectionName(S)); - } else - reportDiscarded(S); - } + for (const std::unique_ptr> &F : + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec) + Add(S, getOutputSectionName(S)); // Remove from the output all the sections which did not meet // the optional constraints. - return filter(Result); + return filter(Ret); } // Process ONLY_IF_RO and ONLY_IF_RW. diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index bb970458e7c6..ade95ce651cf 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -131,6 +131,11 @@ public: bool hasPhdrsCommands(); private: + std::vector>> getSectionMap(); + + std::vector *> + getInputSections(ArrayRef Patterns); + // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig;