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 namespace lld { namespace macho { @@ -19,6 +20,7 @@ class PriorityBuilder { public: + using SymbolOrder = std::vector>; // Reads every input section's call graph profile, and combines them into // callGraphProfile. If an order file is present, any edges where one or both // of the vertices are specified in the order file are discarded. @@ -42,6 +44,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. @@ -57,6 +61,9 @@ private: llvm::Optional getSymbolPriority(const Defined *sym); + // 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, objectFile)); } + } +} + +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; }