Skip to content

Commit

Permalink
Use globMatch() instead of llvm::regex in linker scripts
Browse files Browse the repository at this point in the history
This can speed up lld up to 5 times when linking applications 
with large number of sections and using linker script.

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

llvm-svn: 285895
  • Loading branch information
eleviant777 committed Nov 3, 2016
1 parent 3aa330f commit db68845
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 14 deletions.
10 changes: 5 additions & 5 deletions lld/ELF/LinkerScript.cpp
Expand Up @@ -936,7 +936,7 @@ class elf::ScriptParser : public ScriptParserBase {
std::vector<uint8_t> readOutputSectionFiller(StringRef Tok);
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
Regex readFilePatterns();
StringMatcher readFilePatterns();
std::vector<SectionPattern> readInputSectionsList();
InputSectionDescription *readInputSectionRules(StringRef FilePattern);
unsigned readPhdrType();
Expand Down Expand Up @@ -1207,11 +1207,11 @@ static int precedence(StringRef Op) {
.Default(-1);
}

Regex ScriptParser::readFilePatterns() {
StringMatcher ScriptParser::readFilePatterns() {
std::vector<StringRef> V;
while (!Error && !consume(")"))
V.push_back(next());
return compileGlobPatterns(V);
return StringMatcher(std::move(V));
}

SortSectionPolicy ScriptParser::readSortKind() {
Expand All @@ -1236,7 +1236,7 @@ SortSectionPolicy ScriptParser::readSortKind() {
std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
std::vector<SectionPattern> Ret;
while (!Error && peek() != ")") {
Regex ExcludeFileRe;
StringMatcher ExcludeFileRe;
if (consume("EXCLUDE_FILE")) {
expect("(");
ExcludeFileRe = readFilePatterns();
Expand All @@ -1247,7 +1247,7 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
V.push_back(next());

if (!V.empty())
Ret.push_back({std::move(ExcludeFileRe), compileGlobPatterns(V)});
Ret.push_back({std::move(ExcludeFileRe), StringMatcher(std::move(V))});
else
setError("section pattern is expected");
}
Expand Down
16 changes: 7 additions & 9 deletions lld/ELF/LinkerScript.h
Expand Up @@ -19,7 +19,6 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
#include <functional>

namespace lld {
Expand Down Expand Up @@ -115,9 +114,9 @@ struct OutputSectionCommand : BaseCommand {
// It can optionally have negative match pattern for EXCLUDED_FILE command.
// Also it may be surrounded with SORT() command, so contains sorting rules.
struct SectionPattern {
SectionPattern(llvm::Regex &&Re1, llvm::Regex &&Re2)
: ExcludedFileRe(std::forward<llvm::Regex>(Re1)),
SectionRe(std::forward<llvm::Regex>(Re2)) {}
SectionPattern(StringMatcher &&Re1, StringMatcher &&Re2)
: ExcludedFileRe(std::forward<StringMatcher>(Re1)),
SectionRe(std::forward<StringMatcher>(Re2)) {}

SectionPattern(SectionPattern &&Other) {
std::swap(ExcludedFileRe, Other.ExcludedFileRe);
Expand All @@ -126,18 +125,17 @@ struct SectionPattern {
std::swap(SortInner, Other.SortInner);
}

llvm::Regex ExcludedFileRe;
llvm::Regex SectionRe;
StringMatcher ExcludedFileRe;
StringMatcher SectionRe;
SortSectionPolicy SortOuter;
SortSectionPolicy SortInner;
};

struct InputSectionDescription : BaseCommand {
InputSectionDescription(StringRef FilePattern)
: BaseCommand(InputSectionKind),
FileRe(compileGlobPatterns({FilePattern})) {}
: BaseCommand(InputSectionKind), FileRe(FilePattern) {}
static bool classof(const BaseCommand *C);
llvm::Regex FileRe;
StringMatcher FileRe;

// Input sections that matches at least one of SectionPatterns
// will be associated with this InputSectionDescription.
Expand Down
30 changes: 30 additions & 0 deletions lld/ELF/Strings.cpp
Expand Up @@ -21,6 +21,36 @@ using namespace llvm;
using namespace lld;
using namespace lld::elf;

// Returns true if S matches T. S can contain glob meta-characters.
// The asterisk ('*') matches zero or more characters, and the question
// mark ('?') matches one character.
static bool globMatch(StringRef S, StringRef T) {
for (;;) {
if (S.empty())
return T.empty();
if (S[0] == '*') {
S = S.substr(1);
if (S.empty())
// Fast path. If a pattern is '*', it matches anything.
return true;
for (size_t I = 0, E = T.size(); I < E; ++I)
if (globMatch(S, T.substr(I)))
return true;
return false;
}
if (T.empty() || (S[0] != T[0] && S[0] != '?'))
return false;
S = S.substr(1);
T = T.substr(1);
}
}

bool StringMatcher::match(StringRef S) {
for (StringRef P : Patterns)
if (globMatch(P, S))
return true;
return false;
}
// If an input string is in the form of "foo.N" where N is a number,
// return N. Otherwise, returns 65536, which is one greater than the
// lowest priority.
Expand Down
12 changes: 12 additions & 0 deletions lld/ELF/Strings.h
Expand Up @@ -25,6 +25,18 @@ std::vector<uint8_t> parseHex(StringRef S);
bool isValidCIdentifier(StringRef S);
StringRef unquote(StringRef S);

class StringMatcher {
public:
StringMatcher() = default;
explicit StringMatcher(StringRef P) : Patterns({P}) {}
explicit StringMatcher(std::vector<StringRef> &&Pat)
: Patterns(std::move(Pat)) {}

bool match(StringRef S);
private:
std::vector<StringRef> Patterns;
};

// Returns a demangled C++ symbol name. If Name is not a mangled
// name or the system does not provide __cxa_demangle function,
// it returns an unmodified string.
Expand Down

0 comments on commit db68845

Please sign in to comment.