[lld] r276706 - Split LinkerScript::createSections into small functions.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 25 15:51:07 PDT 2016


Author: ruiu
Date: Mon Jul 25 17:51:07 2016
New Revision: 276706

URL: http://llvm.org/viewvc/llvm-project?rev=276706&view=rev
Log:
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

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=276706&r1=276705&r2=276706&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Mon Jul 25 17:51:07 2016
@@ -74,65 +74,76 @@ static bool match(ArrayRef<StringRef> Pa
   return false;
 }
 
+// Create a vector of (<output section name>, <input section name patterns>).
+// For example, if a returned vector contains (".text" (".foo.*" ".bar.*")),
+// input sections start with ".foo." or ".bar." should be added to
+// ".text" section.
+template <class ELFT>
+std::vector<std::pair<StringRef, ArrayRef<StringRef>>>
+LinkerScript<ELFT>::getSectionMap() {
+  std::vector<std::pair<StringRef, ArrayRef<StringRef>>> Ret;
+
+  for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands)
+    if (auto *Cmd1 = dyn_cast<OutputSectionCommand>(Base1.get()))
+      for (const std::unique_ptr<BaseCommand> &Base2 : Cmd1->Commands)
+        if (auto *Cmd2 = dyn_cast<InputSectionDescription>(Base2.get()))
+          Ret.emplace_back(Cmd1->Name, Cmd2->Patterns);
+
+  return Ret;
+}
+
+// Returns input sections filtered by given glob patterns.
+template <class ELFT>
+std::vector<InputSectionBase<ELFT> *>
+LinkerScript<ELFT>::getInputSections(ArrayRef<StringRef> Patterns) {
+  std::vector<InputSectionBase<ELFT> *> Ret;
+  for (const std::unique_ptr<ObjectFile<ELFT>> &F :
+       Symtab<ELFT>::X->getObjectFiles())
+    for (InputSectionBase<ELFT> *S : F->getSections())
+      if (!isDiscarded(S) && !S->OutSec && match(Patterns, S->getSectionName()))
+        Ret.push_back(S);
+  return Ret;
+}
+
 template <class ELFT>
 std::vector<OutputSectionBase<ELFT> *>
 LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
-  typedef const std::unique_ptr<ObjectFile<ELFT>> ObjectFile;
-  std::vector<OutputSectionBase<ELFT> *> Result;
+  std::vector<OutputSectionBase<ELFT> *> 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<ELFT> *C, StringRef Name) {
+  auto Add = [&](InputSectionBase<ELFT> *C, StringRef Name) {
     OutputSectionBase<ELFT> *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<BaseCommand> &Base : Opt.Commands) {
-    auto *OutCmd = dyn_cast<OutputSectionCommand>(Base.get());
-    if (!OutCmd)
-      continue;
-
-    for (const std::unique_ptr<BaseCommand> &Cmd : OutCmd->Commands) {
-      auto *InCmd = dyn_cast<InputSectionDescription>(Cmd.get());
-      if (!InCmd)
+  for (auto &P : getSectionMap()) {
+    StringRef OutputName = P.first;
+    ArrayRef<StringRef> InputPatterns = P.second;
+    for (InputSectionBase<ELFT> *S : getInputSections(InputPatterns)) {
+      if (OutputName == "/DISCARD/") {
+        S->Live = false;
+        reportDiscarded(S);
         continue;
-
-      for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) {
-        for (InputSectionBase<ELFT> *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<ELFT>::X->getObjectFiles())
-    for (InputSectionBase<ELFT> *S : F->getSections()) {
-      if (!isDiscarded(S)) {
-        if (!S->OutSec)
-          AddInputSec(S, getOutputSectionName(S));
-      } else
-        reportDiscarded(S);
-    }
+  for (const std::unique_ptr<ObjectFile<ELFT>> &F :
+       Symtab<ELFT>::X->getObjectFiles())
+    for (InputSectionBase<ELFT> *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.

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=276706&r1=276705&r2=276706&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Mon Jul 25 17:51:07 2016
@@ -131,6 +131,11 @@ public:
   bool hasPhdrsCommands();
 
 private:
+  std::vector<std::pair<StringRef, ArrayRef<StringRef>>> getSectionMap();
+
+  std::vector<InputSectionBase<ELFT> *>
+  getInputSections(ArrayRef<StringRef> Patterns);
+
   // "ScriptConfig" is a bit too long, so define a short name for it.
   ScriptConfiguration &Opt = *ScriptConfig;
 




More information about the llvm-commits mailing list