10b57cec5SDimitry Andric //===-LTO.h - LLVM Link Time Optimizer ------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares functions and classes used to support LTO. It is intended 100b57cec5SDimitry Andric // to be used both by LTO classes as well as by clients (gold-plugin) that 110b57cec5SDimitry Andric // don't utilize the LTO code generator interfaces. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #ifndef LLVM_LTO_LTO_H 160b57cec5SDimitry Andric #define LLVM_LTO_LTO_H 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h" 190b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 205ffd83dbSDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 210b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h" 220b57cec5SDimitry Andric #include "llvm/LTO/Config.h" 230b57cec5SDimitry Andric #include "llvm/Object/IRSymtab.h" 24349cc55cSDimitry Andric #include "llvm/Support/Caching.h" 250b57cec5SDimitry Andric #include "llvm/Support/Error.h" 260b57cec5SDimitry Andric #include "llvm/Support/thread.h" 27349cc55cSDimitry Andric #include "llvm/Transforms/IPO/FunctionAttrs.h" 280b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionImport.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric class Error; 335ffd83dbSDimitry Andric class IRMover; 340b57cec5SDimitry Andric class LLVMContext; 350b57cec5SDimitry Andric class MemoryBufferRef; 360b57cec5SDimitry Andric class Module; 370b57cec5SDimitry Andric class raw_pwrite_stream; 385ffd83dbSDimitry Andric class ToolOutputFile; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric /// Resolve linkage for prevailing symbols in the \p Index. Linkage changes 410b57cec5SDimitry Andric /// recorded in the index and the ThinLTO backends must apply the changes to 42349cc55cSDimitry Andric /// the module via thinLTOFinalizeInModule. 430b57cec5SDimitry Andric /// 440b57cec5SDimitry Andric /// This is done for correctness (if value exported, ensure we always 450b57cec5SDimitry Andric /// emit a copy), and compile-time optimization (allow drop of duplicates). 460b57cec5SDimitry Andric void thinLTOResolvePrevailingInIndex( 47fe6060f1SDimitry Andric const lto::Config &C, ModuleSummaryIndex &Index, 480b57cec5SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 490b57cec5SDimitry Andric isPrevailing, 500b57cec5SDimitry Andric function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> 510b57cec5SDimitry Andric recordNewLinkage, 520b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric /// Update the linkages in the given \p Index to mark exported values 550b57cec5SDimitry Andric /// as external and non-exported values as internal. The ThinLTO backends 560b57cec5SDimitry Andric /// must apply the changes to the Module via thinLTOInternalizeModule. 570b57cec5SDimitry Andric void thinLTOInternalizeAndPromoteInIndex( 580b57cec5SDimitry Andric ModuleSummaryIndex &Index, 59480093f4SDimitry Andric function_ref<bool(StringRef, ValueInfo)> isExported, 608bcb0991SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 618bcb0991SDimitry Andric isPrevailing); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// Computes a unique hash for the Module considering the current list of 640b57cec5SDimitry Andric /// export/import and other global analysis results. 650b57cec5SDimitry Andric /// The hash is produced in \p Key. 660b57cec5SDimitry Andric void computeLTOCacheKey( 670b57cec5SDimitry Andric SmallString<40> &Key, const lto::Config &Conf, 680b57cec5SDimitry Andric const ModuleSummaryIndex &Index, StringRef ModuleID, 690b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 700b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 710b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 720b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals, 730b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDefs = {}, 740b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDecls = {}); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric namespace lto { 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric /// Given the original \p Path to an output file, replace any path 790b57cec5SDimitry Andric /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the 800b57cec5SDimitry Andric /// resulting directory if it does not yet exist. 810b57cec5SDimitry Andric std::string getThinLTOOutputFile(const std::string &Path, 820b57cec5SDimitry Andric const std::string &OldPrefix, 830b57cec5SDimitry Andric const std::string &NewPrefix); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Setup optimization remarks. 86e8d8bef9SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> setupLLVMOptimizationRemarks( 87e8d8bef9SDimitry Andric LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, 88e8d8bef9SDimitry Andric StringRef RemarksFormat, bool RemarksWithHotness, 89*bdd1243dSDimitry Andric std::optional<uint64_t> RemarksHotnessThreshold = 0, int Count = -1); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric /// Setups the output file for saving statistics. 920b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> 930b57cec5SDimitry Andric setupStatsFile(StringRef StatsFilename); 940b57cec5SDimitry Andric 95e8d8bef9SDimitry Andric /// Produces a container ordering for optimal multi-threaded processing. Returns 96e8d8bef9SDimitry Andric /// ordered indices to elements in the input array. 97e8d8bef9SDimitry Andric std::vector<int> generateModulesOrdering(ArrayRef<BitcodeModule *> R); 98e8d8bef9SDimitry Andric 990b57cec5SDimitry Andric class LTO; 1000b57cec5SDimitry Andric struct SymbolResolution; 1010b57cec5SDimitry Andric class ThinBackendProc; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric /// An input file. This is a symbol table wrapper that only exposes the 1040b57cec5SDimitry Andric /// information that an LTO client should need in order to do symbol resolution. 1050b57cec5SDimitry Andric class InputFile { 1060b57cec5SDimitry Andric public: 1070b57cec5SDimitry Andric class Symbol; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric private: 1100b57cec5SDimitry Andric // FIXME: Remove LTO class friendship once we have bitcode symbol tables. 1110b57cec5SDimitry Andric friend LTO; 1120b57cec5SDimitry Andric InputFile() = default; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric std::vector<BitcodeModule> Mods; 1150b57cec5SDimitry Andric SmallVector<char, 0> Strtab; 1160b57cec5SDimitry Andric std::vector<Symbol> Symbols; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // [begin, end) for each module 1190b57cec5SDimitry Andric std::vector<std::pair<size_t, size_t>> ModuleSymIndices; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric StringRef TargetTriple, SourceFileName, COFFLinkerOpts; 1220b57cec5SDimitry Andric std::vector<StringRef> DependentLibraries; 123fe6060f1SDimitry Andric std::vector<std::pair<StringRef, Comdat::SelectionKind>> ComdatTable; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric public: 1260b57cec5SDimitry Andric ~InputFile(); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric /// Create an InputFile. 1290b57cec5SDimitry Andric static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// The purpose of this class is to only expose the symbol information that an 1320b57cec5SDimitry Andric /// LTO client should need in order to do symbol resolution. 1330b57cec5SDimitry Andric class Symbol : irsymtab::Symbol { 1340b57cec5SDimitry Andric friend LTO; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric public: 1370b57cec5SDimitry Andric Symbol(const irsymtab::Symbol &S) : irsymtab::Symbol(S) {} 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric using irsymtab::Symbol::isUndefined; 1400b57cec5SDimitry Andric using irsymtab::Symbol::isCommon; 1410b57cec5SDimitry Andric using irsymtab::Symbol::isWeak; 1420b57cec5SDimitry Andric using irsymtab::Symbol::isIndirect; 1430b57cec5SDimitry Andric using irsymtab::Symbol::getName; 1440b57cec5SDimitry Andric using irsymtab::Symbol::getIRName; 1450b57cec5SDimitry Andric using irsymtab::Symbol::getVisibility; 1460b57cec5SDimitry Andric using irsymtab::Symbol::canBeOmittedFromSymbolTable; 1470b57cec5SDimitry Andric using irsymtab::Symbol::isTLS; 1480b57cec5SDimitry Andric using irsymtab::Symbol::getComdatIndex; 1490b57cec5SDimitry Andric using irsymtab::Symbol::getCommonSize; 1500b57cec5SDimitry Andric using irsymtab::Symbol::getCommonAlignment; 1510b57cec5SDimitry Andric using irsymtab::Symbol::getCOFFWeakExternalFallback; 1520b57cec5SDimitry Andric using irsymtab::Symbol::getSectionName; 1530b57cec5SDimitry Andric using irsymtab::Symbol::isExecutable; 1540b57cec5SDimitry Andric using irsymtab::Symbol::isUsed; 1550b57cec5SDimitry Andric }; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// A range over the symbols in this InputFile. 1580b57cec5SDimitry Andric ArrayRef<Symbol> symbols() const { return Symbols; } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// Returns linker options specified in the input file. 1610b57cec5SDimitry Andric StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Returns dependent library specifiers from the input file. 1640b57cec5SDimitry Andric ArrayRef<StringRef> getDependentLibraries() const { return DependentLibraries; } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric /// Returns the path to the InputFile. 1670b57cec5SDimitry Andric StringRef getName() const; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric /// Returns the input file's target triple. 1700b57cec5SDimitry Andric StringRef getTargetTriple() const { return TargetTriple; } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Returns the source file path specified at compile time. 1730b57cec5SDimitry Andric StringRef getSourceFileName() const { return SourceFileName; } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // Returns a table with all the comdats used by this file. 176fe6060f1SDimitry Andric ArrayRef<std::pair<StringRef, Comdat::SelectionKind>> getComdatTable() const { 177fe6060f1SDimitry Andric return ComdatTable; 178fe6060f1SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Returns the only BitcodeModule from InputFile. 1810b57cec5SDimitry Andric BitcodeModule &getSingleBitcodeModule(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric private: 1840b57cec5SDimitry Andric ArrayRef<Symbol> module_symbols(unsigned I) const { 1850b57cec5SDimitry Andric const auto &Indices = ModuleSymIndices[I]; 1860b57cec5SDimitry Andric return {Symbols.data() + Indices.first, Symbols.data() + Indices.second}; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric }; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric /// A ThinBackend defines what happens after the thin-link phase during ThinLTO. 1910b57cec5SDimitry Andric /// The details of this type definition aren't important; clients can only 1920b57cec5SDimitry Andric /// create a ThinBackend using one of the create*ThinBackend() functions below. 1930b57cec5SDimitry Andric using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>( 194480093f4SDimitry Andric const Config &C, ModuleSummaryIndex &CombinedIndex, 1950b57cec5SDimitry Andric StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, 196349cc55cSDimitry Andric AddStreamFn AddStream, FileCache Cache)>; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric /// This ThinBackend runs the individual backend jobs in-process. 1995ffd83dbSDimitry Andric /// The default value means to use one job per hardware core (not hyper-thread). 20081ad6265SDimitry Andric /// OnWrite is callback which receives module identifier and notifies LTO user 20181ad6265SDimitry Andric /// that index file for the module (and optionally imports file) was created. 20281ad6265SDimitry Andric /// ShouldEmitIndexFiles being true will write sharded ThinLTO index files 20381ad6265SDimitry Andric /// to the same path as the input module, with suffix ".thinlto.bc" 20481ad6265SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a 20581ad6265SDimitry Andric /// similar path with ".imports" appended instead. 20681ad6265SDimitry Andric using IndexWriteCallback = std::function<void(const std::string &)>; 20781ad6265SDimitry Andric ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism, 20881ad6265SDimitry Andric IndexWriteCallback OnWrite = nullptr, 20981ad6265SDimitry Andric bool ShouldEmitIndexFiles = false, 21081ad6265SDimitry Andric bool ShouldEmitImportsFiles = false); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /// This ThinBackend writes individual module indexes to files, instead of 2130b57cec5SDimitry Andric /// running the individual backend jobs. This backend is for distributed builds 2140b57cec5SDimitry Andric /// where separate processes will invoke the real backends. 2150b57cec5SDimitry Andric /// 2160b57cec5SDimitry Andric /// To find the path to write the index to, the backend checks if the path has a 2170b57cec5SDimitry Andric /// prefix of OldPrefix; if so, it replaces that prefix with NewPrefix. It then 2180b57cec5SDimitry Andric /// appends ".thinlto.bc" and writes the index to that path. If 2190b57cec5SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a 2200b57cec5SDimitry Andric /// similar path with ".imports" appended instead. 2210b57cec5SDimitry Andric /// LinkedObjectsFile is an output stream to write the list of object files for 2220b57cec5SDimitry Andric /// the final ThinLTO linking. Can be nullptr. 2230b57cec5SDimitry Andric /// OnWrite is callback which receives module identifier and notifies LTO user 2240b57cec5SDimitry Andric /// that index file for the module (and optionally imports file) was created. 2250b57cec5SDimitry Andric ThinBackend createWriteIndexesThinBackend(std::string OldPrefix, 2260b57cec5SDimitry Andric std::string NewPrefix, 2270b57cec5SDimitry Andric bool ShouldEmitImportsFiles, 2280b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile, 2290b57cec5SDimitry Andric IndexWriteCallback OnWrite); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric /// This class implements a resolution-based interface to LLVM's LTO 2320b57cec5SDimitry Andric /// functionality. It supports regular LTO, parallel LTO code generation and 2330b57cec5SDimitry Andric /// ThinLTO. You can use it from a linker in the following way: 2340b57cec5SDimitry Andric /// - Set hooks and code generation options (see lto::Config struct defined in 2350b57cec5SDimitry Andric /// Config.h), and use the lto::Config object to create an lto::LTO object. 2360b57cec5SDimitry Andric /// - Create lto::InputFile objects using lto::InputFile::create(), then use 2370b57cec5SDimitry Andric /// the symbols() function to enumerate its symbols and compute a resolution 2380b57cec5SDimitry Andric /// for each symbol (see SymbolResolution below). 2390b57cec5SDimitry Andric /// - After the linker has visited each input file (and each regular object 2400b57cec5SDimitry Andric /// file) and computed a resolution for each symbol, take each lto::InputFile 2410b57cec5SDimitry Andric /// and pass it and an array of symbol resolutions to the add() function. 2420b57cec5SDimitry Andric /// - Call the getMaxTasks() function to get an upper bound on the number of 2430b57cec5SDimitry Andric /// native object files that LTO may add to the link. 2440b57cec5SDimitry Andric /// - Call the run() function. This function will use the supplied AddStream 2450b57cec5SDimitry Andric /// and Cache functions to add up to getMaxTasks() native object files to 2460b57cec5SDimitry Andric /// the link. 2470b57cec5SDimitry Andric class LTO { 2480b57cec5SDimitry Andric friend InputFile; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric public: 2510b57cec5SDimitry Andric /// Create an LTO object. A default constructed LTO object has a reasonable 2520b57cec5SDimitry Andric /// production configuration, but you can customize it by passing arguments to 2530b57cec5SDimitry Andric /// this constructor. 2540b57cec5SDimitry Andric /// FIXME: We do currently require the DiagHandler field to be set in Conf. 2550b57cec5SDimitry Andric /// Until that is fixed, a Config argument is required. 2560b57cec5SDimitry Andric LTO(Config Conf, ThinBackend Backend = nullptr, 2570b57cec5SDimitry Andric unsigned ParallelCodeGenParallelismLevel = 1); 2580b57cec5SDimitry Andric ~LTO(); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric /// Add an input file to the LTO link, using the provided symbol resolutions. 2610b57cec5SDimitry Andric /// The symbol resolutions must appear in the enumeration order given by 2620b57cec5SDimitry Andric /// InputFile::symbols(). 2630b57cec5SDimitry Andric Error add(std::unique_ptr<InputFile> Obj, ArrayRef<SymbolResolution> Res); 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric /// Returns an upper bound on the number of tasks that the client may expect. 2660b57cec5SDimitry Andric /// This may only be called after all IR object files have been added. For a 2670b57cec5SDimitry Andric /// full description of tasks see LTOBackend.h. 2680b57cec5SDimitry Andric unsigned getMaxTasks() const; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric /// Runs the LTO pipeline. This function calls the supplied AddStream 2710b57cec5SDimitry Andric /// function to add native object files to the link. 2720b57cec5SDimitry Andric /// 2730b57cec5SDimitry Andric /// The Cache parameter is optional. If supplied, it will be used to cache 2740b57cec5SDimitry Andric /// native object files and add them to the link. 2750b57cec5SDimitry Andric /// 2760b57cec5SDimitry Andric /// The client will receive at most one callback (via either AddStream or 2770b57cec5SDimitry Andric /// Cache) for each task identifier. 278349cc55cSDimitry Andric Error run(AddStreamFn AddStream, FileCache Cache = nullptr); 2790b57cec5SDimitry Andric 2808bcb0991SDimitry Andric /// Static method that returns a list of libcall symbols that can be generated 2818bcb0991SDimitry Andric /// by LTO but might not be visible from bitcode symbol table. 2828bcb0991SDimitry Andric static ArrayRef<const char*> getRuntimeLibcallSymbols(); 2838bcb0991SDimitry Andric 2840b57cec5SDimitry Andric private: 2850b57cec5SDimitry Andric Config Conf; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric struct RegularLTOState { 288480093f4SDimitry Andric RegularLTOState(unsigned ParallelCodeGenParallelismLevel, 289480093f4SDimitry Andric const Config &Conf); 2900b57cec5SDimitry Andric struct CommonResolution { 2910b57cec5SDimitry Andric uint64_t Size = 0; 2928bcb0991SDimitry Andric MaybeAlign Align; 2930b57cec5SDimitry Andric /// Record if at least one instance of the common was marked as prevailing 2940b57cec5SDimitry Andric bool Prevailing = false; 2950b57cec5SDimitry Andric }; 2960b57cec5SDimitry Andric std::map<std::string, CommonResolution> Commons; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric unsigned ParallelCodeGenParallelismLevel; 2990b57cec5SDimitry Andric LTOLLVMContext Ctx; 3000b57cec5SDimitry Andric std::unique_ptr<Module> CombinedModule; 3010b57cec5SDimitry Andric std::unique_ptr<IRMover> Mover; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // This stores the information about a regular LTO module that we have added 3040b57cec5SDimitry Andric // to the link. It will either be linked immediately (for modules without 3050b57cec5SDimitry Andric // summaries) or after summary-based dead stripping (for modules with 3060b57cec5SDimitry Andric // summaries). 3070b57cec5SDimitry Andric struct AddedModule { 3080b57cec5SDimitry Andric std::unique_ptr<Module> M; 3090b57cec5SDimitry Andric std::vector<GlobalValue *> Keep; 3100b57cec5SDimitry Andric }; 3110b57cec5SDimitry Andric std::vector<AddedModule> ModsWithSummaries; 3125ffd83dbSDimitry Andric bool EmptyCombinedModule = true; 3130b57cec5SDimitry Andric } RegularLTO; 3140b57cec5SDimitry Andric 3155ffd83dbSDimitry Andric using ModuleMapType = MapVector<StringRef, BitcodeModule>; 3165ffd83dbSDimitry Andric 3170b57cec5SDimitry Andric struct ThinLTOState { 3180b57cec5SDimitry Andric ThinLTOState(ThinBackend Backend); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric ThinBackend Backend; 3210b57cec5SDimitry Andric ModuleSummaryIndex CombinedIndex; 3225ffd83dbSDimitry Andric // The full set of bitcode modules in input order. 3235ffd83dbSDimitry Andric ModuleMapType ModuleMap; 3245ffd83dbSDimitry Andric // The bitcode modules to compile, if specified by the LTO Config. 325*bdd1243dSDimitry Andric std::optional<ModuleMapType> ModulesToCompile; 3260b57cec5SDimitry Andric DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID; 3270b57cec5SDimitry Andric } ThinLTO; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // The global resolution for a particular (mangled) symbol name. This is in 3300b57cec5SDimitry Andric // particular necessary to track whether each symbol can be internalized. 3310b57cec5SDimitry Andric // Because any input file may introduce a new cross-partition reference, we 3320b57cec5SDimitry Andric // cannot make any final internalization decisions until all input files have 3330b57cec5SDimitry Andric // been added and the client has called run(). During run() we apply 3340b57cec5SDimitry Andric // internalization decisions either directly to the module (for regular LTO) 3350b57cec5SDimitry Andric // or to the combined index (for ThinLTO). 3360b57cec5SDimitry Andric struct GlobalResolution { 3370b57cec5SDimitry Andric /// The unmangled name of the global. 3380b57cec5SDimitry Andric std::string IRName; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric /// Keep track if the symbol is visible outside of a module with a summary 3410b57cec5SDimitry Andric /// (i.e. in either a regular object or a regular LTO module without a 3420b57cec5SDimitry Andric /// summary). 3430b57cec5SDimitry Andric bool VisibleOutsideSummary = false; 3440b57cec5SDimitry Andric 345fe6060f1SDimitry Andric /// The symbol was exported dynamically, and therefore could be referenced 346fe6060f1SDimitry Andric /// by a shared library not visible to the linker. 347fe6060f1SDimitry Andric bool ExportDynamic = false; 348fe6060f1SDimitry Andric 3490b57cec5SDimitry Andric bool UnnamedAddr = true; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric /// True if module contains the prevailing definition. 3520b57cec5SDimitry Andric bool Prevailing = false; 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric /// Returns true if module contains the prevailing definition and symbol is 3550b57cec5SDimitry Andric /// an IR symbol. For example when module-level inline asm block is used, 3560b57cec5SDimitry Andric /// symbol can be prevailing in module but have no IR name. 3570b57cec5SDimitry Andric bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric /// This field keeps track of the partition number of this global. The 3600b57cec5SDimitry Andric /// regular LTO object is partition 0, while each ThinLTO object has its own 3610b57cec5SDimitry Andric /// partition number from 1 onwards. 3620b57cec5SDimitry Andric /// 3630b57cec5SDimitry Andric /// Any global that is defined or used by more than one partition, or that 3640b57cec5SDimitry Andric /// is referenced externally, may not be internalized. 3650b57cec5SDimitry Andric /// 3660b57cec5SDimitry Andric /// Partitions generally have a one-to-one correspondence with tasks, except 3670b57cec5SDimitry Andric /// that we use partition 0 for all parallel LTO code generation partitions. 3680b57cec5SDimitry Andric /// Any partitioning of the combined LTO object is done internally by the 3690b57cec5SDimitry Andric /// LTO backend. 3700b57cec5SDimitry Andric unsigned Partition = Unknown; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric /// Special partition numbers. 3730b57cec5SDimitry Andric enum : unsigned { 3740b57cec5SDimitry Andric /// A partition number has not yet been assigned to this global. 3750b57cec5SDimitry Andric Unknown = -1u, 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric /// This global is either used by more than one partition or has an 3780b57cec5SDimitry Andric /// external reference, and therefore cannot be internalized. 3790b57cec5SDimitry Andric External = -2u, 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric /// The RegularLTO partition 3820b57cec5SDimitry Andric RegularLTO = 0, 3830b57cec5SDimitry Andric }; 3840b57cec5SDimitry Andric }; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric // Global mapping from mangled symbol names to resolutions. 3870b57cec5SDimitry Andric StringMap<GlobalResolution> GlobalResolutions; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms, 3900b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res, unsigned Partition, 3910b57cec5SDimitry Andric bool InSummary); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // These functions take a range of symbol resolutions [ResI, ResE) and consume 3940b57cec5SDimitry Andric // the resolutions used by a single input module by incrementing ResI. After 3950b57cec5SDimitry Andric // these functions return, [ResI, ResE) will refer to the resolution range for 3960b57cec5SDimitry Andric // the remaining modules in the InputFile. 3970b57cec5SDimitry Andric Error addModule(InputFile &Input, unsigned ModI, 3980b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric Expected<RegularLTOState::AddedModule> 4010b57cec5SDimitry Andric addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4020b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4030b57cec5SDimitry Andric Error linkRegularLTO(RegularLTOState::AddedModule Mod, 4040b57cec5SDimitry Andric bool LivenessFromIndex); 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4070b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric Error runRegularLTO(AddStreamFn AddStream); 410349cc55cSDimitry Andric Error runThinLTO(AddStreamFn AddStream, FileCache Cache, 4110b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric Error checkPartiallySplit(); 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric mutable bool CalledGetMaxTasks = false; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // Use Optional to distinguish false from not yet initialized. 418*bdd1243dSDimitry Andric std::optional<bool> EnableSplitLTOUnit; 419fe6060f1SDimitry Andric 420fe6060f1SDimitry Andric // Identify symbols exported dynamically, and that therefore could be 421fe6060f1SDimitry Andric // referenced by a shared library not visible to the linker. 422fe6060f1SDimitry Andric DenseSet<GlobalValue::GUID> DynamicExportSymbols; 423349cc55cSDimitry Andric 424349cc55cSDimitry Andric // Diagnostic optimization remarks file 425349cc55cSDimitry Andric std::unique_ptr<ToolOutputFile> DiagnosticOutputFile; 4260b57cec5SDimitry Andric }; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric /// The resolution for a symbol. The linker must provide a SymbolResolution for 4290b57cec5SDimitry Andric /// each global symbol based on its internal resolution of that symbol. 4300b57cec5SDimitry Andric struct SymbolResolution { 4310b57cec5SDimitry Andric SymbolResolution() 4320b57cec5SDimitry Andric : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0), 433fe6060f1SDimitry Andric ExportDynamic(0), LinkerRedefined(0) {} 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric /// The linker has chosen this definition of the symbol. 4360b57cec5SDimitry Andric unsigned Prevailing : 1; 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric /// The definition of this symbol is unpreemptable at runtime and is known to 4390b57cec5SDimitry Andric /// be in this linkage unit. 4400b57cec5SDimitry Andric unsigned FinalDefinitionInLinkageUnit : 1; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric /// The definition of this symbol is visible outside of the LTO unit. 4430b57cec5SDimitry Andric unsigned VisibleToRegularObj : 1; 4440b57cec5SDimitry Andric 445fe6060f1SDimitry Andric /// The symbol was exported dynamically, and therefore could be referenced 446fe6060f1SDimitry Andric /// by a shared library not visible to the linker. 447fe6060f1SDimitry Andric unsigned ExportDynamic : 1; 448fe6060f1SDimitry Andric 4490b57cec5SDimitry Andric /// Linker redefined version of the symbol which appeared in -wrap or -defsym 4500b57cec5SDimitry Andric /// linker option. 4510b57cec5SDimitry Andric unsigned LinkerRedefined : 1; 4520b57cec5SDimitry Andric }; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric } // namespace lto 4550b57cec5SDimitry Andric } // namespace llvm 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric #endif 458