class Defined;
class InputSection;
-struct InputSectionDescription;
+class InputSectionDescription;
class OutputSection;
class Patch843419Section;
class Defined;
class InputSection;
-struct InputSectionDescription;
+class InputSectionDescription;
class OutputSection;
class Patch657417Section;
}
}
+StringRef InputFile::getNameForScript() const {
+ if (archiveName.empty())
+ return getName();
+
+ if (nameForScriptCache.empty())
+ nameForScriptCache = (archiveName + Twine(':') + getName()).str();
+
+ return nameForScriptCache;
+}
+
template <class ELFT> DWARFCache *ObjFile<ELFT>::getDwarf() {
llvm::call_once(initDwarf, [this]() {
dwarf = std::make_unique<DWARFCache>(std::make_unique<DWARFContext>(
return symbols;
}
+ // Get filename to use for linker script processing.
+ StringRef getNameForScript() const;
+
// Filename of .a which contained this file. If this file was
// not in an archive file, it is the empty string. We use this
// string for creating error messages.
private:
const Kind fileKind;
+
+ // Cache for getNameForScript().
+ mutable std::string nameForScriptCache;
};
class ELFFileBase : public InputFile {
cmd->sym->type = v.type;
}
-static std::string getFilename(InputFile *file) {
- if (!file)
- return "";
- if (file->archiveName.empty())
- return std::string(file->getName());
- return (file->archiveName + ':' + file->getName()).str();
+static inline StringRef getFilename(const InputFile *file) {
+ return file ? file->getNameForScript() : StringRef();
}
-bool LinkerScript::shouldKeep(InputSectionBase *s) {
- if (keptSections.empty())
+bool InputSectionDescription::matchesFile(const InputFile *file) const {
+ if (filePat.isTrivialMatchAll())
+ return true;
+
+ if (!matchesFileCache || matchesFileCache->first != file)
+ matchesFileCache.emplace(file, filePat.match(getFilename(file)));
+
+ return matchesFileCache->second;
+}
+
+bool SectionPattern::excludesFile(const InputFile *file) const {
+ if (excludedFilePat.empty())
return false;
- std::string filename = getFilename(s->file);
+
+ if (!excludesFileCache || excludesFileCache->first != file)
+ excludesFileCache.emplace(file, excludedFilePat.match(getFilename(file)));
+
+ return excludesFileCache->second;
+}
+
+bool LinkerScript::shouldKeep(InputSectionBase *s) {
for (InputSectionDescription *id : keptSections)
- if (id->filePat.match(filename))
+ if (id->matchesFile(s->file))
for (SectionPattern &p : id->sectionPatterns)
if (p.sectionPat.match(s->name) &&
(s->flags & id->withFlags) == id->withFlags &&
if (!pat.sectionPat.match(sec->name))
continue;
- std::string filename = getFilename(sec->file);
- if (!cmd->filePat.match(filename) ||
- pat.excludedFilePat.match(filename) ||
+ if (!cmd->matchesFile(sec->file) || pat.excludesFile(sec->file) ||
(sec->flags & cmd->withFlags) != cmd->withFlags ||
(sec->flags & cmd->withoutFlags) != 0)
continue;
namespace elf {
class Defined;
+class InputFile;
class InputSection;
class InputSectionBase;
class OutputSection;
// This struct represents one section match pattern in SECTIONS() command.
// 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 {
+class SectionPattern {
+ StringMatcher excludedFilePat;
+
+ // Cache of the most recent input argument and result of excludesFile().
+ mutable llvm::Optional<std::pair<const InputFile *, bool>> excludesFileCache;
+
+public:
SectionPattern(StringMatcher &&pat1, StringMatcher &&pat2)
: excludedFilePat(pat1), sectionPat(pat2),
sortOuter(SortSectionPolicy::Default),
sortInner(SortSectionPolicy::Default) {}
- StringMatcher excludedFilePat;
+ bool excludesFile(const InputFile *file) const;
+
StringMatcher sectionPat;
SortSectionPolicy sortOuter;
SortSectionPolicy sortInner;
};
-struct InputSectionDescription : BaseCommand {
+class InputSectionDescription : public BaseCommand {
+ SingleStringMatcher filePat;
+
+ // Cache of the most recent input argument and result of matchesFile().
+ mutable llvm::Optional<std::pair<const InputFile *, bool>> matchesFileCache;
+
+public:
InputSectionDescription(StringRef filePattern, uint64_t withFlags = 0,
uint64_t withoutFlags = 0)
: BaseCommand(InputSectionKind), filePat(filePattern),
return c->kind == InputSectionKind;
}
- SingleStringMatcher filePat;
+ bool matchesFile(const InputFile *file) const;
// Input sections that matches at least one of SectionPatterns
// will be associated with this InputSectionDescription.
class ThunkSection;
class Thunk;
-struct InputSectionDescription;
+class InputSectionDescription;
class ThunkCreator {
public:
// Match s against this pattern, exactly if ExactMatch is true.
bool match(llvm::StringRef s) const;
+ // Returns true for pattern "*" which will match all inputs.
+ bool isTrivialMatchAll() const {
+ return !ExactMatch && GlobPatternMatcher.isTrivialMatchAll();
+ }
+
private:
// Whether to do an exact match irregardless of the presence of wildcard
// character.
// Add a new pattern to the existing ones to match against.
void addPattern(SingleStringMatcher Matcher) { patterns.push_back(Matcher); }
- bool empty() { return patterns.empty(); }
+ bool empty() const { return patterns.empty(); }
// Match s against the patterns.
bool match(llvm::StringRef s) const;