Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -87,13 +87,14 @@ ConstraintKind Constraint = ConstraintKind::NoConstraint; }; -enum class SortKind { None, Name, Align, NameAlign, AlignName }; +enum SortKind { SortNone, SortByName, SortByAlignment }; struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); StringRef FilePattern; - SortKind Sort = SortKind::None; + SortKind SortOuter = SortNone; + SortKind SortInner = SortNone; std::vector ExcludedFiles; std::vector SectionPatterns; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -131,27 +131,24 @@ Sec->addSection(C); } -template struct SectionsSorter { - SectionsSorter(SortKind Kind) : Kind(Kind) {} - bool operator()(InputSectionBase *A, InputSectionBase *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 +static bool compareName(InputSectionBase *A, InputSectionBase *B) { + return A->getSectionName() < B->getSectionName(); +} + +template +static bool compareAlignment(InputSectionBase *A, + InputSectionBase *B) { + return A->Alignment < B->Alignment; +} + +template +static std::function *, InputSectionBase *)> +getComparator(SortKind K) { + if (K == SortByName) + return compareName; + return compareAlignment; +} template void LinkerScript::createSections( @@ -172,9 +169,12 @@ continue; } - if (Cmd->Sort != SortKind::None) + if (Cmd->SortInner) + std::stable_sort(Sections.begin(), Sections.end(), + getComparator(Cmd->SortInner)); + if (Cmd->SortOuter) std::stable_sort(Sections.begin(), Sections.end(), - SectionsSorter(Cmd->Sort)); + getComparator(Cmd->SortOuter)); for (InputSectionBase *S : Sections) addSection(Factory, *Out, S, OutputName); @@ -484,6 +484,7 @@ void readInputFilePattern(InputSectionDescription *InCmd, bool Keep); void readInputSectionRules(InputSectionDescription *InCmd, bool Keep); unsigned readPhdrType(); + SortKind readSortKind(); void readProvide(bool Hidden); void readAlign(OutputSectionCommand *Cmd); void readSort(); @@ -723,41 +724,36 @@ } } +SortKind ScriptParser::readSortKind() { + if (skip("SORT") || skip("SORT_BY_NAME")) + return SortByName; + if (skip("SORT_BY_ALIGNMENT")) + return SortByAlignment; + return SortNone; +} + void ScriptParser::readInputSectionRules(InputSectionDescription *InCmd, bool Keep) { InCmd->FilePattern = next(); expect("("); + // Read EXCLUDE_FILE(). if (skip("EXCLUDE_FILE")) { expect("("); while (!Error && !skip(")")) InCmd->ExcludedFiles.push_back(next()); } - if (skip("SORT") || skip("SORT_BY_NAME")) { - expect("("); - 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")) { + // Read SORT(). + if (SortKind K1 = readSortKind()) { + InCmd->SortOuter = K1; expect("("); - if (skip("SORT") || skip("SORT_BY_NAME")) { - InCmd->Sort = SortKind::AlignName; + if (SortKind K2 = readSortKind()) { + InCmd->SortInner = K2; expect("("); readInputFilePattern(InCmd, Keep); expect(")"); } else { - InCmd->Sort = SortKind::Align; readInputFilePattern(InCmd, Keep); } expect(")");