[ELF] - Linkerscript: support all kinds of sorting (including nested).

Previously we supported only sorting by name.

When there are nested section sorting commands in linker script, there can be at most 1
level of nesting for section sorting commands.

SORT_BY_NAME (SORT_BY_ALIGNMENT (wildcard section pattern)). It will sort the input
sections by name first, then by alignment if 2 sections have the same name.

SORT_BY_ALIGNMENT (SORT_BY_NAME (wildcard section pattern)). It will sort the input
sections by alignment first, then by name if 2 sections have the same alignment.

SORT_BY_NAME (SORT_BY_NAME (wildcard section pattern)) is treated the same as SORT_
BY_NAME (wildcard section pattern).

SORT_BY_ALIGNMENT (SORT_BY_ALIGNMENT (wildcard section pattern)) is treated the
same as SORT_BY_ALIGNMENT (wildcard section pattern).

All other nested section sorting commands are invalid.

Patch implements that all above.

Differential revision: https://reviews.llvm.org/D23019

llvm-svn: 277583
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index c5b19845..656e646 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -131,11 +131,27 @@
   Sec->addSection(C);
 }
 
-template <class ELFT>
-static bool compareByName(InputSectionBase<ELFT> *A,
-                          InputSectionBase<ELFT> *B) {
-  return A->getSectionName() < B->getSectionName();
-}
+template <class ELFT> struct SectionsSorter {
+  SectionsSorter(SortKind Kind) : Kind(Kind) {}
+  bool operator()(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
+    int AlignmentCmp = A->Alignment - B->Alignment;
+    if (Kind == SortKind::Align || (Kind == SortKind::AlignName && AlignmentCmp != 0))
+      return AlignmentCmp < 0;
+
+    int NameCmp = A->getSectionName().compare(B->getSectionName());
+    if (Kind == SortKind::Name || (Kind == SortKind::NameAlign && NameCmp != 0))
+      return NameCmp < 0;
+
+    if (Kind == SortKind::NameAlign)
+      return AlignmentCmp < 0;
+    if (Kind == SortKind::AlignName)
+      return NameCmp < 0;
+
+    llvm_unreachable("unknown section sort kind in predicate");
+    return false;
+  }
+  SortKind Kind;
+};
 
 template <class ELFT>
 void LinkerScript<ELFT>::createSections(
@@ -155,8 +171,9 @@
       }
       Sections.push_back(S);
     }
-    if (I->Sort)
-      std::stable_sort(Sections.begin(), Sections.end(), compareByName<ELFT>);
+    if (I->Sort != SortKind::None)
+      std::stable_sort(Sections.begin(), Sections.end(),
+                       SectionsSorter<ELFT>(I->Sort));
     for (InputSectionBase<ELFT> *S : Sections)
       addSection(Factory, *Out, S, OutputName);
   }
@@ -715,10 +732,32 @@
       InCmd->ExcludedFiles.push_back(next());
   }
 
-  if (skip("SORT")) {
+  if (skip("SORT") || skip("SORT_BY_NAME")) {
     expect("(");
-    InCmd->Sort = true;
-    readInputFilePattern(InCmd, Keep);
+    if (skip("SORT_BY_ALIGNMENT")) {
+      InCmd->Sort = SortKind::NameAlign;
+      expect("(");
+      readInputFilePattern(InCmd, Keep);
+      expect(")");
+    } else {
+      InCmd->Sort = SortKind::Name;
+      readInputFilePattern(InCmd, Keep);
+    }
+    expect(")");
+    return;
+  }
+
+  if (skip("SORT_BY_ALIGNMENT")) {
+    expect("(");
+    if (skip("SORT") || skip("SORT_BY_NAME")) {
+      InCmd->Sort = SortKind::AlignName;
+      expect("(");
+      readInputFilePattern(InCmd, Keep);
+      expect(")");
+    } else {
+      InCmd->Sort = SortKind::Align;
+      readInputFilePattern(InCmd, Keep);
+    }
     expect(")");
     return;
   }