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" 240b57cec5SDimitry Andric #include "llvm/Support/Error.h" 250b57cec5SDimitry Andric #include "llvm/Support/thread.h" 260b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionImport.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace llvm { 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric class Error; 315ffd83dbSDimitry Andric class IRMover; 320b57cec5SDimitry Andric class LLVMContext; 330b57cec5SDimitry Andric class MemoryBufferRef; 340b57cec5SDimitry Andric class Module; 350b57cec5SDimitry Andric class raw_pwrite_stream; 365ffd83dbSDimitry Andric class Target; 375ffd83dbSDimitry Andric class ToolOutputFile; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// Resolve linkage for prevailing symbols in the \p Index. Linkage changes 400b57cec5SDimitry Andric /// recorded in the index and the ThinLTO backends must apply the changes to 410b57cec5SDimitry Andric /// the module via thinLTOResolvePrevailingInModule. 420b57cec5SDimitry Andric /// 430b57cec5SDimitry Andric /// This is done for correctness (if value exported, ensure we always 440b57cec5SDimitry Andric /// emit a copy), and compile-time optimization (allow drop of duplicates). 450b57cec5SDimitry Andric void thinLTOResolvePrevailingInIndex( 460b57cec5SDimitry Andric ModuleSummaryIndex &Index, 470b57cec5SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 480b57cec5SDimitry Andric isPrevailing, 490b57cec5SDimitry Andric function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> 500b57cec5SDimitry Andric recordNewLinkage, 510b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric /// Update the linkages in the given \p Index to mark exported values 540b57cec5SDimitry Andric /// as external and non-exported values as internal. The ThinLTO backends 550b57cec5SDimitry Andric /// must apply the changes to the Module via thinLTOInternalizeModule. 560b57cec5SDimitry Andric void thinLTOInternalizeAndPromoteInIndex( 570b57cec5SDimitry Andric ModuleSummaryIndex &Index, 58480093f4SDimitry Andric function_ref<bool(StringRef, ValueInfo)> isExported, 598bcb0991SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> 608bcb0991SDimitry Andric isPrevailing); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Computes a unique hash for the Module considering the current list of 630b57cec5SDimitry Andric /// export/import and other global analysis results. 640b57cec5SDimitry Andric /// The hash is produced in \p Key. 650b57cec5SDimitry Andric void computeLTOCacheKey( 660b57cec5SDimitry Andric SmallString<40> &Key, const lto::Config &Conf, 670b57cec5SDimitry Andric const ModuleSummaryIndex &Index, StringRef ModuleID, 680b57cec5SDimitry Andric const FunctionImporter::ImportMapTy &ImportList, 690b57cec5SDimitry Andric const FunctionImporter::ExportSetTy &ExportList, 700b57cec5SDimitry Andric const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR, 710b57cec5SDimitry Andric const GVSummaryMapTy &DefinedGlobals, 720b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDefs = {}, 730b57cec5SDimitry Andric const std::set<GlobalValue::GUID> &CfiFunctionDecls = {}); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric namespace lto { 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric /// Given the original \p Path to an output file, replace any path 780b57cec5SDimitry Andric /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the 790b57cec5SDimitry Andric /// resulting directory if it does not yet exist. 800b57cec5SDimitry Andric std::string getThinLTOOutputFile(const std::string &Path, 810b57cec5SDimitry Andric const std::string &OldPrefix, 820b57cec5SDimitry Andric const std::string &NewPrefix); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// Setup optimization remarks. 85*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> setupLLVMOptimizationRemarks( 86*e8d8bef9SDimitry Andric LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, 87*e8d8bef9SDimitry Andric StringRef RemarksFormat, bool RemarksWithHotness, 88*e8d8bef9SDimitry Andric Optional<uint64_t> RemarksHotnessThreshold = 0, int Count = -1); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// Setups the output file for saving statistics. 910b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>> 920b57cec5SDimitry Andric setupStatsFile(StringRef StatsFilename); 930b57cec5SDimitry Andric 94*e8d8bef9SDimitry Andric /// Produces a container ordering for optimal multi-threaded processing. Returns 95*e8d8bef9SDimitry Andric /// ordered indices to elements in the input array. 96*e8d8bef9SDimitry Andric std::vector<int> generateModulesOrdering(ArrayRef<BitcodeModule *> R); 97*e8d8bef9SDimitry Andric 980b57cec5SDimitry Andric class LTO; 990b57cec5SDimitry Andric struct SymbolResolution; 1000b57cec5SDimitry Andric class ThinBackendProc; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// An input file. This is a symbol table wrapper that only exposes the 1030b57cec5SDimitry Andric /// information that an LTO client should need in order to do symbol resolution. 1040b57cec5SDimitry Andric class InputFile { 1050b57cec5SDimitry Andric public: 1060b57cec5SDimitry Andric class Symbol; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric private: 1090b57cec5SDimitry Andric // FIXME: Remove LTO class friendship once we have bitcode symbol tables. 1100b57cec5SDimitry Andric friend LTO; 1110b57cec5SDimitry Andric InputFile() = default; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric std::vector<BitcodeModule> Mods; 1140b57cec5SDimitry Andric SmallVector<char, 0> Strtab; 1150b57cec5SDimitry Andric std::vector<Symbol> Symbols; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // [begin, end) for each module 1180b57cec5SDimitry Andric std::vector<std::pair<size_t, size_t>> ModuleSymIndices; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric StringRef TargetTriple, SourceFileName, COFFLinkerOpts; 1210b57cec5SDimitry Andric std::vector<StringRef> DependentLibraries; 1220b57cec5SDimitry Andric std::vector<StringRef> ComdatTable; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric public: 1250b57cec5SDimitry Andric ~InputFile(); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// Create an InputFile. 1280b57cec5SDimitry Andric static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// The purpose of this class is to only expose the symbol information that an 1310b57cec5SDimitry Andric /// LTO client should need in order to do symbol resolution. 1320b57cec5SDimitry Andric class Symbol : irsymtab::Symbol { 1330b57cec5SDimitry Andric friend LTO; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric public: 1360b57cec5SDimitry Andric Symbol(const irsymtab::Symbol &S) : irsymtab::Symbol(S) {} 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric using irsymtab::Symbol::isUndefined; 1390b57cec5SDimitry Andric using irsymtab::Symbol::isCommon; 1400b57cec5SDimitry Andric using irsymtab::Symbol::isWeak; 1410b57cec5SDimitry Andric using irsymtab::Symbol::isIndirect; 1420b57cec5SDimitry Andric using irsymtab::Symbol::getName; 1430b57cec5SDimitry Andric using irsymtab::Symbol::getIRName; 1440b57cec5SDimitry Andric using irsymtab::Symbol::getVisibility; 1450b57cec5SDimitry Andric using irsymtab::Symbol::canBeOmittedFromSymbolTable; 1460b57cec5SDimitry Andric using irsymtab::Symbol::isTLS; 1470b57cec5SDimitry Andric using irsymtab::Symbol::getComdatIndex; 1480b57cec5SDimitry Andric using irsymtab::Symbol::getCommonSize; 1490b57cec5SDimitry Andric using irsymtab::Symbol::getCommonAlignment; 1500b57cec5SDimitry Andric using irsymtab::Symbol::getCOFFWeakExternalFallback; 1510b57cec5SDimitry Andric using irsymtab::Symbol::getSectionName; 1520b57cec5SDimitry Andric using irsymtab::Symbol::isExecutable; 1530b57cec5SDimitry Andric using irsymtab::Symbol::isUsed; 1540b57cec5SDimitry Andric }; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /// A range over the symbols in this InputFile. 1570b57cec5SDimitry Andric ArrayRef<Symbol> symbols() const { return Symbols; } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// Returns linker options specified in the input file. 1600b57cec5SDimitry Andric StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// Returns dependent library specifiers from the input file. 1630b57cec5SDimitry Andric ArrayRef<StringRef> getDependentLibraries() const { return DependentLibraries; } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /// Returns the path to the InputFile. 1660b57cec5SDimitry Andric StringRef getName() const; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric /// Returns the input file's target triple. 1690b57cec5SDimitry Andric StringRef getTargetTriple() const { return TargetTriple; } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric /// Returns the source file path specified at compile time. 1720b57cec5SDimitry Andric StringRef getSourceFileName() const { return SourceFileName; } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // Returns a table with all the comdats used by this file. 1750b57cec5SDimitry Andric ArrayRef<StringRef> getComdatTable() const { return ComdatTable; } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric // Returns the only BitcodeModule from InputFile. 1780b57cec5SDimitry Andric BitcodeModule &getSingleBitcodeModule(); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric private: 1810b57cec5SDimitry Andric ArrayRef<Symbol> module_symbols(unsigned I) const { 1820b57cec5SDimitry Andric const auto &Indices = ModuleSymIndices[I]; 1830b57cec5SDimitry Andric return {Symbols.data() + Indices.first, Symbols.data() + Indices.second}; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric }; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric /// This class wraps an output stream for a native object. Most clients should 1880b57cec5SDimitry Andric /// just be able to return an instance of this base class from the stream 1890b57cec5SDimitry Andric /// callback, but if a client needs to perform some action after the stream is 1900b57cec5SDimitry Andric /// written to, that can be done by deriving from this class and overriding the 1910b57cec5SDimitry Andric /// destructor. 1920b57cec5SDimitry Andric class NativeObjectStream { 1930b57cec5SDimitry Andric public: 1940b57cec5SDimitry Andric NativeObjectStream(std::unique_ptr<raw_pwrite_stream> OS) : OS(std::move(OS)) {} 1950b57cec5SDimitry Andric std::unique_ptr<raw_pwrite_stream> OS; 1960b57cec5SDimitry Andric virtual ~NativeObjectStream() = default; 1970b57cec5SDimitry Andric }; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric /// This type defines the callback to add a native object that is generated on 2000b57cec5SDimitry Andric /// the fly. 2010b57cec5SDimitry Andric /// 2020b57cec5SDimitry Andric /// Stream callbacks must be thread safe. 2030b57cec5SDimitry Andric using AddStreamFn = 2040b57cec5SDimitry Andric std::function<std::unique_ptr<NativeObjectStream>(unsigned Task)>; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric /// This is the type of a native object cache. To request an item from the 2070b57cec5SDimitry Andric /// cache, pass a unique string as the Key. For hits, the cached file will be 2080b57cec5SDimitry Andric /// added to the link and this function will return AddStreamFn(). For misses, 2090b57cec5SDimitry Andric /// the cache will return a stream callback which must be called at most once to 2100b57cec5SDimitry Andric /// produce content for the stream. The native object stream produced by the 2110b57cec5SDimitry Andric /// stream callback will add the file to the link after the stream is written 2120b57cec5SDimitry Andric /// to. 2130b57cec5SDimitry Andric /// 2140b57cec5SDimitry Andric /// Clients generally look like this: 2150b57cec5SDimitry Andric /// 2160b57cec5SDimitry Andric /// if (AddStreamFn AddStream = Cache(Task, Key)) 2170b57cec5SDimitry Andric /// ProduceContent(AddStream); 2180b57cec5SDimitry Andric using NativeObjectCache = 2190b57cec5SDimitry Andric std::function<AddStreamFn(unsigned Task, StringRef Key)>; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric /// A ThinBackend defines what happens after the thin-link phase during ThinLTO. 2220b57cec5SDimitry Andric /// The details of this type definition aren't important; clients can only 2230b57cec5SDimitry Andric /// create a ThinBackend using one of the create*ThinBackend() functions below. 2240b57cec5SDimitry Andric using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>( 225480093f4SDimitry Andric const Config &C, ModuleSummaryIndex &CombinedIndex, 2260b57cec5SDimitry Andric StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, 2270b57cec5SDimitry Andric AddStreamFn AddStream, NativeObjectCache Cache)>; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric /// This ThinBackend runs the individual backend jobs in-process. 2305ffd83dbSDimitry Andric /// The default value means to use one job per hardware core (not hyper-thread). 2315ffd83dbSDimitry Andric ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric /// This ThinBackend writes individual module indexes to files, instead of 2340b57cec5SDimitry Andric /// running the individual backend jobs. This backend is for distributed builds 2350b57cec5SDimitry Andric /// where separate processes will invoke the real backends. 2360b57cec5SDimitry Andric /// 2370b57cec5SDimitry Andric /// To find the path to write the index to, the backend checks if the path has a 2380b57cec5SDimitry Andric /// prefix of OldPrefix; if so, it replaces that prefix with NewPrefix. It then 2390b57cec5SDimitry Andric /// appends ".thinlto.bc" and writes the index to that path. If 2400b57cec5SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a 2410b57cec5SDimitry Andric /// similar path with ".imports" appended instead. 2420b57cec5SDimitry Andric /// LinkedObjectsFile is an output stream to write the list of object files for 2430b57cec5SDimitry Andric /// the final ThinLTO linking. Can be nullptr. 2440b57cec5SDimitry Andric /// OnWrite is callback which receives module identifier and notifies LTO user 2450b57cec5SDimitry Andric /// that index file for the module (and optionally imports file) was created. 2460b57cec5SDimitry Andric using IndexWriteCallback = std::function<void(const std::string &)>; 2470b57cec5SDimitry Andric ThinBackend createWriteIndexesThinBackend(std::string OldPrefix, 2480b57cec5SDimitry Andric std::string NewPrefix, 2490b57cec5SDimitry Andric bool ShouldEmitImportsFiles, 2500b57cec5SDimitry Andric raw_fd_ostream *LinkedObjectsFile, 2510b57cec5SDimitry Andric IndexWriteCallback OnWrite); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric /// This class implements a resolution-based interface to LLVM's LTO 2540b57cec5SDimitry Andric /// functionality. It supports regular LTO, parallel LTO code generation and 2550b57cec5SDimitry Andric /// ThinLTO. You can use it from a linker in the following way: 2560b57cec5SDimitry Andric /// - Set hooks and code generation options (see lto::Config struct defined in 2570b57cec5SDimitry Andric /// Config.h), and use the lto::Config object to create an lto::LTO object. 2580b57cec5SDimitry Andric /// - Create lto::InputFile objects using lto::InputFile::create(), then use 2590b57cec5SDimitry Andric /// the symbols() function to enumerate its symbols and compute a resolution 2600b57cec5SDimitry Andric /// for each symbol (see SymbolResolution below). 2610b57cec5SDimitry Andric /// - After the linker has visited each input file (and each regular object 2620b57cec5SDimitry Andric /// file) and computed a resolution for each symbol, take each lto::InputFile 2630b57cec5SDimitry Andric /// and pass it and an array of symbol resolutions to the add() function. 2640b57cec5SDimitry Andric /// - Call the getMaxTasks() function to get an upper bound on the number of 2650b57cec5SDimitry Andric /// native object files that LTO may add to the link. 2660b57cec5SDimitry Andric /// - Call the run() function. This function will use the supplied AddStream 2670b57cec5SDimitry Andric /// and Cache functions to add up to getMaxTasks() native object files to 2680b57cec5SDimitry Andric /// the link. 2690b57cec5SDimitry Andric class LTO { 2700b57cec5SDimitry Andric friend InputFile; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric public: 2730b57cec5SDimitry Andric /// Create an LTO object. A default constructed LTO object has a reasonable 2740b57cec5SDimitry Andric /// production configuration, but you can customize it by passing arguments to 2750b57cec5SDimitry Andric /// this constructor. 2760b57cec5SDimitry Andric /// FIXME: We do currently require the DiagHandler field to be set in Conf. 2770b57cec5SDimitry Andric /// Until that is fixed, a Config argument is required. 2780b57cec5SDimitry Andric LTO(Config Conf, ThinBackend Backend = nullptr, 2790b57cec5SDimitry Andric unsigned ParallelCodeGenParallelismLevel = 1); 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. 3000b57cec5SDimitry Andric Error run(AddStreamFn AddStream, NativeObjectCache 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. 3048bcb0991SDimitry Andric static ArrayRef<const char*> getRuntimeLibcallSymbols(); 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; 3148bcb0991SDimitry Andric MaybeAlign Align; 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. 3475ffd83dbSDimitry Andric 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 3670b57cec5SDimitry Andric bool UnnamedAddr = true; 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric /// True if module contains the prevailing definition. 3700b57cec5SDimitry Andric bool Prevailing = false; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric /// Returns true if module contains the prevailing definition and symbol is 3730b57cec5SDimitry Andric /// an IR symbol. For example when module-level inline asm block is used, 3740b57cec5SDimitry Andric /// symbol can be prevailing in module but have no IR name. 3750b57cec5SDimitry Andric bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric /// This field keeps track of the partition number of this global. The 3780b57cec5SDimitry Andric /// regular LTO object is partition 0, while each ThinLTO object has its own 3790b57cec5SDimitry Andric /// partition number from 1 onwards. 3800b57cec5SDimitry Andric /// 3810b57cec5SDimitry Andric /// Any global that is defined or used by more than one partition, or that 3820b57cec5SDimitry Andric /// is referenced externally, may not be internalized. 3830b57cec5SDimitry Andric /// 3840b57cec5SDimitry Andric /// Partitions generally have a one-to-one correspondence with tasks, except 3850b57cec5SDimitry Andric /// that we use partition 0 for all parallel LTO code generation partitions. 3860b57cec5SDimitry Andric /// Any partitioning of the combined LTO object is done internally by the 3870b57cec5SDimitry Andric /// LTO backend. 3880b57cec5SDimitry Andric unsigned Partition = Unknown; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric /// Special partition numbers. 3910b57cec5SDimitry Andric enum : unsigned { 3920b57cec5SDimitry Andric /// A partition number has not yet been assigned to this global. 3930b57cec5SDimitry Andric Unknown = -1u, 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric /// This global is either used by more than one partition or has an 3960b57cec5SDimitry Andric /// external reference, and therefore cannot be internalized. 3970b57cec5SDimitry Andric External = -2u, 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric /// The RegularLTO partition 4000b57cec5SDimitry Andric RegularLTO = 0, 4010b57cec5SDimitry Andric }; 4020b57cec5SDimitry Andric }; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // Global mapping from mangled symbol names to resolutions. 4050b57cec5SDimitry Andric StringMap<GlobalResolution> GlobalResolutions; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms, 4080b57cec5SDimitry Andric ArrayRef<SymbolResolution> Res, unsigned Partition, 4090b57cec5SDimitry Andric bool InSummary); 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // These functions take a range of symbol resolutions [ResI, ResE) and consume 4120b57cec5SDimitry Andric // the resolutions used by a single input module by incrementing ResI. After 4130b57cec5SDimitry Andric // these functions return, [ResI, ResE) will refer to the resolution range for 4140b57cec5SDimitry Andric // the remaining modules in the InputFile. 4150b57cec5SDimitry Andric Error addModule(InputFile &Input, unsigned ModI, 4160b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric Expected<RegularLTOState::AddedModule> 4190b57cec5SDimitry Andric addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4200b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4210b57cec5SDimitry Andric Error linkRegularLTO(RegularLTOState::AddedModule Mod, 4220b57cec5SDimitry Andric bool LivenessFromIndex); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms, 4250b57cec5SDimitry Andric const SymbolResolution *&ResI, const SymbolResolution *ResE); 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric Error runRegularLTO(AddStreamFn AddStream); 4280b57cec5SDimitry Andric Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, 4290b57cec5SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric Error checkPartiallySplit(); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric mutable bool CalledGetMaxTasks = false; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric // Use Optional to distinguish false from not yet initialized. 4360b57cec5SDimitry Andric Optional<bool> EnableSplitLTOUnit; 4370b57cec5SDimitry Andric }; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric /// The resolution for a symbol. The linker must provide a SymbolResolution for 4400b57cec5SDimitry Andric /// each global symbol based on its internal resolution of that symbol. 4410b57cec5SDimitry Andric struct SymbolResolution { 4420b57cec5SDimitry Andric SymbolResolution() 4430b57cec5SDimitry Andric : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0), 4440b57cec5SDimitry Andric LinkerRedefined(0) {} 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric /// The linker has chosen this definition of the symbol. 4470b57cec5SDimitry Andric unsigned Prevailing : 1; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric /// The definition of this symbol is unpreemptable at runtime and is known to 4500b57cec5SDimitry Andric /// be in this linkage unit. 4510b57cec5SDimitry Andric unsigned FinalDefinitionInLinkageUnit : 1; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric /// The definition of this symbol is visible outside of the LTO unit. 4540b57cec5SDimitry Andric unsigned VisibleToRegularObj : 1; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric /// Linker redefined version of the symbol which appeared in -wrap or -defsym 4570b57cec5SDimitry Andric /// linker option. 4580b57cec5SDimitry Andric unsigned LinkerRedefined : 1; 4590b57cec5SDimitry Andric }; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric } // namespace lto 4620b57cec5SDimitry Andric } // namespace llvm 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric #endif 465