Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -88,13 +88,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: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -135,27 +135,27 @@ 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; +template +static bool compareName(InputSectionBase *A, InputSectionBase *B) { + return A->getSectionName() < B->getSectionName(); +} - llvm_unreachable("unknown section sort kind in predicate"); - return false; - } - SortKind Kind; -}; +template +static bool compareAlignment(InputSectionBase *A, + InputSectionBase *B) { + // ">" is not a mistake. Larger alignments are placed before smaller + // alignments in order to reduce the amount of padding necessary. + // This is compatible with GNU. + return A->Alignment > B->Alignment; +} + +template +static std::function *, InputSectionBase *)> +getComparator(SortKind K) { + if (K == SortByName) + return compareName; + return compareAlignment; +} template void LinkerScript::createSections( @@ -173,9 +173,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, *OutputSections, S, OutputName); @@ -489,6 +492,7 @@ std::vector readInputFilePatterns(); InputSectionDescription *readInputSectionRules(); unsigned readPhdrType(); + SortKind readSortKind(); SymbolAssignment *readProvide(bool Hidden); Expr readAlign(); void readSort(); @@ -731,41 +735,36 @@ return V; } +SortKind ScriptParser::readSortKind() { + if (skip("SORT") || skip("SORT_BY_NAME")) + return SortByName; + if (skip("SORT_BY_ALIGNMENT")) + return SortByAlignment; + return SortNone; +} + InputSectionDescription *ScriptParser::readInputSectionRules() { auto *Cmd = new InputSectionDescription; Cmd->FilePattern = next(); expect("("); + // Read EXCLUDE_FILE(). if (skip("EXCLUDE_FILE")) { expect("("); while (!Error && !skip(")")) Cmd->ExcludedFiles.push_back(next()); } - if (skip("SORT") || skip("SORT_BY_NAME")) { - expect("("); - if (skip("SORT_BY_ALIGNMENT")) { - Cmd->Sort = SortKind::NameAlign; - expect("("); - Cmd->SectionPatterns = readInputFilePatterns(); - expect(")"); - } else { - Cmd->Sort = SortKind::Name; - Cmd->SectionPatterns = readInputFilePatterns(); - } - expect(")"); - return Cmd; - } - - if (skip("SORT_BY_ALIGNMENT")) { + // Read SORT(). + if (SortKind K1 = readSortKind()) { + Cmd->SortOuter = K1; expect("("); - if (skip("SORT") || skip("SORT_BY_NAME")) { - Cmd->Sort = SortKind::AlignName; + if (SortKind K2 = readSortKind()) { + Cmd->SortInner = K2; expect("("); Cmd->SectionPatterns = readInputFilePatterns(); expect(")"); } else { - Cmd->Sort = SortKind::Align; Cmd->SectionPatterns = readInputFilePatterns(); } expect(")");