104eeddc0SDimitry Andric //===- SectionPriorities.h --------------------------------------*- C++ -*-===// 204eeddc0SDimitry Andric // 304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 604eeddc0SDimitry Andric // 704eeddc0SDimitry Andric //===----------------------------------------------------------------------===// 804eeddc0SDimitry Andric 904eeddc0SDimitry Andric #ifndef LLD_MACHO_SECTION_PRIORITIES_H 1004eeddc0SDimitry Andric #define LLD_MACHO_SECTION_PRIORITIES_H 1104eeddc0SDimitry Andric 1204eeddc0SDimitry Andric #include "InputSection.h" 1304eeddc0SDimitry Andric #include "llvm/ADT/DenseMap.h" 1404eeddc0SDimitry Andric 15*bdd1243dSDimitry Andric namespace lld::macho { 1604eeddc0SDimitry Andric 1781ad6265SDimitry Andric using SectionPair = std::pair<const InputSection *, const InputSection *>; 1881ad6265SDimitry Andric 1981ad6265SDimitry Andric class PriorityBuilder { 2081ad6265SDimitry Andric public: 2104eeddc0SDimitry Andric // Reads every input section's call graph profile, and combines them into 2281ad6265SDimitry Andric // callGraphProfile. If an order file is present, any edges where one or both 2381ad6265SDimitry Andric // of the vertices are specified in the order file are discarded. 2404eeddc0SDimitry Andric void extractCallGraphProfile(); 2504eeddc0SDimitry Andric 2604eeddc0SDimitry Andric // Reads the order file at `path` into config->priorities. 2704eeddc0SDimitry Andric // 2804eeddc0SDimitry Andric // An order file has one entry per line, in the following format: 2904eeddc0SDimitry Andric // 3004eeddc0SDimitry Andric // <cpu>:<object file>:<symbol name> 3104eeddc0SDimitry Andric // 3204eeddc0SDimitry Andric // <cpu> and <object file> are optional. If not specified, then that entry 3304eeddc0SDimitry Andric // matches any symbol of that name. Parsing this format is not quite 3404eeddc0SDimitry Andric // straightforward because the symbol name itself can contain colons, so when 3504eeddc0SDimitry Andric // encountering a colon, we consider the preceding characters to decide if it 3604eeddc0SDimitry Andric // can be a valid CPU type or file path. 3704eeddc0SDimitry Andric // 3881ad6265SDimitry Andric // If a symbol is matched by multiple entries, then it takes the 3981ad6265SDimitry Andric // lowest-ordered entry (the one nearest to the front of the list.) 4004eeddc0SDimitry Andric // 4104eeddc0SDimitry Andric // The file can also have line comments that start with '#'. 4204eeddc0SDimitry Andric void parseOrderFile(StringRef path); 4304eeddc0SDimitry Andric 4404eeddc0SDimitry Andric // Returns layout priorities for some or all input sections. Sections are laid 4504eeddc0SDimitry Andric // out in decreasing order; that is, a higher priority section will be closer 4604eeddc0SDimitry Andric // to the beginning of its output section. 4704eeddc0SDimitry Andric // 4804eeddc0SDimitry Andric // If either an order file or a call graph profile are present, this is used 4904eeddc0SDimitry Andric // as the source of priorities. If both are present, the order file takes 5081ad6265SDimitry Andric // precedence, but the call graph profile is still used for symbols that don't 5181ad6265SDimitry Andric // appear in the order file. If neither is present, an empty map is returned. 5204eeddc0SDimitry Andric // 5304eeddc0SDimitry Andric // Each section gets assigned the priority of the highest-priority symbol it 5404eeddc0SDimitry Andric // contains. 5504eeddc0SDimitry Andric llvm::DenseMap<const InputSection *, size_t> buildInputSectionPriorities(); 5681ad6265SDimitry Andric 5781ad6265SDimitry Andric private: 5881ad6265SDimitry Andric // The symbol with the highest priority should be ordered first in the output 5981ad6265SDimitry Andric // section (modulo input section contiguity constraints). Using priority 6081ad6265SDimitry Andric // (highest first) instead of order (lowest first) has the convenient property 6181ad6265SDimitry Andric // that the default-constructed zero priority -- for symbols/sections without 6281ad6265SDimitry Andric // a user-defined order -- naturally ends up putting them at the end of the 6381ad6265SDimitry Andric // output. 6481ad6265SDimitry Andric struct SymbolPriorityEntry { 6581ad6265SDimitry Andric // The priority given to a matching symbol, regardless of which object file 6681ad6265SDimitry Andric // it originated from. 6781ad6265SDimitry Andric size_t anyObjectFile = 0; 6881ad6265SDimitry Andric // The priority given to a matching symbol from a particular object file. 6981ad6265SDimitry Andric llvm::DenseMap<llvm::StringRef, size_t> objectFiles; 7081ad6265SDimitry Andric }; 7181ad6265SDimitry Andric 72*bdd1243dSDimitry Andric std::optional<size_t> getSymbolPriority(const Defined *sym); 7381ad6265SDimitry Andric llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities; 7481ad6265SDimitry Andric llvm::MapVector<SectionPair, uint64_t> callGraphProfile; 7581ad6265SDimitry Andric }; 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric extern PriorityBuilder priorityBuilder; 78*bdd1243dSDimitry Andric } // namespace lld::macho 7904eeddc0SDimitry Andric 8004eeddc0SDimitry Andric #endif 81