Split InputSectionDescription::Sort into SortInner and SortOuter.

Summary:
The comparator function to compare input sections as instructed by
SORT command was a bit too complicated because it needed to handle
four different cases. This patch split it into two function calls.

This patch also simplifies the parser.

Reviewers: grimar

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D23140

llvm-svn: 277780
This commit is contained in:
Rui Ueyama 2016-08-04 22:27:00 +00:00
parent 3bade138b5
commit 742c38361b
2 changed files with 42 additions and 42 deletions

View File

@ -135,27 +135,27 @@ static void addSection(OutputSectionFactory<ELFT> &Factory,
Sec->addSection(C); Sec->addSection(C);
} }
template <class ELFT> struct SectionsSorter { template <class ELFT>
SectionsSorter(SortKind Kind) : Kind(Kind) {} static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
bool operator()(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) { return A->getSectionName() < B->getSectionName();
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()); template <class ELFT>
if (Kind == SortKind::Name || (Kind == SortKind::NameAlign && NameCmp != 0)) static bool compareAlignment(InputSectionBase<ELFT> *A,
return NameCmp < 0; InputSectionBase<ELFT> *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;
}
if (Kind == SortKind::NameAlign) template <class ELFT>
return AlignmentCmp > 0; static std::function<bool(InputSectionBase<ELFT> *, InputSectionBase<ELFT> *)>
if (Kind == SortKind::AlignName) getComparator(SortKind K) {
return NameCmp < 0; if (K == SortByName)
return compareName<ELFT>;
llvm_unreachable("unknown section sort kind in predicate"); return compareAlignment<ELFT>;
return false; }
}
SortKind Kind;
};
template <class ELFT> template <class ELFT>
void LinkerScript<ELFT>::createSections( void LinkerScript<ELFT>::createSections(
@ -173,9 +173,12 @@ void LinkerScript<ELFT>::createSections(
continue; continue;
} }
if (Cmd->Sort != SortKind::None) if (Cmd->SortInner)
std::stable_sort(Sections.begin(), Sections.end(), std::stable_sort(Sections.begin(), Sections.end(),
SectionsSorter<ELFT>(Cmd->Sort)); getComparator<ELFT>(Cmd->SortInner));
if (Cmd->SortOuter)
std::stable_sort(Sections.begin(), Sections.end(),
getComparator<ELFT>(Cmd->SortOuter));
for (InputSectionBase<ELFT> *S : Sections) for (InputSectionBase<ELFT> *S : Sections)
addSection(Factory, *OutputSections, S, OutputName); addSection(Factory, *OutputSections, S, OutputName);
@ -489,6 +492,7 @@ private:
std::vector<StringRef> readInputFilePatterns(); std::vector<StringRef> readInputFilePatterns();
InputSectionDescription *readInputSectionRules(); InputSectionDescription *readInputSectionRules();
unsigned readPhdrType(); unsigned readPhdrType();
SortKind readSortKind();
SymbolAssignment *readProvide(bool Hidden); SymbolAssignment *readProvide(bool Hidden);
Expr readAlign(); Expr readAlign();
void readSort(); void readSort();
@ -731,41 +735,36 @@ std::vector<StringRef> ScriptParser::readInputFilePatterns() {
return V; 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() { InputSectionDescription *ScriptParser::readInputSectionRules() {
auto *Cmd = new InputSectionDescription; auto *Cmd = new InputSectionDescription;
Cmd->FilePattern = next(); Cmd->FilePattern = next();
expect("("); expect("(");
// Read EXCLUDE_FILE().
if (skip("EXCLUDE_FILE")) { if (skip("EXCLUDE_FILE")) {
expect("("); expect("(");
while (!Error && !skip(")")) while (!Error && !skip(")"))
Cmd->ExcludedFiles.push_back(next()); Cmd->ExcludedFiles.push_back(next());
} }
if (skip("SORT") || skip("SORT_BY_NAME")) { // Read SORT().
if (SortKind K1 = readSortKind()) {
Cmd->SortOuter = K1;
expect("("); expect("(");
if (skip("SORT_BY_ALIGNMENT")) { if (SortKind K2 = readSortKind()) {
Cmd->Sort = SortKind::NameAlign; Cmd->SortInner = K2;
expect("("); expect("(");
Cmd->SectionPatterns = readInputFilePatterns(); Cmd->SectionPatterns = readInputFilePatterns();
expect(")"); expect(")");
} else { } else {
Cmd->Sort = SortKind::Name;
Cmd->SectionPatterns = readInputFilePatterns();
}
expect(")");
return Cmd;
}
if (skip("SORT_BY_ALIGNMENT")) {
expect("(");
if (skip("SORT") || skip("SORT_BY_NAME")) {
Cmd->Sort = SortKind::AlignName;
expect("(");
Cmd->SectionPatterns = readInputFilePatterns();
expect(")");
} else {
Cmd->Sort = SortKind::Align;
Cmd->SectionPatterns = readInputFilePatterns(); Cmd->SectionPatterns = readInputFilePatterns();
} }
expect(")"); expect(")");

View File

@ -88,13 +88,14 @@ struct OutputSectionCommand : BaseCommand {
ConstraintKind Constraint = ConstraintKind::NoConstraint; ConstraintKind Constraint = ConstraintKind::NoConstraint;
}; };
enum class SortKind { None, Name, Align, NameAlign, AlignName }; enum SortKind { SortNone, SortByName, SortByAlignment };
struct InputSectionDescription : BaseCommand { struct InputSectionDescription : BaseCommand {
InputSectionDescription() : BaseCommand(InputSectionKind) {} InputSectionDescription() : BaseCommand(InputSectionKind) {}
static bool classof(const BaseCommand *C); static bool classof(const BaseCommand *C);
StringRef FilePattern; StringRef FilePattern;
SortKind Sort = SortKind::None; SortKind SortOuter = SortNone;
SortKind SortInner = SortNone;
std::vector<StringRef> ExcludedFiles; std::vector<StringRef> ExcludedFiles;
std::vector<StringRef> SectionPatterns; std::vector<StringRef> SectionPatterns;
}; };