diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -30,7 +30,6 @@ class InputSection; class Symbol; -struct SymbolPriorityEntry; using NamePair = std::pair; using SectionRenameMap = llvm::DenseMap; @@ -191,20 +190,6 @@ } }; -// The symbol with the highest priority should be ordered first in the output -// section (modulo input section contiguity constraints). Using priority -// (highest first) instead of order (lowest first) has the convenient property -// that the default-constructed zero priority -- for symbols/sections without a -// user-defined order -- naturally ends up putting them at the end of the -// output. -struct SymbolPriorityEntry { - // The priority given to a matching symbol, regardless of which object file - // it originated from. - size_t anyObjectFile = 0; - // The priority given to a matching symbol from a particular object file. - llvm::DenseMap objectFiles; -}; - // Whether to force-load an archive. enum class ForceLoad { Default, // Apply -all_load or -ObjC behaviors if those flags are enabled diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1452,8 +1452,10 @@ replaceCommonSymbols(); StringRef orderFile = args.getLastArgValue(OPT_order_file); - if (!orderFile.empty()) + if (!orderFile.empty()) { priorityBuilder.parseOrderFile(orderFile); + priorityBuilder.populatePriorities(); + } referenceStubBinder(); diff --git a/lld/MachO/SectionPriorities.h b/lld/MachO/SectionPriorities.h --- a/lld/MachO/SectionPriorities.h +++ b/lld/MachO/SectionPriorities.h @@ -11,6 +11,7 @@ #include "InputSection.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" namespace lld { namespace macho { @@ -42,6 +43,8 @@ // The file can also have line comments that start with '#'. void parseOrderFile(StringRef path); + void populatePriorities(); + // 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. @@ -56,7 +59,27 @@ llvm::DenseMap buildInputSectionPriorities(); private: + // The symbol with the highest priority should be ordered first in the output + // section (modulo input section contiguity constraints). Using priority + // (highest first) instead of order (lowest first) has the convenient property + // that the default-constructed zero priority -- for symbols/sections without + // a user-defined order -- naturally ends up putting them at the end of the + // output. + struct SymbolPriorityEntry { + // The priority given to a matching symbol, regardless of which object file + // it originated from. + size_t anyObjectFile = 0; + // The priority given to a matching symbol from a particular object file. + llvm::DenseMap objectFiles; + }; + llvm::Optional getSymbolPriority(const Defined *sym); + + using SymbolObjectFile = std::pair; + using SymbolOrder = llvm::SmallVector; + // This will be populated with symbols ordered so that the earlier + // symbols will have higher priority than the later symbols. + SymbolOrder inputOrder; llvm::DenseMap priorities; llvm::MapVector callGraphProfile; }; diff --git a/lld/MachO/SectionPriorities.cpp b/lld/MachO/SectionPriorities.cpp --- a/lld/MachO/SectionPriorities.cpp +++ b/lld/MachO/SectionPriorities.cpp @@ -283,11 +283,10 @@ entry.toIndex < obj->symbols.size()); auto *fromSym = dyn_cast_or_null(obj->symbols[entry.fromIndex]); auto *toSym = dyn_cast_or_null(obj->symbols[entry.toIndex]); - if (!fromSym || !toSym || - (hasOrderFile && - (getSymbolPriority(fromSym) || getSymbolPriority(toSym)))) - continue; - callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count; + if (fromSym && toSym && + (!hasOrderFile || + (!getSymbolPriority(fromSym) && !getSymbolPriority(toSym)))) + callGraphProfile[{fromSym->isec, toSym->isec}] += entry.count; } } } @@ -336,14 +335,22 @@ symbol = line.trim(); if (!symbol.empty()) { - SymbolPriorityEntry &entry = priorities[symbol]; - if (!objectFile.empty()) - entry.objectFiles.insert( - std::make_pair(objectFile, highestAvailablePriority)); - else - entry.anyObjectFile = - std::max(entry.anyObjectFile, highestAvailablePriority); + inputOrder.push_back(std::make_pair(symbol.str(), objectFile.str())); } + } +} + +void macho::PriorityBuilder::populatePriorities() { + for (const auto &symbolObjectFile : inputOrder) { + StringRef symbol = symbolObjectFile.first; + StringRef objectFile = symbolObjectFile.second; + SymbolPriorityEntry &entry = priorities[symbol]; + if (!objectFile.empty()) + entry.objectFiles.insert( + std::make_pair(objectFile, highestAvailablePriority)); + else + entry.anyObjectFile = + std::max(entry.anyObjectFile, highestAvailablePriority); --highestAvailablePriority; }