1 //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Helper class to build precompiled preamble.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
14 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
16 #include "clang/Lex/Lexer.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/AlignOf.h"
21 #include "llvm/Support/MD5.h"
24 #include <system_error>
25 #include <type_traits>
35 class CompilerInstance;
36 class CompilerInvocation;
39 class PCHContainerOperations;
41 /// Runs lexer to compute suggested preamble bounds.
42 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
43 const llvm::MemoryBuffer *Buffer,
46 class PreambleCallbacks;
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.
51 class PrecompiledPreamble {
53 struct PreambleFileHash;
56 /// Try to build PrecompiledPreamble for \p Invocation. See
57 /// BuildPreambleError for possible error codes.
59 /// \param Invocation Original CompilerInvocation with options to compile the
62 /// \param MainFileBuffer Buffer with the contents of the main file.
64 /// \param Bounds Bounds of the preamble, result of calling
65 /// ComputePreambleBounds.
67 /// \param Diagnostics Diagnostics engine to be used while building the
70 /// \param VFS An instance of vfs::FileSystem to be used for file
73 /// \param PCHContainerOps An instance of PCHContainerOperations.
75 /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
78 /// \param Callbacks A set of callbacks to be executed when building
80 static llvm::ErrorOr<PrecompiledPreamble>
81 Build(const CompilerInvocation &Invocation,
82 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
83 DiagnosticsEngine &Diagnostics,
84 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
85 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
86 bool StoreInMemory, PreambleCallbacks &Callbacks);
88 PrecompiledPreamble(PrecompiledPreamble &&) = default;
89 PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
91 /// PreambleBounds used to build the preamble.
92 PreambleBounds getBounds() const;
94 /// Returns the size, in bytes, that preamble takes on disk or in memory.
95 /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
96 /// be used for logging and debugging purposes only.
97 std::size_t getSize() const;
99 /// Returned string is not null-terminated.
100 llvm::StringRef getContents() const {
101 return {PreambleBytes.data(), PreambleBytes.size()};
104 /// Check whether PrecompiledPreamble can be reused for the new contents(\p
105 /// MainFileBuffer) of the main file.
106 bool CanReuse(const CompilerInvocation &Invocation,
107 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
108 llvm::vfs::FileSystem *VFS) const;
110 /// Changes options inside \p CI to use PCH from this preamble. Also remaps
111 /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
113 /// Requires that CanReuse() is true.
114 /// For in-memory preambles, PrecompiledPreamble instance continues to own the
115 /// MemoryBuffer with the Preamble after this method returns. The caller is
116 /// responsible for making sure the PrecompiledPreamble instance outlives the
117 /// compiler run and the AST that will be using the PCH.
118 void AddImplicitPreamble(CompilerInvocation &CI,
119 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
120 llvm::MemoryBuffer *MainFileBuffer) const;
122 /// Configure \p CI to use this preamble.
123 /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
124 /// If this preamble does not match the file, it may parse differently.
125 void OverridePreamble(CompilerInvocation &CI,
126 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
127 llvm::MemoryBuffer *MainFileBuffer) const;
130 PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
131 bool PreambleEndsAtStartOfLine,
132 llvm::StringMap<PreambleFileHash> FilesInPreamble,
133 llvm::StringSet<> MissingFiles);
135 /// A temp file that would be deleted on destructor call. If destructor is not
136 /// called for any reason, the file will be deleted at static objects'
138 /// An assertion will fire if two TempPCHFiles are created with the same name,
139 /// so it's not intended to be used outside preamble-handling.
142 // A main method used to construct TempPCHFile.
143 static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
146 TempPCHFile(std::string FilePath);
149 TempPCHFile(TempPCHFile &&Other);
150 TempPCHFile &operator=(TempPCHFile &&Other);
152 TempPCHFile(const TempPCHFile &) = delete;
155 /// A path where temporary file is stored.
156 llvm::StringRef getFilePath() const;
159 void RemoveFileIfPresent();
162 llvm::Optional<std::string> FilePath;
165 class InMemoryPreamble {
172 enum class Kind { Empty, InMemory, TempFile };
174 PCHStorage() = default;
175 PCHStorage(TempPCHFile File);
176 PCHStorage(InMemoryPreamble Memory);
178 PCHStorage(const PCHStorage &) = delete;
179 PCHStorage &operator=(const PCHStorage &) = delete;
181 PCHStorage(PCHStorage &&Other);
182 PCHStorage &operator=(PCHStorage &&Other);
186 Kind getKind() const;
188 TempPCHFile &asFile();
189 const TempPCHFile &asFile() const;
191 InMemoryPreamble &asMemory();
192 const InMemoryPreamble &asMemory() const;
199 Kind StorageKind = Kind::Empty;
200 llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
203 /// Data used to determine if a file used in the preamble has been changed.
204 struct PreambleFileHash {
205 /// All files have size set.
208 /// Modification time is set for files that are on disk. For memory
209 /// buffers it is zero.
212 /// Memory buffers have MD5 instead of modification time. We don't
213 /// compute MD5 for on-disk files because we hope that modification time is
214 /// enough to tell if the file was changed.
215 llvm::MD5::MD5Result MD5 = {};
217 static PreambleFileHash createForFile(off_t Size, time_t ModTime);
218 static PreambleFileHash
219 createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
221 friend bool operator==(const PreambleFileHash &LHS,
222 const PreambleFileHash &RHS) {
223 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
226 friend bool operator!=(const PreambleFileHash &LHS,
227 const PreambleFileHash &RHS) {
228 return !(LHS == RHS);
232 /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
233 /// with the specified \p Bounds.
234 void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
235 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
236 llvm::MemoryBuffer *MainFileBuffer) const;
238 /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
239 /// Storage is accessible to clang. This method is an implementation detail of
240 /// AddImplicitPreamble.
242 setupPreambleStorage(const PCHStorage &Storage,
243 PreprocessorOptions &PreprocessorOpts,
244 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
246 /// Manages the memory buffer or temporary file that stores the PCH.
248 /// Keeps track of the files that were used when computing the
249 /// preamble, with both their buffer size and their modification time.
251 /// If any of the files have changed from one compile to the next,
252 /// the preamble must be thrown away.
253 llvm::StringMap<PreambleFileHash> FilesInPreamble;
254 /// Files that were not found during preamble building. If any of these now
255 /// exist then the preamble should not be reused.
257 /// Storing *all* the missing files that could invalidate the preamble would
258 /// make it too expensive to revalidate (when the include path has many
259 /// entries, each #include will miss half of them on average).
260 /// Instead, we track only files that could have satisfied an #include that
261 /// was ultimately not found.
262 llvm::StringSet<> MissingFiles;
263 /// The contents of the file that was used to precompile the preamble. Only
264 /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
265 /// part of the file has not changed, so that preamble can be reused.
266 std::vector<char> PreambleBytes;
267 /// See PreambleBounds::PreambleEndsAtStartOfLine
268 bool PreambleEndsAtStartOfLine;
271 /// A set of callbacks to gather useful information while building a preamble.
272 class PreambleCallbacks {
274 virtual ~PreambleCallbacks() = default;
276 /// Called before FrontendAction::BeginSourceFile.
277 /// Can be used to store references to various CompilerInstance fields
278 /// (e.g. SourceManager) that may be interesting to the consumers of other
280 virtual void BeforeExecute(CompilerInstance &CI);
281 /// Called after FrontendAction::Execute(), but before
282 /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
283 /// various CompilerInstance fields before they are destroyed.
284 virtual void AfterExecute(CompilerInstance &CI);
285 /// Called after PCH has been emitted. \p Writer may be used to retrieve
286 /// information about AST, serialized in PCH.
287 virtual void AfterPCHEmitted(ASTWriter &Writer);
288 /// Called for each TopLevelDecl.
289 /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
290 /// used instead, but having only this method allows a simpler API.
291 virtual void HandleTopLevelDecl(DeclGroupRef DG);
292 /// Creates wrapper class for PPCallbacks so we can also process information
293 /// about includes that are inside of a preamble
294 virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
295 /// The returned CommentHandler will be added to the preprocessor if not null.
296 virtual CommentHandler *getCommentHandler();
297 /// Determines which function bodies are parsed, by default skips everything.
298 /// Only used if FrontendOpts::SkipFunctionBodies is true.
299 /// See ASTConsumer::shouldSkipFunctionBody.
300 virtual bool shouldSkipFunctionBody(Decl *D) { return true; }
303 enum class BuildPreambleError {
304 CouldntCreateTempFile = 1,
305 CouldntCreateTargetInfo,
306 BeginSourceFileFailed,
311 class BuildPreambleErrorCategory final : public std::error_category {
313 const char *name() const noexcept override;
314 std::string message(int condition) const override;
317 std::error_code make_error_code(BuildPreambleError Error);
322 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};