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" 14*0fca6ea1SDimitry Andric #include "llvm/ADT/MapVector.h" 1504eeddc0SDimitry Andric 16bdd1243dSDimitry Andric namespace lld::macho { 1704eeddc0SDimitry Andric 1881ad6265SDimitry Andric using SectionPair = std::pair<const InputSection *, const InputSection *>; 1981ad6265SDimitry Andric 2081ad6265SDimitry Andric class PriorityBuilder { 2181ad6265SDimitry Andric public: 2204eeddc0SDimitry Andric // Reads every input section's call graph profile, and combines them into 2381ad6265SDimitry Andric // callGraphProfile. If an order file is present, any edges where one or both 2481ad6265SDimitry Andric // of the vertices are specified in the order file are discarded. 2504eeddc0SDimitry Andric void extractCallGraphProfile(); 2604eeddc0SDimitry Andric 2704eeddc0SDimitry Andric // Reads the order file at `path` into config->priorities. 2804eeddc0SDimitry Andric // 2904eeddc0SDimitry Andric // An order file has one entry per line, in the following format: 3004eeddc0SDimitry Andric // 3104eeddc0SDimitry Andric // <cpu>:<object file>:<symbol name> 3204eeddc0SDimitry Andric // 3304eeddc0SDimitry Andric // <cpu> and <object file> are optional. If not specified, then that entry 3404eeddc0SDimitry Andric // matches any symbol of that name. Parsing this format is not quite 3504eeddc0SDimitry Andric // straightforward because the symbol name itself can contain colons, so when 3604eeddc0SDimitry Andric // encountering a colon, we consider the preceding characters to decide if it 3704eeddc0SDimitry Andric // can be a valid CPU type or file path. 3804eeddc0SDimitry Andric // 3981ad6265SDimitry Andric // If a symbol is matched by multiple entries, then it takes the 4081ad6265SDimitry Andric // lowest-ordered entry (the one nearest to the front of the list.) 4104eeddc0SDimitry Andric // 4204eeddc0SDimitry Andric // The file can also have line comments that start with '#'. 4304eeddc0SDimitry Andric void parseOrderFile(StringRef path); 4404eeddc0SDimitry Andric 4504eeddc0SDimitry Andric // Returns layout priorities for some or all input sections. Sections are laid 4604eeddc0SDimitry Andric // out in decreasing order; that is, a higher priority section will be closer 4704eeddc0SDimitry Andric // to the beginning of its output section. 4804eeddc0SDimitry Andric // 4904eeddc0SDimitry Andric // If either an order file or a call graph profile are present, this is used 5004eeddc0SDimitry Andric // as the source of priorities. If both are present, the order file takes 5181ad6265SDimitry Andric // precedence, but the call graph profile is still used for symbols that don't 5281ad6265SDimitry Andric // appear in the order file. If neither is present, an empty map is returned. 5304eeddc0SDimitry Andric // 5404eeddc0SDimitry Andric // Each section gets assigned the priority of the highest-priority symbol it 5504eeddc0SDimitry Andric // contains. 5604eeddc0SDimitry Andric llvm::DenseMap<const InputSection *, size_t> buildInputSectionPriorities(); 5781ad6265SDimitry Andric 5881ad6265SDimitry Andric private: 5981ad6265SDimitry Andric // The symbol with the highest priority should be ordered first in the output 6081ad6265SDimitry Andric // section (modulo input section contiguity constraints). Using priority 6181ad6265SDimitry Andric // (highest first) instead of order (lowest first) has the convenient property 6281ad6265SDimitry Andric // that the default-constructed zero priority -- for symbols/sections without 6381ad6265SDimitry Andric // a user-defined order -- naturally ends up putting them at the end of the 6481ad6265SDimitry Andric // output. 6581ad6265SDimitry Andric struct SymbolPriorityEntry { 6681ad6265SDimitry Andric // The priority given to a matching symbol, regardless of which object file 6781ad6265SDimitry Andric // it originated from. 6881ad6265SDimitry Andric size_t anyObjectFile = 0; 6981ad6265SDimitry Andric // The priority given to a matching symbol from a particular object file. 7081ad6265SDimitry Andric llvm::DenseMap<llvm::StringRef, size_t> objectFiles; 7181ad6265SDimitry Andric }; 7281ad6265SDimitry Andric 73bdd1243dSDimitry Andric std::optional<size_t> getSymbolPriority(const Defined *sym); 7481ad6265SDimitry Andric llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities; 7581ad6265SDimitry Andric llvm::MapVector<SectionPair, uint64_t> callGraphProfile; 7681ad6265SDimitry Andric }; 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric extern PriorityBuilder priorityBuilder; 79bdd1243dSDimitry Andric } // namespace lld::macho 8004eeddc0SDimitry Andric 8104eeddc0SDimitry Andric #endif 82