clang  6.0.0
PrecompiledPreamble.h
Go to the documentation of this file.
1 //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
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 // Helper class to build precompiled preamble.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
16 
17 #include "clang/Lex/Lexer.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "llvm/ADT/IntrusiveRefCntPtr.h"
20 #include "llvm/Support/AlignOf.h"
21 #include "llvm/Support/MD5.h"
22 #include <cstddef>
23 #include <memory>
24 #include <system_error>
25 #include <type_traits>
26 
27 namespace llvm {
28 class MemoryBuffer;
29 }
30 
31 namespace clang {
32 namespace vfs {
33 class FileSystem;
34 }
35 
36 class CompilerInstance;
37 class CompilerInvocation;
38 class DeclGroupRef;
39 class PCHContainerOperations;
40 
41 /// \brief Runs lexer to compute suggested preamble bounds.
42 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
43  llvm::MemoryBuffer *Buffer,
44  unsigned MaxLines);
45 
46 class PreambleCallbacks;
47 
48 /// A class holding a PCH and all information to check whether it is valid to
49 /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
50 /// CanReusePreamble + AddImplicitPreamble to make use of it.
52  class PCHStorage;
53  struct PreambleFileHash;
54 
55 public:
56  /// \brief Try to build PrecompiledPreamble for \p Invocation. See
57  /// BuildPreambleError for possible error codes.
58  ///
59  /// \param Invocation Original CompilerInvocation with options to compile the
60  /// file.
61  ///
62  /// \param MainFileBuffer Buffer with the contents of the main file.
63  ///
64  /// \param Bounds Bounds of the preamble, result of calling
65  /// ComputePreambleBounds.
66  ///
67  /// \param Diagnostics Diagnostics engine to be used while building the
68  /// preamble.
69  ///
70  /// \param VFS An instance of vfs::FileSystem to be used for file
71  /// accesses.
72  ///
73  /// \param PCHContainerOps An instance of PCHContainerOperations.
74  ///
75  /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
76  /// a temporary file.
77  ///
78  /// \param Callbacks A set of callbacks to be executed when building
79  /// the preamble.
80  static llvm::ErrorOr<PrecompiledPreamble>
81  Build(const CompilerInvocation &Invocation,
82  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
84  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
85  bool StoreInMemory, PreambleCallbacks &Callbacks);
86 
88  PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
89 
90  /// PreambleBounds used to build the preamble.
91  PreambleBounds getBounds() const;
92 
93  /// Returns the size, in bytes, that preamble takes on disk or in memory.
94  /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
95  /// be used for logging and debugging purposes only.
96  std::size_t getSize() const;
97 
98  /// Check whether PrecompiledPreamble can be reused for the new contents(\p
99  /// MainFileBuffer) of the main file.
100  bool CanReuse(const CompilerInvocation &Invocation,
101  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
102  vfs::FileSystem *VFS) const;
103 
104  /// Changes options inside \p CI to use PCH from this preamble. Also remaps
105  /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
106  /// is accessible.
107  /// For in-memory preambles, PrecompiledPreamble instance continues to own
108  /// the MemoryBuffer with the Preamble after this method returns. The caller
109  /// is reponsible for making sure the PrecompiledPreamble instance outlives
110  /// the compiler run and the AST that will be using the PCH.
111  void AddImplicitPreamble(CompilerInvocation &CI,
113  llvm::MemoryBuffer *MainFileBuffer) const;
114 
115 private:
116  PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
117  bool PreambleEndsAtStartOfLine,
118  llvm::StringMap<PreambleFileHash> FilesInPreamble);
119 
120  /// A temp file that would be deleted on destructor call. If destructor is not
121  /// called for any reason, the file will be deleted at static objects'
122  /// destruction.
123  /// An assertion will fire if two TempPCHFiles are created with the same name,
124  /// so it's not intended to be used outside preamble-handling.
125  class TempPCHFile {
126  public:
127  // A main method used to construct TempPCHFile.
128  static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
129 
130  /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
131  static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
132  StringRef Suffix);
133  /// Create a new instance of TemporaryFile for file at \p Path. Use with
134  /// extreme caution, there's an assertion checking that there's only a
135  /// single instance of TempPCHFile alive for each path.
136  static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path);
137 
138  private:
139  TempPCHFile(std::string FilePath);
140 
141  public:
142  TempPCHFile(TempPCHFile &&Other);
143  TempPCHFile &operator=(TempPCHFile &&Other);
144 
145  TempPCHFile(const TempPCHFile &) = delete;
146  ~TempPCHFile();
147 
148  /// A path where temporary file is stored.
149  llvm::StringRef getFilePath() const;
150 
151  private:
152  void RemoveFileIfPresent();
153 
154  private:
156  };
157 
158  class InMemoryPreamble {
159  public:
160  std::string Data;
161  };
162 
163  class PCHStorage {
164  public:
165  enum class Kind { Empty, InMemory, TempFile };
166 
167  PCHStorage() = default;
168  PCHStorage(TempPCHFile File);
169  PCHStorage(InMemoryPreamble Memory);
170 
171  PCHStorage(const PCHStorage &) = delete;
172  PCHStorage &operator=(const PCHStorage &) = delete;
173 
174  PCHStorage(PCHStorage &&Other);
175  PCHStorage &operator=(PCHStorage &&Other);
176 
177  ~PCHStorage();
178 
179  Kind getKind() const;
180 
181  TempPCHFile &asFile();
182  const TempPCHFile &asFile() const;
183 
184  InMemoryPreamble &asMemory();
185  const InMemoryPreamble &asMemory() const;
186 
187  private:
188  void destroy();
189  void setEmpty();
190 
191  private:
192  Kind StorageKind = Kind::Empty;
193  llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
194  };
195 
196  /// Data used to determine if a file used in the preamble has been changed.
197  struct PreambleFileHash {
198  /// All files have size set.
199  off_t Size = 0;
200 
201  /// Modification time is set for files that are on disk. For memory
202  /// buffers it is zero.
203  time_t ModTime = 0;
204 
205  /// Memory buffers have MD5 instead of modification time. We don't
206  /// compute MD5 for on-disk files because we hope that modification time is
207  /// enough to tell if the file was changed.
208  llvm::MD5::MD5Result MD5 = {};
209 
210  static PreambleFileHash createForFile(off_t Size, time_t ModTime);
211  static PreambleFileHash
212  createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
213 
214  friend bool operator==(const PreambleFileHash &LHS,
215  const PreambleFileHash &RHS) {
216  return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
217  LHS.MD5 == RHS.MD5;
218  }
219  friend bool operator!=(const PreambleFileHash &LHS,
220  const PreambleFileHash &RHS) {
221  return !(LHS == RHS);
222  }
223  };
224 
225  /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
226  /// Storage is accessible to clang. This method is an implementation detail of
227  /// AddImplicitPreamble.
228  static void setupPreambleStorage(const PCHStorage &Storage,
229  PreprocessorOptions &PreprocessorOpts,
231 
232  /// Manages the memory buffer or temporary file that stores the PCH.
233  PCHStorage Storage;
234  /// Keeps track of the files that were used when computing the
235  /// preamble, with both their buffer size and their modification time.
236  ///
237  /// If any of the files have changed from one compile to the next,
238  /// the preamble must be thrown away.
239  llvm::StringMap<PreambleFileHash> FilesInPreamble;
240  /// The contents of the file that was used to precompile the preamble. Only
241  /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
242  /// part of the file has not changed, so that preamble can be reused.
243  std::vector<char> PreambleBytes;
244  /// See PreambleBounds::PreambleEndsAtStartOfLine
245  bool PreambleEndsAtStartOfLine;
246 };
247 
248 /// A set of callbacks to gather useful information while building a preamble.
250 public:
251  virtual ~PreambleCallbacks() = default;
252 
253  /// Called before FrontendAction::BeginSourceFile.
254  /// Can be used to store references to various CompilerInstance fields
255  /// (e.g. SourceManager) that may be interesting to the consumers of other
256  /// callbacks.
257  virtual void BeforeExecute(CompilerInstance &CI);
258  /// Called after FrontendAction::Execute(), but before
259  /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
260  /// various CompilerInstance fields before they are destroyed.
261  virtual void AfterExecute(CompilerInstance &CI);
262  /// Called after PCH has been emitted. \p Writer may be used to retrieve
263  /// information about AST, serialized in PCH.
264  virtual void AfterPCHEmitted(ASTWriter &Writer);
265  /// Called for each TopLevelDecl.
266  /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
267  /// used instead, but having only this method allows a simpler API.
268  virtual void HandleTopLevelDecl(DeclGroupRef DG);
269  /// Creates wrapper class for PPCallbacks so we can also process information
270  /// about includes that are inside of a preamble
271  virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
272 };
273 
274 enum class BuildPreambleError {
275  PreambleIsEmpty = 1,
281 };
282 
283 class BuildPreambleErrorCategory final : public std::error_category {
284 public:
285  const char *name() const noexcept override;
286  std::string message(int condition) const override;
287 };
288 
289 std::error_code make_error_code(BuildPreambleError Error);
290 } // namespace clang
291 
292 namespace std {
293 template <>
294 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
295 } // namespace std
296 
297 #endif
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition: Lexer.h:59
bool operator==(CanQual< T > x, CanQual< U > y)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Definition: opencl-c.h:60
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:26
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
The virtual file system interface.
Definition: Format.h:1900
std::error_code make_error_code(BuildPreambleError Error)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
A set of callbacks to gather useful information while building a preamble.
Defines the clang::Preprocessor interface.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
Kind
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Dataflow Directional Tag Classes.
A class holding a PCH and all information to check whether it is valid to reuse the PCH for the subse...
Helper class for holding the data necessary to invoke the compiler.
bool operator!=(CanQual< T > x, CanQual< U > y)
Writes an AST file containing the contents of a translation unit.
Definition: ASTWriter.h:104
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:930