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