1303231Sdim//===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// This file declares the ThinLTOCodeGenerator class, similar to the 10303231Sdim// LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for 11303231Sdim// linker plugin. 12303231Sdim// 13303231Sdim//===----------------------------------------------------------------------===// 14303231Sdim 15303231Sdim#ifndef LLVM_LTO_THINLTOCODEGENERATOR_H 16303231Sdim#define LLVM_LTO_THINLTOCODEGENERATOR_H 17303231Sdim 18303231Sdim#include "llvm-c/lto.h" 19303231Sdim#include "llvm/ADT/StringSet.h" 20303231Sdim#include "llvm/ADT/Triple.h" 21303231Sdim#include "llvm/IR/ModuleSummaryIndex.h" 22353358Sdim#include "llvm/LTO/LTO.h" 23321369Sdim#include "llvm/Support/CachePruning.h" 24303231Sdim#include "llvm/Support/CodeGen.h" 25303231Sdim#include "llvm/Support/MemoryBuffer.h" 26303231Sdim#include "llvm/Target/TargetOptions.h" 27303231Sdim 28303231Sdim#include <string> 29303231Sdim 30303231Sdimnamespace llvm { 31303231Sdimclass StringRef; 32303231Sdimclass LLVMContext; 33303231Sdimclass TargetMachine; 34303231Sdim 35303231Sdim/// Helper to gather options relevant to the target machine creation 36303231Sdimstruct TargetMachineBuilder { 37303231Sdim Triple TheTriple; 38303231Sdim std::string MCpu; 39303231Sdim std::string MAttr; 40303231Sdim TargetOptions Options; 41303231Sdim Optional<Reloc::Model> RelocModel; 42314564Sdim CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive; 43303231Sdim 44303231Sdim std::unique_ptr<TargetMachine> create() const; 45303231Sdim}; 46303231Sdim 47303231Sdim/// This class define an interface similar to the LTOCodeGenerator, but adapted 48303231Sdim/// for ThinLTO processing. 49303231Sdim/// The ThinLTOCodeGenerator is not intended to be reuse for multiple 50303231Sdim/// compilation: the model is that the client adds modules to the generator and 51303231Sdim/// ask to perform the ThinLTO optimizations / codegen, and finally destroys the 52303231Sdim/// codegenerator. 53303231Sdimclass ThinLTOCodeGenerator { 54303231Sdimpublic: 55303231Sdim /// Add given module to the code generator. 56303231Sdim void addModule(StringRef Identifier, StringRef Data); 57303231Sdim 58303231Sdim /** 59303231Sdim * Adds to a list of all global symbols that must exist in the final generated 60303231Sdim * code. If a symbol is not listed there, it will be optimized away if it is 61303231Sdim * inlined into every usage. 62303231Sdim */ 63303231Sdim void preserveSymbol(StringRef Name); 64303231Sdim 65303231Sdim /** 66303231Sdim * Adds to a list of all global symbols that are cross-referenced between 67303231Sdim * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every 68303231Sdim * references from a ThinLTO module to this symbol is optimized away, then 69303231Sdim * the symbol can be discarded. 70303231Sdim */ 71303231Sdim void crossReferenceSymbol(StringRef Name); 72303231Sdim 73303231Sdim /** 74303231Sdim * Process all the modules that were added to the code generator in parallel. 75303231Sdim * 76314564Sdim * Client can access the resulting object files using getProducedBinaries(), 77314564Sdim * unless setGeneratedObjectsDirectory() has been called, in which case 78314564Sdim * results are available through getProducedBinaryFiles(). 79303231Sdim */ 80303231Sdim void run(); 81303231Sdim 82303231Sdim /** 83314564Sdim * Return the "in memory" binaries produced by the code generator. This is 84314564Sdim * filled after run() unless setGeneratedObjectsDirectory() has been 85314564Sdim * called, in which case results are available through 86314564Sdim * getProducedBinaryFiles(). 87303231Sdim */ 88303231Sdim std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() { 89303231Sdim return ProducedBinaries; 90303231Sdim } 91303231Sdim 92303231Sdim /** 93314564Sdim * Return the "on-disk" binaries produced by the code generator. This is 94314564Sdim * filled after run() when setGeneratedObjectsDirectory() has been 95314564Sdim * called, in which case results are available through getProducedBinaries(). 96314564Sdim */ 97314564Sdim std::vector<std::string> &getProducedBinaryFiles() { 98314564Sdim return ProducedBinaryFiles; 99314564Sdim } 100314564Sdim 101314564Sdim /** 102303231Sdim * \defgroup Options setters 103303231Sdim * @{ 104303231Sdim */ 105303231Sdim 106303231Sdim /** 107303231Sdim * \defgroup Cache controlling options 108303231Sdim * 109303231Sdim * These entry points control the ThinLTO cache. The cache is intended to 110303231Sdim * support incremental build, and thus needs to be persistent accross build. 111303231Sdim * The client enabled the cache by supplying a path to an existing directory. 112303231Sdim * The code generator will use this to store objects files that may be reused 113303231Sdim * during a subsequent build. 114303231Sdim * To avoid filling the disk space, a few knobs are provided: 115303231Sdim * - The pruning interval limit the frequency at which the garbage collector 116303231Sdim * will try to scan the cache directory to prune it from expired entries. 117341825Sdim * Setting to -1 disable the pruning (default). Setting to 0 will force 118341825Sdim * pruning to occur. 119303231Sdim * - The pruning expiration time indicates to the garbage collector how old 120303231Sdim * an entry needs to be to be removed. 121303231Sdim * - Finally, the garbage collector can be instructed to prune the cache till 122303231Sdim * the occupied space goes below a threshold. 123303231Sdim * @{ 124303231Sdim */ 125303231Sdim 126303231Sdim struct CachingOptions { 127303231Sdim std::string Path; // Path to the cache, empty to disable. 128321369Sdim CachePruningPolicy Policy; 129303231Sdim }; 130303231Sdim 131303231Sdim /// Provide a path to a directory where to store the cached files for 132303231Sdim /// incremental build. 133303231Sdim void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); } 134303231Sdim 135327952Sdim /// Cache policy: interval (seconds) between two prunes of the cache. Set to a 136341825Sdim /// negative value to disable pruning. A value of 0 will force pruning to 137341825Sdim /// occur. 138303231Sdim void setCachePruningInterval(int Interval) { 139327952Sdim if(Interval < 0) 140327952Sdim CacheOptions.Policy.Interval.reset(); 141327952Sdim else 142321369Sdim CacheOptions.Policy.Interval = std::chrono::seconds(Interval); 143303231Sdim } 144303231Sdim 145303231Sdim /// Cache policy: expiration (in seconds) for an entry. 146303231Sdim /// A value of 0 will be ignored. 147303231Sdim void setCacheEntryExpiration(unsigned Expiration) { 148303231Sdim if (Expiration) 149321369Sdim CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration); 150303231Sdim } 151303231Sdim 152303231Sdim /** 153303231Sdim * Sets the maximum cache size that can be persistent across build, in terms 154341825Sdim * of percentage of the available space on the disk. Set to 100 to indicate 155341825Sdim * no limit, 50 to indicate that the cache size will not be left over 156303231Sdim * half the available space. A value over 100 will be reduced to 100, and a 157303231Sdim * value of 0 will be ignored. 158303231Sdim * 159303231Sdim * 160303231Sdim * The formula looks like: 161303231Sdim * AvailableSpace = FreeSpace + ExistingCacheSize 162303231Sdim * NewCacheSize = AvailableSpace * P/100 163303231Sdim * 164303231Sdim */ 165303231Sdim void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) { 166303231Sdim if (Percentage) 167321369Sdim CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage; 168303231Sdim } 169303231Sdim 170341825Sdim /// Cache policy: the maximum size for the cache directory in bytes. A value 171341825Sdim /// over the amount of available space on the disk will be reduced to the 172341825Sdim /// amount of available space. A value of 0 will be ignored. 173344779Sdim void setCacheMaxSizeBytes(uint64_t MaxSizeBytes) { 174341825Sdim if (MaxSizeBytes) 175341825Sdim CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes; 176341825Sdim } 177341825Sdim 178341825Sdim /// Cache policy: the maximum number of files in the cache directory. A value 179341825Sdim /// of 0 will be ignored. 180341825Sdim void setCacheMaxSizeFiles(unsigned MaxSizeFiles) { 181341825Sdim if (MaxSizeFiles) 182341825Sdim CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles; 183341825Sdim } 184341825Sdim 185303231Sdim /**@}*/ 186303231Sdim 187303231Sdim /// Set the path to a directory where to save temporaries at various stages of 188303231Sdim /// the processing. 189303231Sdim void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); } 190303231Sdim 191314564Sdim /// Set the path to a directory where to save generated object files. This 192314564Sdim /// path can be used by a linker to request on-disk files instead of in-memory 193314564Sdim /// buffers. When set, results are available through getProducedBinaryFiles() 194314564Sdim /// instead of getProducedBinaries(). 195314564Sdim void setGeneratedObjectsDirectory(std::string Path) { 196314564Sdim SavedObjectsDirectoryPath = std::move(Path); 197314564Sdim } 198314564Sdim 199303231Sdim /// CPU to use to initialize the TargetMachine 200303231Sdim void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); } 201303231Sdim 202303231Sdim /// Subtarget attributes 203303231Sdim void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); } 204303231Sdim 205303231Sdim /// TargetMachine options 206303231Sdim void setTargetOptions(TargetOptions Options) { 207303231Sdim TMBuilder.Options = std::move(Options); 208303231Sdim } 209303231Sdim 210321369Sdim /// Enable the Freestanding mode: indicate that the optimizer should not 211321369Sdim /// assume builtins are present on the target. 212321369Sdim void setFreestanding(bool Enabled) { Freestanding = Enabled; } 213321369Sdim 214303231Sdim /// CodeModel 215303231Sdim void setCodePICModel(Optional<Reloc::Model> Model) { 216303231Sdim TMBuilder.RelocModel = Model; 217303231Sdim } 218303231Sdim 219303231Sdim /// CodeGen optimization level 220303231Sdim void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) { 221303231Sdim TMBuilder.CGOptLevel = CGOptLevel; 222303231Sdim } 223303231Sdim 224314564Sdim /// IR optimization level: from 0 to 3. 225314564Sdim void setOptLevel(unsigned NewOptLevel) { 226314564Sdim OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel; 227314564Sdim } 228314564Sdim 229303231Sdim /// Disable CodeGen, only run the stages till codegen and stop. The output 230303231Sdim /// will be bitcode. 231303231Sdim void disableCodeGen(bool Disable) { DisableCodeGen = Disable; } 232303231Sdim 233303231Sdim /// Perform CodeGen only: disable all other stages. 234303231Sdim void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; } 235303231Sdim 236303231Sdim /**@}*/ 237303231Sdim 238303231Sdim /** 239303231Sdim * \defgroup Set of APIs to run individual stages in isolation. 240303231Sdim * @{ 241303231Sdim */ 242303231Sdim 243303231Sdim /** 244303231Sdim * Produce the combined summary index from all the bitcode files: 245303231Sdim * "thin-link". 246303231Sdim */ 247303231Sdim std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex(); 248303231Sdim 249303231Sdim /** 250303231Sdim * Perform promotion and renaming of exported internal functions, 251303231Sdim * and additionally resolve weak and linkonce symbols. 252303231Sdim * Index is updated to reflect linkage changes from weak resolution. 253303231Sdim */ 254353358Sdim void promote(Module &Module, ModuleSummaryIndex &Index, 255353358Sdim const lto::InputFile &File); 256303231Sdim 257303231Sdim /** 258303231Sdim * Compute and emit the imported files for module at \p ModulePath. 259303231Sdim */ 260344779Sdim void emitImports(Module &Module, StringRef OutputName, 261353358Sdim ModuleSummaryIndex &Index, 262353358Sdim const lto::InputFile &File); 263303231Sdim 264303231Sdim /** 265303231Sdim * Perform cross-module importing for the module identified by 266303231Sdim * ModuleIdentifier. 267303231Sdim */ 268353358Sdim void crossModuleImport(Module &Module, ModuleSummaryIndex &Index, 269353358Sdim const lto::InputFile &File); 270303231Sdim 271303231Sdim /** 272303231Sdim * Compute the list of summaries needed for importing into module. 273303231Sdim */ 274344779Sdim void gatherImportedSummariesForModule( 275344779Sdim Module &Module, ModuleSummaryIndex &Index, 276353358Sdim std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex, 277353358Sdim const lto::InputFile &File); 278303231Sdim 279303231Sdim /** 280303231Sdim * Perform internalization. Index is updated to reflect linkage changes. 281303231Sdim */ 282353358Sdim void internalize(Module &Module, ModuleSummaryIndex &Index, 283353358Sdim const lto::InputFile &File); 284303231Sdim 285303231Sdim /** 286303231Sdim * Perform post-importing ThinLTO optimizations. 287303231Sdim */ 288303231Sdim void optimize(Module &Module); 289303231Sdim 290353358Sdim /** 291353358Sdim * Write temporary object file to SavedObjectDirectoryPath, write symlink 292353358Sdim * to Cache directory if needed. Returns the path to the generated file in 293353358Sdim * SavedObjectsDirectoryPath. 294353358Sdim */ 295353358Sdim std::string writeGeneratedObject(int count, StringRef CacheEntryPath, 296353358Sdim const MemoryBuffer &OutputBuffer); 297303231Sdim /**@}*/ 298303231Sdim 299303231Sdimprivate: 300303231Sdim /// Helper factory to build a TargetMachine 301303231Sdim TargetMachineBuilder TMBuilder; 302303231Sdim 303314564Sdim /// Vector holding the in-memory buffer containing the produced binaries, when 304314564Sdim /// SavedObjectsDirectoryPath isn't set. 305303231Sdim std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries; 306303231Sdim 307314564Sdim /// Path to generated files in the supplied SavedObjectsDirectoryPath if any. 308314564Sdim std::vector<std::string> ProducedBinaryFiles; 309314564Sdim 310303231Sdim /// Vector holding the input buffers containing the bitcode modules to 311303231Sdim /// process. 312353358Sdim std::vector<std::unique_ptr<lto::InputFile>> Modules; 313303231Sdim 314303231Sdim /// Set of symbols that need to be preserved outside of the set of bitcode 315303231Sdim /// files. 316303231Sdim StringSet<> PreservedSymbols; 317303231Sdim 318303231Sdim /// Set of symbols that are cross-referenced between bitcode files. 319303231Sdim StringSet<> CrossReferencedSymbols; 320303231Sdim 321303231Sdim /// Control the caching behavior. 322303231Sdim CachingOptions CacheOptions; 323303231Sdim 324303231Sdim /// Path to a directory to save the temporary bitcode files. 325303231Sdim std::string SaveTempsDir; 326303231Sdim 327314564Sdim /// Path to a directory to save the generated object files. 328314564Sdim std::string SavedObjectsDirectoryPath; 329314564Sdim 330303231Sdim /// Flag to enable/disable CodeGen. When set to true, the process stops after 331303231Sdim /// optimizations and a bitcode is produced. 332303231Sdim bool DisableCodeGen = false; 333303231Sdim 334303231Sdim /// Flag to indicate that only the CodeGen will be performed, no cross-module 335303231Sdim /// importing or optimization. 336303231Sdim bool CodeGenOnly = false; 337314564Sdim 338321369Sdim /// Flag to indicate that the optimizer should not assume builtins are present 339321369Sdim /// on the target. 340321369Sdim bool Freestanding = false; 341321369Sdim 342314564Sdim /// IR Optimization Level [0-3]. 343314564Sdim unsigned OptLevel = 3; 344303231Sdim}; 345303231Sdim} 346303231Sdim#endif 347