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