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