xref: /freebsd/contrib/llvm-project/llvm/include/llvm/LTO/LTO.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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