1303231Sdim//===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===//
2303231Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303231Sdim//
7303231Sdim//===----------------------------------------------------------------------===//
8303231Sdim//
9303231Sdim// This file declares the ThinLTOCodeGenerator class, similar to the
10303231Sdim// LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for
11303231Sdim// linker plugin.
12303231Sdim//
13303231Sdim//===----------------------------------------------------------------------===//
14303231Sdim
15303231Sdim#ifndef LLVM_LTO_THINLTOCODEGENERATOR_H
16303231Sdim#define LLVM_LTO_THINLTOCODEGENERATOR_H
17303231Sdim
18303231Sdim#include "llvm-c/lto.h"
19303231Sdim#include "llvm/ADT/StringSet.h"
20303231Sdim#include "llvm/ADT/Triple.h"
21303231Sdim#include "llvm/IR/ModuleSummaryIndex.h"
22353358Sdim#include "llvm/LTO/LTO.h"
23321369Sdim#include "llvm/Support/CachePruning.h"
24303231Sdim#include "llvm/Support/CodeGen.h"
25303231Sdim#include "llvm/Support/MemoryBuffer.h"
26303231Sdim#include "llvm/Target/TargetOptions.h"
27303231Sdim
28303231Sdim#include <string>
29303231Sdim
30303231Sdimnamespace llvm {
31303231Sdimclass StringRef;
32303231Sdimclass LLVMContext;
33303231Sdimclass TargetMachine;
34303231Sdim
35303231Sdim/// Helper to gather options relevant to the target machine creation
36303231Sdimstruct TargetMachineBuilder {
37303231Sdim  Triple TheTriple;
38303231Sdim  std::string MCpu;
39303231Sdim  std::string MAttr;
40303231Sdim  TargetOptions Options;
41303231Sdim  Optional<Reloc::Model> RelocModel;
42314564Sdim  CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive;
43303231Sdim
44303231Sdim  std::unique_ptr<TargetMachine> create() const;
45303231Sdim};
46303231Sdim
47303231Sdim/// This class define an interface similar to the LTOCodeGenerator, but adapted
48303231Sdim/// for ThinLTO processing.
49303231Sdim/// The ThinLTOCodeGenerator is not intended to be reuse for multiple
50303231Sdim/// compilation: the model is that the client adds modules to the generator and
51303231Sdim/// ask to perform the ThinLTO optimizations / codegen, and finally destroys the
52303231Sdim/// codegenerator.
53303231Sdimclass ThinLTOCodeGenerator {
54303231Sdimpublic:
55303231Sdim  /// Add given module to the code generator.
56303231Sdim  void addModule(StringRef Identifier, StringRef Data);
57303231Sdim
58303231Sdim  /**
59303231Sdim   * Adds to a list of all global symbols that must exist in the final generated
60303231Sdim   * code. If a symbol is not listed there, it will be optimized away if it is
61303231Sdim   * inlined into every usage.
62303231Sdim   */
63303231Sdim  void preserveSymbol(StringRef Name);
64303231Sdim
65303231Sdim  /**
66303231Sdim   * Adds to a list of all global symbols that are cross-referenced between
67303231Sdim   * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
68303231Sdim   * references from a ThinLTO module to this symbol is optimized away, then
69303231Sdim   * the symbol can be discarded.
70303231Sdim   */
71303231Sdim  void crossReferenceSymbol(StringRef Name);
72303231Sdim
73303231Sdim  /**
74303231Sdim   * Process all the modules that were added to the code generator in parallel.
75303231Sdim   *
76314564Sdim   * Client can access the resulting object files using getProducedBinaries(),
77314564Sdim   * unless setGeneratedObjectsDirectory() has been called, in which case
78314564Sdim   * results are available through getProducedBinaryFiles().
79303231Sdim   */
80303231Sdim  void run();
81303231Sdim
82303231Sdim  /**
83314564Sdim   * Return the "in memory" binaries produced by the code generator. This is
84314564Sdim   * filled after run() unless setGeneratedObjectsDirectory() has been
85314564Sdim   * called, in which case results are available through
86314564Sdim   * getProducedBinaryFiles().
87303231Sdim   */
88303231Sdim  std::vector<std::unique_ptr<MemoryBuffer>> &getProducedBinaries() {
89303231Sdim    return ProducedBinaries;
90303231Sdim  }
91303231Sdim
92303231Sdim  /**
93314564Sdim   * Return the "on-disk" binaries produced by the code generator. This is
94314564Sdim   * filled after run() when setGeneratedObjectsDirectory() has been
95314564Sdim   * called, in which case results are available through getProducedBinaries().
96314564Sdim   */
97314564Sdim  std::vector<std::string> &getProducedBinaryFiles() {
98314564Sdim    return ProducedBinaryFiles;
99314564Sdim  }
100314564Sdim
101314564Sdim  /**
102303231Sdim   * \defgroup Options setters
103303231Sdim   * @{
104303231Sdim   */
105303231Sdim
106303231Sdim  /**
107303231Sdim   * \defgroup Cache controlling options
108303231Sdim   *
109303231Sdim   * These entry points control the ThinLTO cache. The cache is intended to
110303231Sdim   * support incremental build, and thus needs to be persistent accross build.
111303231Sdim   * The client enabled the cache by supplying a path to an existing directory.
112303231Sdim   * The code generator will use this to store objects files that may be reused
113303231Sdim   * during a subsequent build.
114303231Sdim   * To avoid filling the disk space, a few knobs are provided:
115303231Sdim   *  - The pruning interval limit the frequency at which the garbage collector
116303231Sdim   *    will try to scan the cache directory to prune it from expired entries.
117341825Sdim   *    Setting to -1 disable the pruning (default). Setting to 0 will force
118341825Sdim   *    pruning to occur.
119303231Sdim   *  - The pruning expiration time indicates to the garbage collector how old
120303231Sdim   *    an entry needs to be to be removed.
121303231Sdim   *  - Finally, the garbage collector can be instructed to prune the cache till
122303231Sdim   *    the occupied space goes below a threshold.
123303231Sdim   * @{
124303231Sdim   */
125303231Sdim
126303231Sdim  struct CachingOptions {
127303231Sdim    std::string Path;                    // Path to the cache, empty to disable.
128321369Sdim    CachePruningPolicy Policy;
129303231Sdim  };
130303231Sdim
131303231Sdim  /// Provide a path to a directory where to store the cached files for
132303231Sdim  /// incremental build.
133303231Sdim  void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
134303231Sdim
135327952Sdim  /// Cache policy: interval (seconds) between two prunes of the cache. Set to a
136341825Sdim  /// negative value to disable pruning. A value of 0 will force pruning to
137341825Sdim  /// occur.
138303231Sdim  void setCachePruningInterval(int Interval) {
139327952Sdim    if(Interval < 0)
140327952Sdim      CacheOptions.Policy.Interval.reset();
141327952Sdim    else
142321369Sdim      CacheOptions.Policy.Interval = std::chrono::seconds(Interval);
143303231Sdim  }
144303231Sdim
145303231Sdim  /// Cache policy: expiration (in seconds) for an entry.
146303231Sdim  /// A value of 0 will be ignored.
147303231Sdim  void setCacheEntryExpiration(unsigned Expiration) {
148303231Sdim    if (Expiration)
149321369Sdim      CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration);
150303231Sdim  }
151303231Sdim
152303231Sdim  /**
153303231Sdim   * Sets the maximum cache size that can be persistent across build, in terms
154341825Sdim   * of percentage of the available space on the disk. Set to 100 to indicate
155341825Sdim   * no limit, 50 to indicate that the cache size will not be left over
156303231Sdim   * half the available space. A value over 100 will be reduced to 100, and a
157303231Sdim   * value of 0 will be ignored.
158303231Sdim   *
159303231Sdim   *
160303231Sdim   * The formula looks like:
161303231Sdim   *  AvailableSpace = FreeSpace + ExistingCacheSize
162303231Sdim   *  NewCacheSize = AvailableSpace * P/100
163303231Sdim   *
164303231Sdim   */
165303231Sdim  void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
166303231Sdim    if (Percentage)
167321369Sdim      CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage;
168303231Sdim  }
169303231Sdim
170341825Sdim  /// Cache policy: the maximum size for the cache directory in bytes. A value
171341825Sdim  /// over the amount of available space on the disk will be reduced to the
172341825Sdim  /// amount of available space. A value of 0 will be ignored.
173344779Sdim  void setCacheMaxSizeBytes(uint64_t MaxSizeBytes) {
174341825Sdim    if (MaxSizeBytes)
175341825Sdim      CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes;
176341825Sdim  }
177341825Sdim
178341825Sdim  /// Cache policy: the maximum number of files in the cache directory. A value
179341825Sdim  /// of 0 will be ignored.
180341825Sdim  void setCacheMaxSizeFiles(unsigned MaxSizeFiles) {
181341825Sdim    if (MaxSizeFiles)
182341825Sdim      CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles;
183341825Sdim  }
184341825Sdim
185303231Sdim  /**@}*/
186303231Sdim
187303231Sdim  /// Set the path to a directory where to save temporaries at various stages of
188303231Sdim  /// the processing.
189303231Sdim  void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); }
190303231Sdim
191314564Sdim  /// Set the path to a directory where to save generated object files. This
192314564Sdim  /// path can be used by a linker to request on-disk files instead of in-memory
193314564Sdim  /// buffers. When set, results are available through getProducedBinaryFiles()
194314564Sdim  /// instead of getProducedBinaries().
195314564Sdim  void setGeneratedObjectsDirectory(std::string Path) {
196314564Sdim    SavedObjectsDirectoryPath = std::move(Path);
197314564Sdim  }
198314564Sdim
199303231Sdim  /// CPU to use to initialize the TargetMachine
200303231Sdim  void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); }
201303231Sdim
202303231Sdim  /// Subtarget attributes
203303231Sdim  void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); }
204303231Sdim
205303231Sdim  /// TargetMachine options
206303231Sdim  void setTargetOptions(TargetOptions Options) {
207303231Sdim    TMBuilder.Options = std::move(Options);
208303231Sdim  }
209303231Sdim
210321369Sdim  /// Enable the Freestanding mode: indicate that the optimizer should not
211321369Sdim  /// assume builtins are present on the target.
212321369Sdim  void setFreestanding(bool Enabled) { Freestanding = Enabled; }
213321369Sdim
214303231Sdim  /// CodeModel
215303231Sdim  void setCodePICModel(Optional<Reloc::Model> Model) {
216303231Sdim    TMBuilder.RelocModel = Model;
217303231Sdim  }
218303231Sdim
219303231Sdim  /// CodeGen optimization level
220303231Sdim  void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
221303231Sdim    TMBuilder.CGOptLevel = CGOptLevel;
222303231Sdim  }
223303231Sdim
224314564Sdim  /// IR optimization level: from 0 to 3.
225314564Sdim  void setOptLevel(unsigned NewOptLevel) {
226314564Sdim    OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel;
227314564Sdim  }
228314564Sdim
229303231Sdim  /// Disable CodeGen, only run the stages till codegen and stop. The output
230303231Sdim  /// will be bitcode.
231303231Sdim  void disableCodeGen(bool Disable) { DisableCodeGen = Disable; }
232303231Sdim
233303231Sdim  /// Perform CodeGen only: disable all other stages.
234303231Sdim  void setCodeGenOnly(bool CGOnly) { CodeGenOnly = CGOnly; }
235303231Sdim
236303231Sdim  /**@}*/
237303231Sdim
238303231Sdim  /**
239303231Sdim   * \defgroup Set of APIs to run individual stages in isolation.
240303231Sdim   * @{
241303231Sdim   */
242303231Sdim
243303231Sdim  /**
244303231Sdim   * Produce the combined summary index from all the bitcode files:
245303231Sdim   * "thin-link".
246303231Sdim   */
247303231Sdim  std::unique_ptr<ModuleSummaryIndex> linkCombinedIndex();
248303231Sdim
249303231Sdim  /**
250303231Sdim   * Perform promotion and renaming of exported internal functions,
251303231Sdim   * and additionally resolve weak and linkonce symbols.
252303231Sdim   * Index is updated to reflect linkage changes from weak resolution.
253303231Sdim   */
254353358Sdim  void promote(Module &Module, ModuleSummaryIndex &Index,
255353358Sdim               const lto::InputFile &File);
256303231Sdim
257303231Sdim  /**
258303231Sdim   * Compute and emit the imported files for module at \p ModulePath.
259303231Sdim   */
260344779Sdim  void emitImports(Module &Module, StringRef OutputName,
261353358Sdim                   ModuleSummaryIndex &Index,
262353358Sdim                   const lto::InputFile &File);
263303231Sdim
264303231Sdim  /**
265303231Sdim   * Perform cross-module importing for the module identified by
266303231Sdim   * ModuleIdentifier.
267303231Sdim   */
268353358Sdim  void crossModuleImport(Module &Module, ModuleSummaryIndex &Index,
269353358Sdim                         const lto::InputFile &File);
270303231Sdim
271303231Sdim  /**
272303231Sdim   * Compute the list of summaries needed for importing into module.
273303231Sdim   */
274344779Sdim  void gatherImportedSummariesForModule(
275344779Sdim      Module &Module, ModuleSummaryIndex &Index,
276353358Sdim      std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
277353358Sdim      const lto::InputFile &File);
278303231Sdim
279303231Sdim  /**
280303231Sdim   * Perform internalization. Index is updated to reflect linkage changes.
281303231Sdim   */
282353358Sdim  void internalize(Module &Module, ModuleSummaryIndex &Index,
283353358Sdim                   const lto::InputFile &File);
284303231Sdim
285303231Sdim  /**
286303231Sdim   * Perform post-importing ThinLTO optimizations.
287303231Sdim   */
288303231Sdim  void optimize(Module &Module);
289303231Sdim
290353358Sdim  /**
291353358Sdim   * Write temporary object file to SavedObjectDirectoryPath, write symlink
292353358Sdim   * to Cache directory if needed. Returns the path to the generated file in
293353358Sdim   * SavedObjectsDirectoryPath.
294353358Sdim   */
295353358Sdim  std::string writeGeneratedObject(int count, StringRef CacheEntryPath,
296353358Sdim                                   const MemoryBuffer &OutputBuffer);
297303231Sdim  /**@}*/
298303231Sdim
299303231Sdimprivate:
300303231Sdim  /// Helper factory to build a TargetMachine
301303231Sdim  TargetMachineBuilder TMBuilder;
302303231Sdim
303314564Sdim  /// Vector holding the in-memory buffer containing the produced binaries, when
304314564Sdim  /// SavedObjectsDirectoryPath isn't set.
305303231Sdim  std::vector<std::unique_ptr<MemoryBuffer>> ProducedBinaries;
306303231Sdim
307314564Sdim  /// Path to generated files in the supplied SavedObjectsDirectoryPath if any.
308314564Sdim  std::vector<std::string> ProducedBinaryFiles;
309314564Sdim
310303231Sdim  /// Vector holding the input buffers containing the bitcode modules to
311303231Sdim  /// process.
312353358Sdim  std::vector<std::unique_ptr<lto::InputFile>> Modules;
313303231Sdim
314303231Sdim  /// Set of symbols that need to be preserved outside of the set of bitcode
315303231Sdim  /// files.
316303231Sdim  StringSet<> PreservedSymbols;
317303231Sdim
318303231Sdim  /// Set of symbols that are cross-referenced between bitcode files.
319303231Sdim  StringSet<> CrossReferencedSymbols;
320303231Sdim
321303231Sdim  /// Control the caching behavior.
322303231Sdim  CachingOptions CacheOptions;
323303231Sdim
324303231Sdim  /// Path to a directory to save the temporary bitcode files.
325303231Sdim  std::string SaveTempsDir;
326303231Sdim
327314564Sdim  /// Path to a directory to save the generated object files.
328314564Sdim  std::string SavedObjectsDirectoryPath;
329314564Sdim
330303231Sdim  /// Flag to enable/disable CodeGen. When set to true, the process stops after
331303231Sdim  /// optimizations and a bitcode is produced.
332303231Sdim  bool DisableCodeGen = false;
333303231Sdim
334303231Sdim  /// Flag to indicate that only the CodeGen will be performed, no cross-module
335303231Sdim  /// importing or optimization.
336303231Sdim  bool CodeGenOnly = false;
337314564Sdim
338321369Sdim  /// Flag to indicate that the optimizer should not assume builtins are present
339321369Sdim  /// on the target.
340321369Sdim  bool Freestanding = false;
341321369Sdim
342314564Sdim  /// IR Optimization Level [0-3].
343314564Sdim  unsigned OptLevel = 3;
344303231Sdim};
345303231Sdim}
346303231Sdim#endif
347