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/Support/AlignOf.h"
20 #include "llvm/Support/MD5.h"
23 #include <system_error>
24 #include <type_traits>
34 class CompilerInstance;
35 class CompilerInvocation;
37 class PCHContainerOperations;
39 /// Runs lexer to compute suggested preamble bounds.
40 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
41 llvm::MemoryBuffer *Buffer,
44 class PreambleCallbacks;
46 /// A class holding a PCH and all information to check whether it is valid to
47 /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
48 /// CanReusePreamble + AddImplicitPreamble to make use of it.
49 class PrecompiledPreamble {
51 struct PreambleFileHash;
54 /// Try to build PrecompiledPreamble for \p Invocation. See
55 /// BuildPreambleError for possible error codes.
57 /// \param Invocation Original CompilerInvocation with options to compile the
60 /// \param MainFileBuffer Buffer with the contents of the main file.
62 /// \param Bounds Bounds of the preamble, result of calling
63 /// ComputePreambleBounds.
65 /// \param Diagnostics Diagnostics engine to be used while building the
68 /// \param VFS An instance of vfs::FileSystem to be used for file
71 /// \param PCHContainerOps An instance of PCHContainerOperations.
73 /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
76 /// \param Callbacks A set of callbacks to be executed when building
78 static llvm::ErrorOr<PrecompiledPreamble>
79 Build(const CompilerInvocation &Invocation,
80 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
81 DiagnosticsEngine &Diagnostics,
82 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
83 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
84 bool StoreInMemory, PreambleCallbacks &Callbacks);
86 PrecompiledPreamble(PrecompiledPreamble &&) = default;
87 PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
89 /// PreambleBounds used to build the preamble.
90 PreambleBounds getBounds() const;
92 /// Returns the size, in bytes, that preamble takes on disk or in memory.
93 /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
94 /// be used for logging and debugging purposes only.
95 std::size_t getSize() const;
97 /// Check whether PrecompiledPreamble can be reused for the new contents(\p
98 /// MainFileBuffer) of the main file.
99 bool CanReuse(const CompilerInvocation &Invocation,
100 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
101 llvm::vfs::FileSystem *VFS) const;
103 /// Changes options inside \p CI to use PCH from this preamble. Also remaps
104 /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
106 /// Requires that CanReuse() is true.
107 /// For in-memory preambles, PrecompiledPreamble instance continues to own the
108 /// MemoryBuffer with the Preamble after this method returns. The caller is
109 /// responsible for making sure the PrecompiledPreamble instance outlives the
110 /// compiler run and the AST that will be using the PCH.
111 void AddImplicitPreamble(CompilerInvocation &CI,
112 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
113 llvm::MemoryBuffer *MainFileBuffer) const;
115 /// Configure \p CI to use this preamble.
116 /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
117 /// If this preamble does not match the file, it may parse differently.
118 void OverridePreamble(CompilerInvocation &CI,
119 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
120 llvm::MemoryBuffer *MainFileBuffer) const;
123 PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
124 bool PreambleEndsAtStartOfLine,
125 llvm::StringMap<PreambleFileHash> FilesInPreamble);
127 /// A temp file that would be deleted on destructor call. If destructor is not
128 /// called for any reason, the file will be deleted at static objects'
130 /// An assertion will fire if two TempPCHFiles are created with the same name,
131 /// so it's not intended to be used outside preamble-handling.
134 // A main method used to construct TempPCHFile.
135 static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
138 TempPCHFile(std::string FilePath);
141 TempPCHFile(TempPCHFile &&Other);
142 TempPCHFile &operator=(TempPCHFile &&Other);
144 TempPCHFile(const TempPCHFile &) = delete;
147 /// A path where temporary file is stored.
148 llvm::StringRef getFilePath() const;
151 void RemoveFileIfPresent();
154 llvm::Optional<std::string> FilePath;
157 class InMemoryPreamble {
164 enum class Kind { Empty, InMemory, TempFile };
166 PCHStorage() = default;
167 PCHStorage(TempPCHFile File);
168 PCHStorage(InMemoryPreamble Memory);
170 PCHStorage(const PCHStorage &) = delete;
171 PCHStorage &operator=(const PCHStorage &) = delete;
173 PCHStorage(PCHStorage &&Other);
174 PCHStorage &operator=(PCHStorage &&Other);
178 Kind getKind() const;
180 TempPCHFile &asFile();
181 const TempPCHFile &asFile() const;
183 InMemoryPreamble &asMemory();
184 const InMemoryPreamble &asMemory() const;
191 Kind StorageKind = Kind::Empty;
192 llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
195 /// Data used to determine if a file used in the preamble has been changed.
196 struct PreambleFileHash {
197 /// All files have size set.
200 /// Modification time is set for files that are on disk. For memory
201 /// buffers it is zero.
204 /// Memory buffers have MD5 instead of modification time. We don't
205 /// compute MD5 for on-disk files because we hope that modification time is
206 /// enough to tell if the file was changed.
207 llvm::MD5::MD5Result MD5 = {};
209 static PreambleFileHash createForFile(off_t Size, time_t ModTime);
210 static PreambleFileHash
211 createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
213 friend bool operator==(const PreambleFileHash &LHS,
214 const PreambleFileHash &RHS) {
215 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
218 friend bool operator!=(const PreambleFileHash &LHS,
219 const PreambleFileHash &RHS) {
220 return !(LHS == RHS);
224 /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
225 /// with the specified \p Bounds.
226 void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
227 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
228 llvm::MemoryBuffer *MainFileBuffer) const;
230 /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
231 /// Storage is accessible to clang. This method is an implementation detail of
232 /// AddImplicitPreamble.
234 setupPreambleStorage(const PCHStorage &Storage,
235 PreprocessorOptions &PreprocessorOpts,
236 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
238 /// Manages the memory buffer or temporary file that stores the PCH.
240 /// Keeps track of the files that were used when computing the
241 /// preamble, with both their buffer size and their modification time.
243 /// If any of the files have changed from one compile to the next,
244 /// the preamble must be thrown away.
245 llvm::StringMap<PreambleFileHash> FilesInPreamble;
246 /// The contents of the file that was used to precompile the preamble. Only
247 /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
248 /// part of the file has not changed, so that preamble can be reused.
249 std::vector<char> PreambleBytes;
250 /// See PreambleBounds::PreambleEndsAtStartOfLine
251 bool PreambleEndsAtStartOfLine;
254 /// A set of callbacks to gather useful information while building a preamble.
255 class PreambleCallbacks {
257 virtual ~PreambleCallbacks() = default;
259 /// Called before FrontendAction::BeginSourceFile.
260 /// Can be used to store references to various CompilerInstance fields
261 /// (e.g. SourceManager) that may be interesting to the consumers of other
263 virtual void BeforeExecute(CompilerInstance &CI);
264 /// Called after FrontendAction::Execute(), but before
265 /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
266 /// various CompilerInstance fields before they are destroyed.
267 virtual void AfterExecute(CompilerInstance &CI);
268 /// Called after PCH has been emitted. \p Writer may be used to retrieve
269 /// information about AST, serialized in PCH.
270 virtual void AfterPCHEmitted(ASTWriter &Writer);
271 /// Called for each TopLevelDecl.
272 /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
273 /// used instead, but having only this method allows a simpler API.
274 virtual void HandleTopLevelDecl(DeclGroupRef DG);
275 /// Creates wrapper class for PPCallbacks so we can also process information
276 /// about includes that are inside of a preamble
277 virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
278 /// The returned CommentHandler will be added to the preprocessor if not null.
279 virtual CommentHandler *getCommentHandler();
282 enum class BuildPreambleError {
283 CouldntCreateTempFile = 1,
284 CouldntCreateTargetInfo,
285 BeginSourceFileFailed,
290 class BuildPreambleErrorCategory final : public std::error_category {
292 const char *name() const noexcept override;
293 std::string message(int condition) const override;
296 std::error_code make_error_code(BuildPreambleError Error);
301 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};