xref: /freebsd/contrib/llvm-project/llvm/include/llvm/LTO/LTO.h (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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"
200b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
210b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
230b57cec5SDimitry Andric #include "llvm/IR/RemarkStreamer.h"
240b57cec5SDimitry Andric #include "llvm/LTO/Config.h"
250b57cec5SDimitry Andric #include "llvm/Linker/IRMover.h"
260b57cec5SDimitry Andric #include "llvm/Object/IRSymtab.h"
270b57cec5SDimitry Andric #include "llvm/Support/Error.h"
280b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
290b57cec5SDimitry Andric #include "llvm/Support/thread.h"
300b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
310b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionImport.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace llvm {
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric class BitcodeModule;
360b57cec5SDimitry Andric class Error;
370b57cec5SDimitry Andric class LLVMContext;
380b57cec5SDimitry Andric class MemoryBufferRef;
390b57cec5SDimitry Andric class Module;
400b57cec5SDimitry Andric class Target;
410b57cec5SDimitry Andric class raw_pwrite_stream;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// Resolve linkage for prevailing symbols in the \p Index. Linkage changes
440b57cec5SDimitry Andric /// recorded in the index and the ThinLTO backends must apply the changes to
450b57cec5SDimitry Andric /// the module via thinLTOResolvePrevailingInModule.
460b57cec5SDimitry Andric ///
470b57cec5SDimitry Andric /// This is done for correctness (if value exported, ensure we always
480b57cec5SDimitry Andric /// emit a copy), and compile-time optimization (allow drop of duplicates).
490b57cec5SDimitry Andric void thinLTOResolvePrevailingInIndex(
500b57cec5SDimitry Andric     ModuleSummaryIndex &Index,
510b57cec5SDimitry Andric     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
520b57cec5SDimitry Andric         isPrevailing,
530b57cec5SDimitry Andric     function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
540b57cec5SDimitry Andric         recordNewLinkage,
550b57cec5SDimitry Andric     const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric /// Update the linkages in the given \p Index to mark exported values
580b57cec5SDimitry Andric /// as external and non-exported values as internal. The ThinLTO backends
590b57cec5SDimitry Andric /// must apply the changes to the Module via thinLTOInternalizeModule.
600b57cec5SDimitry Andric void thinLTOInternalizeAndPromoteInIndex(
610b57cec5SDimitry Andric     ModuleSummaryIndex &Index,
62*480093f4SDimitry Andric     function_ref<bool(StringRef, ValueInfo)> isExported,
638bcb0991SDimitry Andric     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
648bcb0991SDimitry Andric         isPrevailing);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric /// Computes a unique hash for the Module considering the current list of
670b57cec5SDimitry Andric /// export/import and other global analysis results.
680b57cec5SDimitry Andric /// The hash is produced in \p Key.
690b57cec5SDimitry Andric void computeLTOCacheKey(
700b57cec5SDimitry Andric     SmallString<40> &Key, const lto::Config &Conf,
710b57cec5SDimitry Andric     const ModuleSummaryIndex &Index, StringRef ModuleID,
720b57cec5SDimitry Andric     const FunctionImporter::ImportMapTy &ImportList,
730b57cec5SDimitry Andric     const FunctionImporter::ExportSetTy &ExportList,
740b57cec5SDimitry Andric     const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
750b57cec5SDimitry Andric     const GVSummaryMapTy &DefinedGlobals,
760b57cec5SDimitry Andric     const std::set<GlobalValue::GUID> &CfiFunctionDefs = {},
770b57cec5SDimitry Andric     const std::set<GlobalValue::GUID> &CfiFunctionDecls = {});
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric namespace lto {
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric /// Given the original \p Path to an output file, replace any path
820b57cec5SDimitry Andric /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
830b57cec5SDimitry Andric /// resulting directory if it does not yet exist.
840b57cec5SDimitry Andric std::string getThinLTOOutputFile(const std::string &Path,
850b57cec5SDimitry Andric                                  const std::string &OldPrefix,
860b57cec5SDimitry Andric                                  const std::string &NewPrefix);
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric /// Setup optimization remarks.
890b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>>
900b57cec5SDimitry Andric setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
910b57cec5SDimitry Andric                          StringRef RemarksPasses, StringRef RemarksFormat,
920b57cec5SDimitry Andric                          bool RemarksWithHotness, int Count = -1);
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric /// Setups the output file for saving statistics.
950b57cec5SDimitry Andric Expected<std::unique_ptr<ToolOutputFile>>
960b57cec5SDimitry Andric setupStatsFile(StringRef StatsFilename);
970b57cec5SDimitry 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>(
225*480093f4SDimitry 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.
2300b57cec5SDimitry Andric ThinBackend createInProcessThinBackend(unsigned ParallelismLevel);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric /// This ThinBackend writes individual module indexes to files, instead of
2330b57cec5SDimitry Andric /// running the individual backend jobs. This backend is for distributed builds
2340b57cec5SDimitry Andric /// where separate processes will invoke the real backends.
2350b57cec5SDimitry Andric ///
2360b57cec5SDimitry Andric /// To find the path to write the index to, the backend checks if the path has a
2370b57cec5SDimitry Andric /// prefix of OldPrefix; if so, it replaces that prefix with NewPrefix. It then
2380b57cec5SDimitry Andric /// appends ".thinlto.bc" and writes the index to that path. If
2390b57cec5SDimitry Andric /// ShouldEmitImportsFiles is true it also writes a list of imported files to a
2400b57cec5SDimitry Andric /// similar path with ".imports" appended instead.
2410b57cec5SDimitry Andric /// LinkedObjectsFile is an output stream to write the list of object files for
2420b57cec5SDimitry Andric /// the final ThinLTO linking. Can be nullptr.
2430b57cec5SDimitry Andric /// OnWrite is callback which receives module identifier and notifies LTO user
2440b57cec5SDimitry Andric /// that index file for the module (and optionally imports file) was created.
2450b57cec5SDimitry Andric using IndexWriteCallback = std::function<void(const std::string &)>;
2460b57cec5SDimitry Andric ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
2470b57cec5SDimitry Andric                                           std::string NewPrefix,
2480b57cec5SDimitry Andric                                           bool ShouldEmitImportsFiles,
2490b57cec5SDimitry Andric                                           raw_fd_ostream *LinkedObjectsFile,
2500b57cec5SDimitry Andric                                           IndexWriteCallback OnWrite);
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric /// This class implements a resolution-based interface to LLVM's LTO
2530b57cec5SDimitry Andric /// functionality. It supports regular LTO, parallel LTO code generation and
2540b57cec5SDimitry Andric /// ThinLTO. You can use it from a linker in the following way:
2550b57cec5SDimitry Andric /// - Set hooks and code generation options (see lto::Config struct defined in
2560b57cec5SDimitry Andric ///   Config.h), and use the lto::Config object to create an lto::LTO object.
2570b57cec5SDimitry Andric /// - Create lto::InputFile objects using lto::InputFile::create(), then use
2580b57cec5SDimitry Andric ///   the symbols() function to enumerate its symbols and compute a resolution
2590b57cec5SDimitry Andric ///   for each symbol (see SymbolResolution below).
2600b57cec5SDimitry Andric /// - After the linker has visited each input file (and each regular object
2610b57cec5SDimitry Andric ///   file) and computed a resolution for each symbol, take each lto::InputFile
2620b57cec5SDimitry Andric ///   and pass it and an array of symbol resolutions to the add() function.
2630b57cec5SDimitry Andric /// - Call the getMaxTasks() function to get an upper bound on the number of
2640b57cec5SDimitry Andric ///   native object files that LTO may add to the link.
2650b57cec5SDimitry Andric /// - Call the run() function. This function will use the supplied AddStream
2660b57cec5SDimitry Andric ///   and Cache functions to add up to getMaxTasks() native object files to
2670b57cec5SDimitry Andric ///   the link.
2680b57cec5SDimitry Andric class LTO {
2690b57cec5SDimitry Andric   friend InputFile;
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric public:
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,
2780b57cec5SDimitry Andric       unsigned ParallelCodeGenParallelismLevel = 1);
2790b57cec5SDimitry Andric   ~LTO();
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   /// Add an input file to the LTO link, using the provided symbol resolutions.
2820b57cec5SDimitry Andric   /// The symbol resolutions must appear in the enumeration order given by
2830b57cec5SDimitry Andric   /// InputFile::symbols().
2840b57cec5SDimitry Andric   Error add(std::unique_ptr<InputFile> Obj, ArrayRef<SymbolResolution> Res);
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   /// Returns an upper bound on the number of tasks that the client may expect.
2870b57cec5SDimitry Andric   /// This may only be called after all IR object files have been added. For a
2880b57cec5SDimitry Andric   /// full description of tasks see LTOBackend.h.
2890b57cec5SDimitry Andric   unsigned getMaxTasks() const;
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   /// Runs the LTO pipeline. This function calls the supplied AddStream
2920b57cec5SDimitry Andric   /// function to add native object files to the link.
2930b57cec5SDimitry Andric   ///
2940b57cec5SDimitry Andric   /// The Cache parameter is optional. If supplied, it will be used to cache
2950b57cec5SDimitry Andric   /// native object files and add them to the link.
2960b57cec5SDimitry Andric   ///
2970b57cec5SDimitry Andric   /// The client will receive at most one callback (via either AddStream or
2980b57cec5SDimitry Andric   /// Cache) for each task identifier.
2990b57cec5SDimitry Andric   Error run(AddStreamFn AddStream, NativeObjectCache Cache = nullptr);
3000b57cec5SDimitry Andric 
3018bcb0991SDimitry Andric   /// Static method that returns a list of libcall symbols that can be generated
3028bcb0991SDimitry Andric   /// by LTO but might not be visible from bitcode symbol table.
3038bcb0991SDimitry Andric   static ArrayRef<const char*> getRuntimeLibcallSymbols();
3048bcb0991SDimitry Andric 
3050b57cec5SDimitry Andric private:
3060b57cec5SDimitry Andric   Config Conf;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   struct RegularLTOState {
309*480093f4SDimitry Andric     RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
310*480093f4SDimitry Andric                     const Config &Conf);
3110b57cec5SDimitry Andric     struct CommonResolution {
3120b57cec5SDimitry Andric       uint64_t Size = 0;
3138bcb0991SDimitry Andric       MaybeAlign Align;
3140b57cec5SDimitry Andric       /// Record if at least one instance of the common was marked as prevailing
3150b57cec5SDimitry Andric       bool Prevailing = false;
3160b57cec5SDimitry Andric     };
3170b57cec5SDimitry Andric     std::map<std::string, CommonResolution> Commons;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric     unsigned ParallelCodeGenParallelismLevel;
3200b57cec5SDimitry Andric     LTOLLVMContext Ctx;
3210b57cec5SDimitry Andric     std::unique_ptr<Module> CombinedModule;
3220b57cec5SDimitry Andric     std::unique_ptr<IRMover> Mover;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric     // This stores the information about a regular LTO module that we have added
3250b57cec5SDimitry Andric     // to the link. It will either be linked immediately (for modules without
3260b57cec5SDimitry Andric     // summaries) or after summary-based dead stripping (for modules with
3270b57cec5SDimitry Andric     // summaries).
3280b57cec5SDimitry Andric     struct AddedModule {
3290b57cec5SDimitry Andric       std::unique_ptr<Module> M;
3300b57cec5SDimitry Andric       std::vector<GlobalValue *> Keep;
3310b57cec5SDimitry Andric     };
3320b57cec5SDimitry Andric     std::vector<AddedModule> ModsWithSummaries;
3330b57cec5SDimitry Andric   } RegularLTO;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   struct ThinLTOState {
3360b57cec5SDimitry Andric     ThinLTOState(ThinBackend Backend);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     ThinBackend Backend;
3390b57cec5SDimitry Andric     ModuleSummaryIndex CombinedIndex;
3400b57cec5SDimitry Andric     MapVector<StringRef, BitcodeModule> ModuleMap;
3410b57cec5SDimitry Andric     DenseMap<GlobalValue::GUID, StringRef> PrevailingModuleForGUID;
3420b57cec5SDimitry Andric   } ThinLTO;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   // The global resolution for a particular (mangled) symbol name. This is in
3450b57cec5SDimitry Andric   // particular necessary to track whether each symbol can be internalized.
3460b57cec5SDimitry Andric   // Because any input file may introduce a new cross-partition reference, we
3470b57cec5SDimitry Andric   // cannot make any final internalization decisions until all input files have
3480b57cec5SDimitry Andric   // been added and the client has called run(). During run() we apply
3490b57cec5SDimitry Andric   // internalization decisions either directly to the module (for regular LTO)
3500b57cec5SDimitry Andric   // or to the combined index (for ThinLTO).
3510b57cec5SDimitry Andric   struct GlobalResolution {
3520b57cec5SDimitry Andric     /// The unmangled name of the global.
3530b57cec5SDimitry Andric     std::string IRName;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     /// Keep track if the symbol is visible outside of a module with a summary
3560b57cec5SDimitry Andric     /// (i.e. in either a regular object or a regular LTO module without a
3570b57cec5SDimitry Andric     /// summary).
3580b57cec5SDimitry Andric     bool VisibleOutsideSummary = false;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     bool UnnamedAddr = true;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric     /// True if module contains the prevailing definition.
3630b57cec5SDimitry Andric     bool Prevailing = false;
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric     /// Returns true if module contains the prevailing definition and symbol is
3660b57cec5SDimitry Andric     /// an IR symbol. For example when module-level inline asm block is used,
3670b57cec5SDimitry Andric     /// symbol can be prevailing in module but have no IR name.
3680b57cec5SDimitry Andric     bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric     /// This field keeps track of the partition number of this global. The
3710b57cec5SDimitry Andric     /// regular LTO object is partition 0, while each ThinLTO object has its own
3720b57cec5SDimitry Andric     /// partition number from 1 onwards.
3730b57cec5SDimitry Andric     ///
3740b57cec5SDimitry Andric     /// Any global that is defined or used by more than one partition, or that
3750b57cec5SDimitry Andric     /// is referenced externally, may not be internalized.
3760b57cec5SDimitry Andric     ///
3770b57cec5SDimitry Andric     /// Partitions generally have a one-to-one correspondence with tasks, except
3780b57cec5SDimitry Andric     /// that we use partition 0 for all parallel LTO code generation partitions.
3790b57cec5SDimitry Andric     /// Any partitioning of the combined LTO object is done internally by the
3800b57cec5SDimitry Andric     /// LTO backend.
3810b57cec5SDimitry Andric     unsigned Partition = Unknown;
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric     /// Special partition numbers.
3840b57cec5SDimitry Andric     enum : unsigned {
3850b57cec5SDimitry Andric       /// A partition number has not yet been assigned to this global.
3860b57cec5SDimitry Andric       Unknown = -1u,
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric       /// This global is either used by more than one partition or has an
3890b57cec5SDimitry Andric       /// external reference, and therefore cannot be internalized.
3900b57cec5SDimitry Andric       External = -2u,
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric       /// The RegularLTO partition
3930b57cec5SDimitry Andric       RegularLTO = 0,
3940b57cec5SDimitry Andric     };
3950b57cec5SDimitry Andric   };
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   // Global mapping from mangled symbol names to resolutions.
3980b57cec5SDimitry Andric   StringMap<GlobalResolution> GlobalResolutions;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
4010b57cec5SDimitry Andric                             ArrayRef<SymbolResolution> Res, unsigned Partition,
4020b57cec5SDimitry Andric                             bool InSummary);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   // These functions take a range of symbol resolutions [ResI, ResE) and consume
4050b57cec5SDimitry Andric   // the resolutions used by a single input module by incrementing ResI. After
4060b57cec5SDimitry Andric   // these functions return, [ResI, ResE) will refer to the resolution range for
4070b57cec5SDimitry Andric   // the remaining modules in the InputFile.
4080b57cec5SDimitry Andric   Error addModule(InputFile &Input, unsigned ModI,
4090b57cec5SDimitry Andric                   const SymbolResolution *&ResI, const SymbolResolution *ResE);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   Expected<RegularLTOState::AddedModule>
4120b57cec5SDimitry Andric   addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
4130b57cec5SDimitry Andric                 const SymbolResolution *&ResI, const SymbolResolution *ResE);
4140b57cec5SDimitry Andric   Error linkRegularLTO(RegularLTOState::AddedModule Mod,
4150b57cec5SDimitry Andric                        bool LivenessFromIndex);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
4180b57cec5SDimitry Andric                    const SymbolResolution *&ResI, const SymbolResolution *ResE);
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   Error runRegularLTO(AddStreamFn AddStream);
4210b57cec5SDimitry Andric   Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
4220b57cec5SDimitry Andric                    const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   Error checkPartiallySplit();
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   mutable bool CalledGetMaxTasks = false;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   // Use Optional to distinguish false from not yet initialized.
4290b57cec5SDimitry Andric   Optional<bool> EnableSplitLTOUnit;
4300b57cec5SDimitry Andric };
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric /// The resolution for a symbol. The linker must provide a SymbolResolution for
4330b57cec5SDimitry Andric /// each global symbol based on its internal resolution of that symbol.
4340b57cec5SDimitry Andric struct SymbolResolution {
4350b57cec5SDimitry Andric   SymbolResolution()
4360b57cec5SDimitry Andric       : Prevailing(0), FinalDefinitionInLinkageUnit(0), VisibleToRegularObj(0),
4370b57cec5SDimitry Andric         LinkerRedefined(0) {}
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   /// The linker has chosen this definition of the symbol.
4400b57cec5SDimitry Andric   unsigned Prevailing : 1;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   /// The definition of this symbol is unpreemptable at runtime and is known to
4430b57cec5SDimitry Andric   /// be in this linkage unit.
4440b57cec5SDimitry Andric   unsigned FinalDefinitionInLinkageUnit : 1;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   /// The definition of this symbol is visible outside of the LTO unit.
4470b57cec5SDimitry Andric   unsigned VisibleToRegularObj : 1;
4480b57cec5SDimitry 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