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