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 78*0fca6ea1SDimitry Andric StringLiteral getThinLTODefaultCPU(const Triple &TheTriple); 79*0fca6ea1SDimitry Andric 800b57cec5SDimitry Andric /// Given the original \p Path to an output file, replace any path 810b57cec5SDimitry Andric /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the 820b57cec5SDimitry Andric /// resulting directory if it does not yet exist. 8306c3fb27SDimitry Andric std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix, 8406c3fb27SDimitry Andric StringRef NewPrefix); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric /// Setup optimization remarks. 87e8d8bef9SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> setupLLVMOptimizationRemarks( 88e8d8bef9SDimitry Andric LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, 89e8d8bef9SDimitry Andric StringRef RemarksFormat, bool RemarksWithHotness, 90bdd1243dSDimitry Andric std::optional<uint64_t> RemarksHotnessThreshold = 0, int Count = -1); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Setups the output file for saving statistics. 930b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> 940b57cec5SDimitry Andric setupStatsFile(StringRef StatsFilename); 950b57cec5SDimitry Andric 96e8d8bef9SDimitry Andric /// Produces a container ordering for optimal multi-threaded processing. Returns 97e8d8bef9SDimitry Andric /// ordered indices to elements in the input array. 98e8d8bef9SDimitry Andric std::vector<int> generateModulesOrdering(ArrayRef<BitcodeModule *> R); 99e8d8bef9SDimitry Andric 10006c3fb27SDimitry Andric /// Updates MemProf attributes (and metadata) based on whether the index 10106c3fb27SDimitry Andric /// has recorded that we are linking with allocation libraries containing 10206c3fb27SDimitry Andric /// the necessary APIs for downstream transformations. 10306c3fb27SDimitry Andric void updateMemProfAttributes(Module &Mod, const ModuleSummaryIndex &Index); 10406c3fb27SDimitry Andric 1050b57cec5SDimitry Andric class LTO; 1060b57cec5SDimitry Andric struct SymbolResolution; 1070b57cec5SDimitry Andric class ThinBackendProc; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric /// An input file. This is a symbol table wrapper that only exposes the 1100b57cec5SDimitry Andric /// information that an LTO client should need in order to do symbol resolution. 1110b57cec5SDimitry Andric class InputFile { 1120b57cec5SDimitry Andric public: 1130b57cec5SDimitry Andric class Symbol; 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric private: 1160b57cec5SDimitry Andric // FIXME: Remove LTO class friendship once we have bitcode symbol tables. 1170b57cec5SDimitry Andric friend LTO; 1180b57cec5SDimitry Andric InputFile() = default; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric std::vector<BitcodeModule> Mods; 1210b57cec5SDimitry Andric SmallVector<char, 0> Strtab; 1220b57cec5SDimitry Andric std::vector<Symbol> Symbols; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric // [begin, end) for each module 1250b57cec5SDimitry Andric std::vector<std::pair<size_t, size_t>> ModuleSymIndices; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric StringRef TargetTriple, SourceFileName, COFFLinkerOpts; 1280b57cec5SDimitry Andric std::vector<StringRef> DependentLibraries; 129fe6060f1SDimitry Andric std::vector<std::pair<StringRef, Comdat::SelectionKind>> ComdatTable; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric public: 1320b57cec5SDimitry Andric ~InputFile(); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric /// Create an InputFile. 1350b57cec5SDimitry Andric static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// The purpose of this class is to only expose the symbol information that an 1380b57cec5SDimitry Andric /// LTO client should need in order to do symbol resolution. 1390b57cec5SDimitry Andric class Symbol : irsymtab::Symbol { 1400b57cec5SDimitry Andric friend LTO; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric public: Symbol(const irsymtab::Symbol & S)1430b57cec5SDimitry Andric Symbol(const irsymtab::Symbol &S) : irsymtab::Symbol(S) {} 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric using irsymtab::Symbol::isUndefined; 1460b57cec5SDimitry Andric using irsymtab::Symbol::isCommon; 1470b57cec5SDimitry Andric using irsymtab::Symbol::isWeak; 1480b57cec5SDimitry Andric using irsymtab::Symbol::isIndirect; 1490b57cec5SDimitry Andric using irsymtab::Symbol::getName; 1500b57cec5SDimitry Andric using irsymtab::Symbol::getIRName; 1510b57cec5SDimitry Andric using irsymtab::Symbol::getVisibility; 1520b57cec5SDimitry Andric using irsymtab::Symbol::canBeOmittedFromSymbolTable; 1530b57cec5SDimitry Andric using irsymtab::Symbol::isTLS; 1540b57cec5SDimitry Andric using irsymtab::Symbol::getComdatIndex; 1550b57cec5SDimitry Andric using irsymtab::Symbol::getCommonSize; 1560b57cec5SDimitry Andric using irsymtab::Symbol::getCommonAlignment; 1570b57cec5SDimitry Andric using irsymtab::Symbol::getCOFFWeakExternalFallback; 1580b57cec5SDimitry Andric using irsymtab::Symbol::getSectionName; 1590b57cec5SDimitry Andric using irsymtab::Symbol::isExecutable; 1600b57cec5SDimitry Andric using irsymtab::Symbol::isUsed; 1610b57cec5SDimitry Andric }; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// A range over the symbols in this InputFile. symbols()1640b57cec5SDimitry Andric ArrayRef<Symbol> symbols() const { return Symbols; } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric /// Returns linker options specified in the input file. getCOFFLinkerOpts()1670b57cec5SDimitry Andric StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric /// Returns dependent library specifiers from the input file. getDependentLibraries()1700b57cec5SDimitry Andric ArrayRef<StringRef> getDependentLibraries() const { return DependentLibraries; } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Returns the path to the InputFile. 1730b57cec5SDimitry Andric StringRef getName() const; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric /// Returns the input file's target triple. getTargetTriple()1760b57cec5SDimitry Andric StringRef getTargetTriple() const { return TargetTriple; } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric /// Returns the source file path specified at compile time. getSourceFileName()1790b57cec5SDimitry Andric StringRef getSourceFileName() const { return SourceFileName; } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric // Returns a table with all the comdats used by this file. getComdatTable()182fe6060f1SDimitry Andric ArrayRef<std::pair<StringRef, Comdat::SelectionKind>> getComdatTable() const { 183fe6060f1SDimitry Andric return ComdatTable; 184fe6060f1SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // Returns the only BitcodeModule from InputFile. 1870b57cec5SDimitry Andric BitcodeModule &getSingleBitcodeModule(); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric private: module_symbols(unsigned I)1900b57cec5SDimitry Andric ArrayRef<Symbol> module_symbols(unsigned I) const { 1910b57cec5SDimitry Andric const auto &Indices = ModuleSymIndices[I]; 1920b57cec5SDimitry Andric return {Symbols.data() + Indices.first, Symbols.data() + Indices.second}; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric }; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric /// A ThinBackend defines what happens after the thin-link phase during ThinLTO. 1970b57cec5SDimitry Andric /// The details of this type definition aren't important; clients can only 1980b57cec5SDimitry Andric /// create a ThinBackend using one of the create*ThinBackend() functions below. 1990b57cec5SDimitry Andric using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>( 200480093f4SDimitry Andric const Config &C, ModuleSummaryIndex &CombinedIndex, 2015f757f3fSDimitry Andric DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries, 202349cc55cSDimitry Andric AddStreamFn AddStream, FileCache Cache)>; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric /// This ThinBackend runs the individual backend jobs in-process. 2055ffd83dbSDimitry Andric /// The default value means to use one job per hardware core (not hyper-thread). 20681ad6265SDimitry Andric /// OnWrite is callback which receives module identifier and notifies LTO user 20781ad6265SDimitry Andric /// that index file for the module (and optionally imports file) was created. 20881ad6265SDimitry Andric /// ShouldEmitIndexFiles being true will write sharded ThinLTO index files 20981ad6265SDimitry Andric /// to the same path as the input module, with suffix ".thinlto.bc" 21081ad6265SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a 21181ad6265SDimitry Andric /// similar path with ".imports" appended instead. 21281ad6265SDimitry Andric using IndexWriteCallback = std::function<void(const std::string &)>; 21381ad6265SDimitry Andric ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism, 21481ad6265SDimitry Andric IndexWriteCallback OnWrite = nullptr, 21581ad6265SDimitry Andric bool ShouldEmitIndexFiles = false, 21681ad6265SDimitry Andric bool ShouldEmitImportsFiles = false); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric /// This ThinBackend writes individual module indexes to files, instead of 2190b57cec5SDimitry Andric /// running the individual backend jobs. This backend is for distributed builds 2200b57cec5SDimitry Andric /// where separate processes will invoke the real backends. 2210b57cec5SDimitry Andric /// 2220b57cec5SDimitry Andric /// To find the path to write the index to, the backend checks if the path has a 2230b57cec5SDimitry Andric /// prefix of OldPrefix; if so, it replaces that prefix with NewPrefix. It then 2240b57cec5SDimitry Andric /// appends ".thinlto.bc" and writes the index to that path. If 2250b57cec5SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a 2260b57cec5SDimitry Andric /// similar path with ".imports" appended instead. 2270b57cec5SDimitry Andric /// LinkedObjectsFile is an output stream to write the list of object files for 22806c3fb27SDimitry Andric /// the final ThinLTO linking. Can be nullptr. If LinkedObjectsFile is not 22906c3fb27SDimitry Andric /// nullptr and NativeObjectPrefix is not empty then it replaces the prefix of 23006c3fb27SDimitry Andric /// the objects with NativeObjectPrefix instead of NewPrefix. OnWrite is 23106c3fb27SDimitry Andric /// callback which receives module identifier and notifies LTO user that index 23206c3fb27SDimitry Andric /// file for the module (and optionally imports file) was created. 2330b57cec5SDimitry Andric ThinBackend createWriteIndexesThinBackend(std::string OldPrefix, 2340b57cec5SDimitry Andric std::string NewPrefix, 23506c3fb27SDimitry Andric std::string NativeObjectPrefix, 2360b57cec5SDimitry Andric bool ShouldEmitImportsFiles, 2370b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile, 2380b57cec5SDimitry Andric IndexWriteCallback OnWrite); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric /// This class implements a resolution-based interface to LLVM's LTO 2410b57cec5SDimitry Andric /// functionality. It supports regular LTO, parallel LTO code generation and 2420b57cec5SDimitry Andric /// ThinLTO. You can use it from a linker in the following way: 2430b57cec5SDimitry Andric /// - Set hooks and code generation options (see lto::Config struct defined in 2440b57cec5SDimitry Andric /// Config.h), and use the lto::Config object to create an lto::LTO object. 2450b57cec5SDimitry Andric /// - Create lto::InputFile objects using lto::InputFile::create(), then use 2460b57cec5SDimitry Andric /// the symbols() function to enumerate its symbols and compute a resolution 2470b57cec5SDimitry Andric /// for each symbol (see SymbolResolution below). 2480b57cec5SDimitry Andric /// - After the linker has visited each input file (and each regular object 2490b57cec5SDimitry Andric /// file) and computed a resolution for each symbol, take each lto::InputFile 2500b57cec5SDimitry Andric /// and pass it and an array of symbol resolutions to the add() function. 2510b57cec5SDimitry Andric /// - Call the getMaxTasks() function to get an upper bound on the number of 2520b57cec5SDimitry Andric /// native object files that LTO may add to the link. 2530b57cec5SDimitry Andric /// - Call the run() function. This function will use the supplied AddStream 2540b57cec5SDimitry Andric /// and Cache functions to add up to getMaxTasks() native object files to 2550b57cec5SDimitry Andric /// the link. 2560b57cec5SDimitry Andric class LTO { 2570b57cec5SDimitry Andric friend InputFile; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric public: 26006c3fb27SDimitry Andric /// Unified LTO modes 26106c3fb27SDimitry Andric enum LTOKind { 26206c3fb27SDimitry Andric /// Any LTO mode without Unified LTO. The default mode. 26306c3fb27SDimitry Andric LTOK_Default, 26406c3fb27SDimitry Andric 26506c3fb27SDimitry Andric /// Regular LTO, with Unified LTO enabled. 26606c3fb27SDimitry Andric LTOK_UnifiedRegular, 26706c3fb27SDimitry Andric 26806c3fb27SDimitry Andric /// ThinLTO, with Unified LTO enabled. 26906c3fb27SDimitry Andric LTOK_UnifiedThin, 27006c3fb27SDimitry Andric }; 27106c3fb27SDimitry Andric 2720b57cec5SDimitry Andric /// Create an LTO object. A default constructed LTO object has a reasonable 2730b57cec5SDimitry Andric /// production configuration, but you can customize it by passing arguments to 2740b57cec5SDimitry Andric /// this constructor. 2750b57cec5SDimitry Andric /// FIXME: We do currently require the DiagHandler field to be set in Conf. 2760b57cec5SDimitry Andric /// Until that is fixed, a Config argument is required. 2770b57cec5SDimitry Andric LTO(Config Conf, ThinBackend Backend = nullptr, 27806c3fb27SDimitry Andric unsigned ParallelCodeGenParallelismLevel = 1, 27906c3fb27SDimitry Andric LTOKind LTOMode = LTOK_Default); 2800b57cec5SDimitry Andric ~LTO(); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric /// Add an input file to the LTO link, using the provided symbol resolutions. 2830b57cec5SDimitry Andric /// The symbol resolutions must appear in the enumeration order given by 2840b57cec5SDimitry Andric /// InputFile::symbols(). 2850b57cec5SDimitry Andric Error add(std::unique_ptr<InputFile> Obj, ArrayRef<SymbolResolution> Res); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric /// Returns an upper bound on the number of tasks that the client may expect. 2880b57cec5SDimitry Andric /// This may only be called after all IR object files have been added. For a 2890b57cec5SDimitry Andric /// full description of tasks see LTOBackend.h. 2900b57cec5SDimitry Andric unsigned getMaxTasks() const; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric /// Runs the LTO pipeline. This function calls the supplied AddStream 2930b57cec5SDimitry Andric /// function to add native object files to the link. 2940b57cec5SDimitry Andric /// 2950b57cec5SDimitry Andric /// The Cache parameter is optional. If supplied, it will be used to cache 2960b57cec5SDimitry Andric /// native object files and add them to the link. 2970b57cec5SDimitry Andric /// 2980b57cec5SDimitry Andric /// The client will receive at most one callback (via either AddStream or 2990b57cec5SDimitry Andric /// Cache) for each task identifier. 300349cc55cSDimitry Andric Error run(AddStreamFn AddStream, FileCache Cache = nullptr); 3010b57cec5SDimitry Andric 3028bcb0991SDimitry Andric /// Static method that returns a list of libcall symbols that can be generated 3038bcb0991SDimitry Andric /// by LTO but might not be visible from bitcode symbol table. 304*0fca6ea1SDimitry Andric static SmallVector<const char *> getRuntimeLibcallSymbols(const Triple &TT); 3058bcb0991SDimitry Andric 3060b57cec5SDimitry Andric private: 3070b57cec5SDimitry Andric Config Conf; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric struct RegularLTOState { 310480093f4SDimitry Andric RegularLTOState(unsigned ParallelCodeGenParallelismLevel, 311480093f4SDimitry Andric const Config &Conf); 3120b57cec5SDimitry Andric struct CommonResolution { 3130b57cec5SDimitry Andric uint64_t Size = 0; 31406c3fb27SDimitry Andric Align Alignment; 3150b57cec5SDimitry Andric /// Record if at least one instance of the common was marked as prevailing 3160b57cec5SDimitry Andric bool Prevailing = false; 3170b57cec5SDimitry Andric }; 3180b57cec5SDimitry Andric std::map<std::string, CommonResolution> Commons; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric unsigned ParallelCodeGenParallelismLevel; 3210b57cec5SDimitry Andric LTOLLVMContext Ctx; 3220b57cec5SDimitry Andric std::unique_ptr<Module> CombinedModule; 3230b57cec5SDimitry Andric std::unique_ptr<IRMover> Mover; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric // This stores the information about a regular LTO module that we have added 3260b57cec5SDimitry Andric // to the link. It will either be linked immediately (for modules without 3270b57cec5SDimitry Andric // summaries) or after summary-based dead stripping (for modules with 3280b57cec5SDimitry Andric // summaries). 3290b57cec5SDimitry Andric struct AddedModule { 3300b57cec5SDimitry Andric std::unique_ptr<Module> M; 3310b57cec5SDimitry Andric std::vector<GlobalValue *> Keep; 3320b57cec5SDimitry Andric }; 3330b57cec5SDimitry Andric std::vector<AddedModule> ModsWithSummaries; 3345ffd83dbSDimitry Andric bool EmptyCombinedModule = true; 3350b57cec5SDimitry Andric } RegularLTO; 3360b57cec5SDimitry Andric 3375ffd83dbSDimitry Andric using ModuleMapType = MapVector<StringRef, BitcodeModule>; 3385ffd83dbSDimitry Andric 3390b57cec5SDimitry Andric struct ThinLTOState { 3400b57cec5SDimitry Andric ThinLTOState(ThinBackend Backend); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric ThinBackend Backend; 3430b57cec5SDimitry Andric ModuleSummaryIndex CombinedIndex; 3445ffd83dbSDimitry Andric // The full set of bitcode modules in input order. 3455ffd83dbSDimitry Andric ModuleMapType ModuleMap; 3465ffd83dbSDimitry Andric // The bitcode modules to compile, if specified by the LTO Config. 347bdd1243dSDimitry Andric std::optional<ModuleMapType> ModulesToCompile; 3480b57cec5SDimitry Andric DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID; 3490b57cec5SDimitry Andric } ThinLTO; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric // The global resolution for a particular (mangled) symbol name. This is in 3520b57cec5SDimitry Andric // particular necessary to track whether each symbol can be internalized. 3530b57cec5SDimitry Andric // Because any input file may introduce a new cross-partition reference, we 3540b57cec5SDimitry Andric // cannot make any final internalization decisions until all input files have 3550b57cec5SDimitry Andric // been added and the client has called run(). During run() we apply 3560b57cec5SDimitry Andric // internalization decisions either directly to the module (for regular LTO) 3570b57cec5SDimitry Andric // or to the combined index (for ThinLTO). 3580b57cec5SDimitry Andric struct GlobalResolution { 3590b57cec5SDimitry Andric /// The unmangled name of the global. 3600b57cec5SDimitry Andric std::string IRName; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric /// Keep track if the symbol is visible outside of a module with a summary 3630b57cec5SDimitry Andric /// (i.e. in either a regular object or a regular LTO module without a 3640b57cec5SDimitry Andric /// summary). 3650b57cec5SDimitry Andric bool VisibleOutsideSummary = false; 3660b57cec5SDimitry Andric 367fe6060f1SDimitry Andric /// The symbol was exported dynamically, and therefore could be referenced 368fe6060f1SDimitry Andric /// by a shared library not visible to the linker. 369fe6060f1SDimitry Andric bool ExportDynamic = false; 370fe6060f1SDimitry Andric 3710b57cec5SDimitry Andric bool UnnamedAddr = true; 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric /// True if module contains the prevailing definition. 3740b57cec5SDimitry Andric bool Prevailing = false; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric /// Returns true if module contains the prevailing definition and symbol is 3770b57cec5SDimitry Andric /// an IR symbol. For example when module-level inline asm block is used, 3780b57cec5SDimitry Andric /// symbol can be prevailing in module but have no IR name. isPrevailingIRSymbolGlobalResolution3790b57cec5SDimitry Andric bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric /// This field keeps track of the partition number of this global. The 3820b57cec5SDimitry Andric /// regular LTO object is partition 0, while each ThinLTO object has its own 3830b57cec5SDimitry Andric /// partition number from 1 onwards. 3840b57cec5SDimitry Andric /// 3850b57cec5SDimitry Andric /// Any global that is defined or used by more than one partition, or that 3860b57cec5SDimitry Andric /// is referenced externally, may not be internalized. 3870b57cec5SDimitry Andric /// 3880b57cec5SDimitry Andric /// Partitions generally have a one-to-one correspondence with tasks, except 3890b57cec5SDimitry Andric /// that we use partition 0 for all parallel LTO code generation partitions. 3900b57cec5SDimitry Andric /// Any partitioning of the combined LTO object is done internally by the 3910b57cec5SDimitry Andric /// LTO backend. 3920b57cec5SDimitry Andric unsigned Partition = Unknown; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric /// Special partition numbers. 3950b57cec5SDimitry Andric enum : unsigned { 3960b57cec5SDimitry Andric /// A partition number has not yet been assigned to this global. 3970b57cec5SDimitry Andric Unknown = -1u, 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric /// This global is either used by more than one partition or has an 4000b57cec5SDimitry Andric /// external reference, and therefore cannot be internalized. 4010b57cec5SDimitry Andric External = -2u, 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric /// The RegularLTO partition 4040b57cec5SDimitry Andric RegularLTO = 0, 4050b57cec5SDimitry Andric }; 4060b57cec5SDimitry Andric }; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric // Global mapping from mangled symbol names to resolutions. 4091db9f3b2SDimitry Andric // Make this an optional to guard against accessing after it has been reset 4101db9f3b2SDimitry Andric // (to reduce memory after we're done with it). 4111db9f3b2SDimitry Andric std::optional<StringMap<GlobalResolution>> GlobalResolutions; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms, 4140b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res, unsigned Partition, 4150b57cec5SDimitry Andric bool InSummary); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // These functions take a range of symbol resolutions [ResI, ResE) and consume 4180b57cec5SDimitry Andric // the resolutions used by a single input module by incrementing ResI. After 4190b57cec5SDimitry Andric // these functions return, [ResI, ResE) will refer to the resolution range for 4200b57cec5SDimitry Andric // the remaining modules in the InputFile. 4210b57cec5SDimitry Andric Error addModule(InputFile &Input, unsigned ModI, 4220b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric Expected<RegularLTOState::AddedModule> 4250b57cec5SDimitry Andric addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4260b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4270b57cec5SDimitry Andric Error linkRegularLTO(RegularLTOState::AddedModule Mod, 4280b57cec5SDimitry Andric bool LivenessFromIndex); 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4310b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric Error runRegularLTO(AddStreamFn AddStream); 434349cc55cSDimitry Andric Error runThinLTO(AddStreamFn AddStream, FileCache Cache, 4350b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric Error checkPartiallySplit(); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric mutable bool CalledGetMaxTasks = false; 4400b57cec5SDimitry Andric 44106c3fb27SDimitry Andric // LTO mode when using Unified LTO. 44206c3fb27SDimitry Andric LTOKind LTOMode; 44306c3fb27SDimitry Andric 4440b57cec5SDimitry Andric // Use Optional to distinguish false from not yet initialized. 445bdd1243dSDimitry Andric std::optional<bool> EnableSplitLTOUnit; 446fe6060f1SDimitry Andric 447fe6060f1SDimitry Andric // Identify symbols exported dynamically, and that therefore could be 448fe6060f1SDimitry Andric // referenced by a shared library not visible to the linker. 449fe6060f1SDimitry Andric DenseSet<GlobalValue::GUID> DynamicExportSymbols; 450349cc55cSDimitry Andric 451349cc55cSDimitry Andric // Diagnostic optimization remarks file 452349cc55cSDimitry Andric std::unique_ptr<ToolOutputFile> DiagnosticOutputFile; 4530b57cec5SDimitry Andric }; 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric /// The resolution for a symbol. The linker must provide a SymbolResolution for 4560b57cec5SDimitry Andric /// each global symbol based on its internal resolution of that symbol. 4570b57cec5SDimitry Andric struct SymbolResolution { SymbolResolutionSymbolResolution4580b57cec5SDimitry Andric SymbolResolution() 4590b57cec5SDimitry Andric : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0), 460fe6060f1SDimitry Andric ExportDynamic(0), LinkerRedefined(0) {} 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric /// The linker has chosen this definition of the symbol. 4630b57cec5SDimitry Andric unsigned Prevailing : 1; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric /// The definition of this symbol is unpreemptable at runtime and is known to 4660b57cec5SDimitry Andric /// be in this linkage unit. 4670b57cec5SDimitry Andric unsigned FinalDefinitionInLinkageUnit : 1; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric /// The definition of this symbol is visible outside of the LTO unit. 4700b57cec5SDimitry Andric unsigned VisibleToRegularObj : 1; 4710b57cec5SDimitry Andric 472fe6060f1SDimitry Andric /// The symbol was exported dynamically, and therefore could be referenced 473fe6060f1SDimitry Andric /// by a shared library not visible to the linker. 474fe6060f1SDimitry Andric unsigned ExportDynamic : 1; 475fe6060f1SDimitry Andric 4760b57cec5SDimitry Andric /// Linker redefined version of the symbol which appeared in -wrap or -defsym 4770b57cec5SDimitry Andric /// linker option. 4780b57cec5SDimitry Andric unsigned LinkerRedefined : 1; 4790b57cec5SDimitry Andric }; 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric } // namespace lto 4820b57cec5SDimitry Andric } // namespace llvm 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric #endif 485