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