1 //===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the ThinLTOCodeGenerator class, similar to the 10 // LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for 11 // linker plugin. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_LTO_LEGACY_THINLTOCODEGENERATOR_H 16 #define LLVM_LTO_LEGACY_THINLTOCODEGENERATOR_H 17 18 #include "llvm-c/lto.h" 19 #include "llvm/ADT/StringSet.h" 20 #include "llvm/IR/ModuleSummaryIndex.h" 21 #include "llvm/LTO/LTO.h" 22 #include "llvm/Support/CachePruning.h" 23 #include "llvm/Support/CodeGen.h" 24 #include "llvm/Support/Compiler.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Target/TargetOptions.h" 27 #include "llvm/TargetParser/Triple.h" 28 29 #include <string> 30 31 namespace llvm { 32 class StringRef; 33 class TargetMachine; 34 35 /// ThinLTOCodeGeneratorImpl - Namespace used for ThinLTOCodeGenerator 36 /// implementation details. It should be considered private to the 37 /// implementation. 38 namespace ThinLTOCodeGeneratorImpl { 39 struct TargetMachineBuilder; 40 } 41 42 /// Helper to gather options relevant to the target machine creation 43 struct ThinLTOCodeGeneratorImpl::TargetMachineBuilder { 44 Triple TheTriple; 45 std::string MCpu; 46 std::string MAttr; 47 TargetOptions Options; 48 std::optional<Reloc::Model> RelocModel; 49 CodeGenOptLevel CGOptLevel = CodeGenOptLevel::Aggressive; 50 51 LLVM_ABI std::unique_ptr<TargetMachine> create() const; 52 }; 53 54 /// This class define an interface similar to the LTOCodeGenerator, but adapted 55 /// for ThinLTO processing. 56 /// The ThinLTOCodeGenerator is not intended to be reuse for multiple 57 /// compilation: the model is that the client adds modules to the generator and 58 /// ask to perform the ThinLTO optimizations / codegen, and finally destroys the 59 /// codegenerator. 60 class ThinLTOCodeGenerator { 61 public: 62 /// Add given module to the code generator. 63 LLVM_ABI void addModule(StringRef Identifier, StringRef Data); 64 65 /** 66 * Adds to a list of all global symbols that must exist in the final generated 67 * code. If a symbol is not listed there, it will be optimized away if it is 68 * inlined into every usage. 69 */ 70 LLVM_ABI void preserveSymbol(StringRef Name); 71 72 /** 73 * Adds to a list of all global symbols that are cross-referenced between 74 * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every 75 * references from a ThinLTO module to this symbol is optimized away, then 76 * the symbol can be discarded. 77 */ 78 LLVM_ABI void crossReferenceSymbol(StringRef Name); 79 80 /** 81 * Process all the modules that were added to the code generator in parallel. 82 * 83 * Client can access the resulting object files using getProducedBinaries(), 84 * unless setGeneratedObjectsDirectory() has been called, in which case 85 * results are available through getProducedBinaryFiles(). 86 */ 87 LLVM_ABI void run(); 88 89 /** 90 * Return the "in memory" binaries produced by the code generator. This is 91 * filled after run() unless setGeneratedObjectsDirectory() has been 92 * called, in which case results are available through 93 * getProducedBinaryFiles(). 94 */ getProducedBinaries()95 std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() { 96 return ProducedBinaries; 97 } 98 99 /** 100 * Return the "on-disk" binaries produced by the code generator. This is 101 * filled after run() when setGeneratedObjectsDirectory() has been 102 * called, in which case results are available through getProducedBinaries(). 103 */ getProducedBinaryFiles()104 std::vector<std::string> &getProducedBinaryFiles() { 105 return ProducedBinaryFiles; 106 } 107 108 /** 109 * \defgroup Options setters 110 * @{ 111 */ 112 113 /** 114 * \defgroup Cache controlling options 115 * 116 * These entry points control the ThinLTO cache. The cache is intended to 117 * support incremental build, and thus needs to be persistent accross build. 118 * The client enabled the cache by supplying a path to an existing directory. 119 * The code generator will use this to store objects files that may be reused 120 * during a subsequent build. 121 * To avoid filling the disk space, a few knobs are provided: 122 * - The pruning interval limit the frequency at which the garbage collector 123 * will try to scan the cache directory to prune it from expired entries. 124 * Setting to -1 disable the pruning (default). Setting to 0 will force 125 * pruning to occur. 126 * - The pruning expiration time indicates to the garbage collector how old 127 * an entry needs to be to be removed. 128 * - Finally, the garbage collector can be instructed to prune the cache till 129 * the occupied space goes below a threshold. 130 * @{ 131 */ 132 133 struct CachingOptions { 134 std::string Path; // Path to the cache, empty to disable. 135 CachePruningPolicy Policy; 136 }; 137 138 /// Provide a path to a directory where to store the cached files for 139 /// incremental build. setCacheDir(std::string Path)140 void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); } 141 142 /// Cache policy: interval (seconds) between two prunes of the cache. Set to a 143 /// negative value to disable pruning. A value of 0 will force pruning to 144 /// occur. setCachePruningInterval(int Interval)145 void setCachePruningInterval(int Interval) { 146 if(Interval < 0) 147 CacheOptions.Policy.Interval.reset(); 148 else 149 CacheOptions.Policy.Interval = std::chrono::seconds(Interval); 150 } 151 152 /// Cache policy: expiration (in seconds) for an entry. 153 /// A value of 0 will be ignored. setCacheEntryExpiration(unsigned Expiration)154 void setCacheEntryExpiration(unsigned Expiration) { 155 if (Expiration) 156 CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration); 157 } 158 159 /** 160 * Sets the maximum cache size that can be persistent across build, in terms 161 * of percentage of the available space on the disk. Set to 100 to indicate 162 * no limit, 50 to indicate that the cache size will not be left over 163 * half the available space. A value over 100 will be reduced to 100, and a 164 * value of 0 will be ignored. 165 * 166 * 167 * The formula looks like: 168 * AvailableSpace = FreeSpace + ExistingCacheSize 169 * NewCacheSize = AvailableSpace * P/100 170 * 171 */ setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage)172 void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) { 173 if (Percentage) 174 CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage; 175 } 176 177 /// Cache policy: the maximum size for the cache directory in bytes. A value 178 /// over the amount of available space on the disk will be reduced to the 179 /// amount of available space. A value of 0 will be ignored. setCacheMaxSizeBytes(uint64_t MaxSizeBytes)180 void setCacheMaxSizeBytes(uint64_t MaxSizeBytes) { 181 if (MaxSizeBytes) 182 CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes; 183 } 184 185 /// Cache policy: the maximum number of files in the cache directory. A value 186 /// of 0 will be ignored. setCacheMaxSizeFiles(unsigned MaxSizeFiles)187 void setCacheMaxSizeFiles(unsigned MaxSizeFiles) { 188 if (MaxSizeFiles) 189 CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles; 190 } 191 192 /**@}*/ 193 194 /// Set the path to a directory where to save temporaries at various stages of 195 /// the processing. setSaveTempsDir(std::string Path)196 void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); } 197 198 /// Set the path to a directory where to save generated object files. This 199 /// path can be used by a linker to request on-disk files instead of in-memory 200 /// buffers. When set, results are available through getProducedBinaryFiles() 201 /// instead of getProducedBinaries(). setGeneratedObjectsDirectory(std::string Path)202 void setGeneratedObjectsDirectory(std::string Path) { 203 SavedObjectsDirectoryPath = std::move(Path); 204 } 205 206 /// CPU to use to initialize the TargetMachine setCpu(std::string Cpu)207 void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); } 208 209 /// Subtarget attributes setAttr(std::string MAttr)210 void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); } 211 212 /// TargetMachine options setTargetOptions(TargetOptions Options)213 void setTargetOptions(TargetOptions Options) { 214 TMBuilder.Options = std::move(Options); 215 } 216 217 /// Enable the Freestanding mode: indicate that the optimizer should not 218 /// assume builtins are present on the target. setFreestanding(bool Enabled)219 void setFreestanding(bool Enabled) { Freestanding = Enabled; } 220 221 /// CodeModel setCodePICModel(std::optional<Reloc::Model> Model)222 void setCodePICModel(std::optional<Reloc::Model> Model) { 223 TMBuilder.RelocModel = Model; 224 } 225 226 /// CodeGen optimization level setCodeGenOptLevel(CodeGenOptLevel CGOptLevel)227 void setCodeGenOptLevel(CodeGenOptLevel CGOptLevel) { 228 TMBuilder.CGOptLevel = CGOptLevel; 229 } 230 231 /// IR optimization level: from 0 to 3. setOptLevel(unsigned NewOptLevel)232 void setOptLevel(unsigned NewOptLevel) { 233 OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel; 234 } 235 236 /// Enable or disable debug output for the new pass manager. setDebugPassManager(unsigned Enabled)237 void setDebugPassManager(unsigned Enabled) { DebugPassManager = Enabled; } 238 239 /// Disable CodeGen, only run the stages till codegen and stop. The output 240 /// will be bitcode. disableCodeGen(bool Disable)241 void disableCodeGen(bool Disable) { DisableCodeGen = Disable; } 242 243 /// Perform CodeGen only: disable all other stages. setCodeGenOnly(bool CGOnly)244 void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; } 245 246 /**@}*/ 247 248 /** 249 * \defgroup Set of APIs to run individual stages in isolation. 250 * @{ 251 */ 252 253 /** 254 * Produce the combined summary index from all the bitcode files: 255 * "thin-link". 256 */ 257 LLVM_ABI std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex(); 258 259 /** 260 * Perform promotion and renaming of exported internal functions, 261 * and additionally resolve weak and linkonce symbols. 262 * Index is updated to reflect linkage changes from weak resolution. 263 */ 264 LLVM_ABI void promote(Module &Module, ModuleSummaryIndex &Index, 265 const lto::InputFile &File); 266 267 /** 268 * Compute and emit the imported files for module at \p ModulePath. 269 */ 270 LLVM_ABI void emitImports(Module &Module, StringRef OutputName, 271 ModuleSummaryIndex &Index, 272 const lto::InputFile &File); 273 274 /** 275 * Perform cross-module importing for the module identified by 276 * ModuleIdentifier. 277 */ 278 LLVM_ABI void crossModuleImport(Module &Module, ModuleSummaryIndex &Index, 279 const lto::InputFile &File); 280 281 /** 282 * Compute the list of summaries and the subset of declaration summaries 283 * needed for importing into module. 284 */ 285 LLVM_ABI void gatherImportedSummariesForModule( 286 Module &Module, ModuleSummaryIndex &Index, 287 ModuleToSummariesForIndexTy &ModuleToSummariesForIndex, 288 GVSummaryPtrSet &DecSummaries, const lto::InputFile &File); 289 290 /** 291 * Perform internalization. Index is updated to reflect linkage changes. 292 */ 293 LLVM_ABI void internalize(Module &Module, ModuleSummaryIndex &Index, 294 const lto::InputFile &File); 295 296 /** 297 * Perform post-importing ThinLTO optimizations. 298 */ 299 LLVM_ABI void optimize(Module &Module); 300 301 /** 302 * Write temporary object file to SavedObjectDirectoryPath, write symlink 303 * to Cache directory if needed. Returns the path to the generated file in 304 * SavedObjectsDirectoryPath. 305 */ 306 LLVM_ABI std::string writeGeneratedObject(int count, StringRef CacheEntryPath, 307 const MemoryBuffer &OutputBuffer); 308 /**@}*/ 309 310 private: 311 /// Helper factory to build a TargetMachine 312 ThinLTOCodeGeneratorImpl::TargetMachineBuilder TMBuilder; 313 314 /// Vector holding the in-memory buffer containing the produced binaries, when 315 /// SavedObjectsDirectoryPath isn't set. 316 std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries; 317 318 /// Path to generated files in the supplied SavedObjectsDirectoryPath if any. 319 std::vector<std::string> ProducedBinaryFiles; 320 321 /// Vector holding the input buffers containing the bitcode modules to 322 /// process. 323 std::vector<std::unique_ptr<lto::InputFile>> Modules; 324 325 /// Set of symbols that need to be preserved outside of the set of bitcode 326 /// files. 327 StringSet<> PreservedSymbols; 328 329 /// Set of symbols that are cross-referenced between bitcode files. 330 StringSet<> CrossReferencedSymbols; 331 332 /// Control the caching behavior. 333 CachingOptions CacheOptions; 334 335 /// Path to a directory to save the temporary bitcode files. 336 std::string SaveTempsDir; 337 338 /// Path to a directory to save the generated object files. 339 std::string SavedObjectsDirectoryPath; 340 341 /// Flag to enable/disable CodeGen. When set to true, the process stops after 342 /// optimizations and a bitcode is produced. 343 bool DisableCodeGen = false; 344 345 /// Flag to indicate that only the CodeGen will be performed, no cross-module 346 /// importing or optimization. 347 bool CodeGenOnly = false; 348 349 /// Flag to indicate that the optimizer should not assume builtins are present 350 /// on the target. 351 bool Freestanding = false; 352 353 /// IR Optimization Level [0-3]. 354 unsigned OptLevel = 3; 355 356 /// Flag to indicate whether debug output should be enabled for the new pass 357 /// manager. 358 bool DebugPassManager = false; 359 }; 360 } 361 #endif 362