diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -170,7 +170,6 @@ std::vector sectionAlignments; std::vector segmentProtections; - llvm::DenseMap priorities; llvm::MapVector, uint64_t> callGraphProfile; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1453,7 +1453,7 @@ StringRef orderFile = args.getLastArgValue(OPT_order_file); if (!orderFile.empty()) - parseOrderFile(orderFile); + priorityBuilder->parseOrderFile(orderFile); referenceStubBinder(); @@ -1510,7 +1510,7 @@ gatherInputSections(); if (config->callGraphProfileSort) - extractCallGraphProfile(); + priorityBuilder->extractCallGraphProfile(); if (config->deadStrip) markLive(); diff --git a/lld/MachO/SectionPriorities.h b/lld/MachO/SectionPriorities.h --- a/lld/MachO/SectionPriorities.h +++ b/lld/MachO/SectionPriorities.h @@ -15,41 +15,50 @@ namespace lld { namespace macho { -// Reads every input section's call graph profile, and combines them into -// config->callGraphProfile. If an order file is present, any edges where one -// or both of the vertices are specified in the order file are discarded. -void extractCallGraphProfile(); +class PriorityBuilder { +public: + // Reads every input section's call graph profile, and combines them into + // config->callGraphProfile. If an order file is present, any edges where one + // or both of the vertices are specified in the order file are discarded. + void extractCallGraphProfile(); -// Reads the order file at `path` into config->priorities. -// -// An order file has one entry per line, in the following format: -// -// :: -// -// and are optional. If not specified, then that entry -// matches any symbol of that name. Parsing this format is not quite -// straightforward because the symbol name itself can contain colons, so when -// encountering a colon, we consider the preceding characters to decide if it -// can be a valid CPU type or file path. -// -// If a symbol is matched by multiple entries, then it takes the lowest-ordered -// entry (the one nearest to the front of the list.) -// -// The file can also have line comments that start with '#'. -void parseOrderFile(StringRef path); + // Reads the order file at `path` into config->priorities. + // + // An order file has one entry per line, in the following format: + // + // :: + // + // and are optional. If not specified, then that entry + // matches any symbol of that name. Parsing this format is not quite + // straightforward because the symbol name itself can contain colons, so when + // encountering a colon, we consider the preceding characters to decide if it + // can be a valid CPU type or file path. + // + // If a symbol is matched by multiple entries, then it takes the + // lowest-ordered entry (the one nearest to the front of the list.) + // + // The file can also have line comments that start with '#'. + void parseOrderFile(StringRef path); -// Returns layout priorities for some or all input sections. Sections are laid -// out in decreasing order; that is, a higher priority section will be closer -// to the beginning of its output section. -// -// If either an order file or a call graph profile are present, this is used -// as the source of priorities. If both are present, the order file takes -// precedence, but the call graph profile is still used for symbols that don't -// appear in the order file. If neither is present, an empty map is returned. -// -// Each section gets assigned the priority of the highest-priority symbol it -// contains. -llvm::DenseMap buildInputSectionPriorities(); + // Returns layout priorities for some or all input sections. Sections are laid + // out in decreasing order; that is, a higher priority section will be closer + // to the beginning of its output section. + // + // If either an order file or a call graph profile are present, this is used + // as the source of priorities. If both are present, the order file takes + // precedence, but the call graph profile is still used for symbols that don't + // appear in the order file. If neither is present, an empty map is returned. + // + // Each section gets assigned the priority of the highest-priority symbol it + // contains. + llvm::DenseMap buildInputSectionPriorities(); + +private: + llvm::Optional getSymbolPriority(const Defined *sym); + llvm::DenseMap priorities; +}; + +extern std::unique_ptr priorityBuilder; } // namespace macho } // namespace lld diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp --- a/lld/MachO/SectionPriorities.cpp +++ b/lld/MachO/SectionPriorities.cpp @@ -34,6 +34,9 @@ using namespace lld; using namespace lld::macho; +std::unique_ptr macho::priorityBuilder = + std::make_unique(); + namespace { size_t lowestPriority = std::numeric_limits::max(); @@ -251,12 +254,12 @@ return orderMap; } -static Optional getSymbolPriority(const Defined *sym) { +Optional macho::PriorityBuilder::getSymbolPriority(const Defined *sym) { if (sym->isAbsolute()) return None; - auto it = config->priorities.find(sym->getName()); - if (it == config->priorities.end()) + auto it = priorities.find(sym->getName()); + if (it == priorities.end()) return None; const SymbolPriorityEntry &entry = it->second; const InputFile *f = sym->isec->getFile(); @@ -273,9 +276,9 @@ return std::max(entry.objectFiles.lookup(filename), entry.anyObjectFile); } -void macho::extractCallGraphProfile() { +void macho::PriorityBuilder::extractCallGraphProfile() { TimeTraceScope timeScope("Extract call graph profile"); - bool hasOrderFile = !config->priorities.empty(); + bool hasOrderFile = !priorities.empty(); for (const InputFile *file : inputFiles) { auto *obj = dyn_cast_or_null(file); if (!obj) @@ -294,7 +297,7 @@ } } -void macho::parseOrderFile(StringRef path) { +void macho::PriorityBuilder::parseOrderFile(StringRef path) { assert(config->callGraphProfile.empty() && "Order file must be parsed before call graph profile is processed"); Optional buffer = readFile(path); @@ -339,7 +342,7 @@ symbol = line.trim(); if (!symbol.empty()) { - SymbolPriorityEntry &entry = config->priorities[symbol]; + SymbolPriorityEntry &entry = priorities[symbol]; if (!objectFile.empty()) entry.objectFiles.insert(std::make_pair(objectFile, priority)); else @@ -361,12 +364,13 @@ return CallGraphSort().run(); } -DenseMap macho::buildInputSectionPriorities() { +DenseMap +macho::PriorityBuilder::buildInputSectionPriorities() { DenseMap sectionPriorities; if (config->callGraphProfileSort) sectionPriorities = computeCallGraphProfileOrder(); - if (config->priorities.empty()) + if (priorities.empty()) return sectionPriorities; auto addSym = [&](const Defined *sym) { diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -857,7 +857,7 @@ sortOutputSegments(); DenseMap isecPriorities = - buildInputSectionPriorities(); + priorityBuilder->buildInputSectionPriorities(); uint32_t sectionIndex = 0; for (OutputSegment *seg : outputSegments) {