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