Simplify SORT and --sort-section command line option handling.
authorRui Ueyama <ruiu@google.com>
Tue, 20 Sep 2016 19:42:41 +0000 (19:42 +0000)
committerRui Ueyama <ruiu@google.com>
Tue, 20 Sep 2016 19:42:41 +0000 (19:42 +0000)
Differential Revision: https://reviews.llvm.org/D24685

llvm-svn: 282006

lld/ELF/LinkerScript.cpp
lld/test/ELF/linkerscript/sort.s

index ea2c14b..f092691 100644 (file)
@@ -156,6 +156,12 @@ static bool matchConstraints(ArrayRef<InputSectionBase<ELFT> *> Sections,
   });
 }
 
+static void sortSections(std::vector<InputSectionData *> &Sections,
+                         SortSectionPolicy K) {
+  if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None)
+    std::stable_sort(Sections.begin(), Sections.end(), getComparator(K));
+}
+
 // Compute and remember which sections the InputSectionDescription matches.
 template <class ELFT>
 void LinkerScript<ELFT>::computeInputSections(InputSectionDescription *I) {
@@ -175,13 +181,24 @@ void LinkerScript<ELFT>::computeInputSections(InputSectionDescription *I) {
     }
   }
 
-  // Sort for SORT() commands.
-  if (I->SortInner != SortSectionPolicy::Default)
-    std::stable_sort(I->Sections.begin(), I->Sections.end(),
-                     getComparator(I->SortInner));
-  if (I->SortOuter != SortSectionPolicy::Default)
-    std::stable_sort(I->Sections.begin(), I->Sections.end(),
-                     getComparator(I->SortOuter));
+  // Sort sections as instructed by SORT-family commands and --sort-section
+  // option. Because SORT-family commands can be nested at most two depth
+  // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command
+  // line option is respected even if a SORT command is given, the exact
+  // behavior we have here is a bit complicated. Here are the rules.
+  //
+  // 1. If two SORT commands are given, --sort-section is ignored.
+  // 2. If one SORT command is given, and if it is not SORT_NONE,
+  //    --sort-section is handled as an inner SORT command.
+  // 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
+  // 4. If no SORT command is given, sort according to --sort-section.
+  if (I->SortOuter != SortSectionPolicy::None) {
+    if (I->SortInner == SortSectionPolicy::Default)
+      sortSections(I->Sections, Config->SortSection);
+    else
+      sortSections(I->Sections, I->SortInner);
+    sortSections(I->Sections, I->SortOuter);
+  }
 
   // We do not add duplicate input sections, so mark them with a dummy output
   // section for now.
@@ -1058,27 +1075,6 @@ SortSectionPolicy ScriptParser::readSortKind() {
   return SortSectionPolicy::Default;
 }
 
-static void selectSortKind(InputSectionDescription *Cmd) {
-  if (Cmd->SortOuter == SortSectionPolicy::None) {
-    Cmd->SortOuter = SortSectionPolicy::Default;
-    return;
-  }
-
-  if (Cmd->SortOuter != SortSectionPolicy::Default) {
-    // If the section sorting command in linker script is nested, the command
-    // line option will be ignored.
-    if (Cmd->SortInner != SortSectionPolicy::Default)
-      return;
-    // If the section sorting command in linker script isn't nested, the
-    // command line option will make the section sorting command to be treated
-    // as nested sorting command.
-    Cmd->SortInner = Config->SortSection;
-    return;
-  }
-  // If sorting rule not specified, use command line option.
-  Cmd->SortOuter = Config->SortSection;
-}
-
 // Method reads a list of sequence of excluded files and section globs given in
 // a following form: ((EXCLUDE_FILE(file_pattern+))? section_pattern+)+
 // Example: *(.foo.1 EXCLUDE_FILE (*a.o) .foo.2 EXCLUDE_FILE (*b.o) .foo.3)
@@ -1133,11 +1129,9 @@ ScriptParser::readInputSectionRules(StringRef FilePattern) {
       Cmd->SectionPatterns.push_back({Regex(), readFilePatterns()});
     }
     expect(")");
-    selectSortKind(Cmd);
     return Cmd;
   }
 
-  selectSortKind(Cmd);
   readSectionExcludes(Cmd);
   return Cmd;
 }
index 34bdc2f..e2781d4 100644 (file)
 # RUN: ld.lld --sort-section name -o %t10 --script %t9.script %t2.o %t1.o
 # RUN: llvm-objdump -s %t10 | FileCheck -check-prefix=UNSORTED %s
 
+## SORT_NONE as a inner sort directive.
+# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(SORT_NONE(.aaa.*))) } }" > %t10.script
+# RUN: ld.lld -o %t11 --script %t10.script %t2.o %t1.o
+# RUN: llvm-objdump -s %t11 | FileCheck -check-prefix=SORTED_A %s
 
 .global _start
 _start: