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_THINLTOCODEGENERATOR_H
16#define LLVM_LTO_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
30namespace llvm {
31class StringRef;
32class LLVMContext;
33class TargetMachine;
34
35/// Helper to gather options relevant to the target machine creation
36struct 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.
53class ThinLTOCodeGenerator {
54public:
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  /// Disable CodeGen, only run the stages till codegen and stop. The output
230  /// will be bitcode.
231  void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
232
233  /// Perform CodeGen only: disable all other stages.
234  void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
235
236  /**@}*/
237
238  /**
239   * \defgroup Set of APIs to run individual stages in isolation.
240   * @{
241   */
242
243  /**
244   * Produce the combined summary index from all the bitcode files:
245   * "thin-link".
246   */
247  std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
248
249  /**
250   * Perform promotion and renaming of exported internal functions,
251   * and additionally resolve weak and linkonce symbols.
252   * Index is updated to reflect linkage changes from weak resolution.
253   */
254  void promote(Module &Module, ModuleSummaryIndex &Index,
255               const lto::InputFile &File);
256
257  /**
258   * Compute and emit the imported files for module at \p ModulePath.
259   */
260  void emitImports(Module &Module, StringRef OutputName,
261                   ModuleSummaryIndex &Index,
262                   const lto::InputFile &File);
263
264  /**
265   * Perform cross-module importing for the module identified by
266   * ModuleIdentifier.
267   */
268  void crossModuleImport(Module &Module, ModuleSummaryIndex &Index,
269                         const lto::InputFile &File);
270
271  /**
272   * Compute the list of summaries needed for importing into module.
273   */
274  void gatherImportedSummariesForModule(
275      Module &Module, ModuleSummaryIndex &Index,
276      std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
277      const lto::InputFile &File);
278
279  /**
280   * Perform internalization. Index is updated to reflect linkage changes.
281   */
282  void internalize(Module &Module, ModuleSummaryIndex &Index,
283                   const lto::InputFile &File);
284
285  /**
286   * Perform post-importing ThinLTO optimizations.
287   */
288  void optimize(Module &Module);
289
290  /**
291   * Write temporary object file to SavedObjectDirectoryPath, write symlink
292   * to Cache directory if needed. Returns the path to the generated file in
293   * SavedObjectsDirectoryPath.
294   */
295  std::string writeGeneratedObject(int count, StringRef CacheEntryPath,
296                                   const MemoryBuffer &OutputBuffer);
297  /**@}*/
298
299private:
300  /// Helper factory to build a TargetMachine
301  TargetMachineBuilder TMBuilder;
302
303  /// Vector holding the in-memory buffer containing the produced binaries, when
304  /// SavedObjectsDirectoryPath isn't set.
305  std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
306
307  /// Path to generated files in the supplied SavedObjectsDirectoryPath if any.
308  std::vector<std::string> ProducedBinaryFiles;
309
310  /// Vector holding the input buffers containing the bitcode modules to
311  /// process.
312  std::vector<std::unique_ptr<lto::InputFile>> Modules;
313
314  /// Set of symbols that need to be preserved outside of the set of bitcode
315  /// files.
316  StringSet<> PreservedSymbols;
317
318  /// Set of symbols that are cross-referenced between bitcode files.
319  StringSet<> CrossReferencedSymbols;
320
321  /// Control the caching behavior.
322  CachingOptions CacheOptions;
323
324  /// Path to a directory to save the temporary bitcode files.
325  std::string SaveTempsDir;
326
327  /// Path to a directory to save the generated object files.
328  std::string SavedObjectsDirectoryPath;
329
330  /// Flag to enable/disable CodeGen. When set to true, the process stops after
331  /// optimizations and a bitcode is produced.
332  bool DisableCodeGen = false;
333
334  /// Flag to indicate that only the CodeGen will be performed, no cross-module
335  /// importing or optimization.
336  bool CodeGenOnly = false;
337
338  /// Flag to indicate that the optimizer should not assume builtins are present
339  /// on the target.
340  bool Freestanding = false;
341
342  /// IR Optimization Level [0-3].
343  unsigned OptLevel = 3;
344};
345}
346#endif
347