1 //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Helper class to build precompiled preamble.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
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"
24 #include <system_error>
25 #include <type_traits>
36 class CompilerInstance;
37 class CompilerInvocation;
39 class PCHContainerOperations;
41 /// \brief Runs lexer to compute suggested preamble bounds.
42 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
43 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 /// \brief 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, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
84 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
85 bool StoreInMemory, PreambleCallbacks &Callbacks);
87 PrecompiledPreamble(PrecompiledPreamble &&) = default;
88 PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
90 /// PreambleBounds used to build the preamble.
91 PreambleBounds getBounds() const;
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;
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;
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
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,
112 IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
113 llvm::MemoryBuffer *MainFileBuffer) const;
116 PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
117 bool PreambleEndsAtStartOfLine,
118 llvm::StringMap<PreambleFileHash> FilesInPreamble);
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'
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.
127 // A main method used to construct TempPCHFile.
128 static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
130 /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
131 static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
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);
139 TempPCHFile(std::string FilePath);
142 TempPCHFile(TempPCHFile &&Other);
143 TempPCHFile &operator=(TempPCHFile &&Other);
145 TempPCHFile(const TempPCHFile &) = delete;
148 /// A path where temporary file is stored.
149 llvm::StringRef getFilePath() const;
152 void RemoveFileIfPresent();
155 llvm::Optional<std::string> FilePath;
158 class InMemoryPreamble {
165 enum class Kind { Empty, InMemory, TempFile };
167 PCHStorage() = default;
168 PCHStorage(TempPCHFile File);
169 PCHStorage(InMemoryPreamble Memory);
171 PCHStorage(const PCHStorage &) = delete;
172 PCHStorage &operator=(const PCHStorage &) = delete;
174 PCHStorage(PCHStorage &&Other);
175 PCHStorage &operator=(PCHStorage &&Other);
179 Kind getKind() const;
181 TempPCHFile &asFile();
182 const TempPCHFile &asFile() const;
184 InMemoryPreamble &asMemory();
185 const InMemoryPreamble &asMemory() const;
192 Kind StorageKind = Kind::Empty;
193 llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
196 /// Data used to determine if a file used in the preamble has been changed.
197 struct PreambleFileHash {
198 /// All files have size set.
201 /// Modification time is set for files that are on disk. For memory
202 /// buffers it is zero.
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 = {};
210 static PreambleFileHash createForFile(off_t Size, time_t ModTime);
211 static PreambleFileHash
212 createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
214 friend bool operator==(const PreambleFileHash &LHS,
215 const PreambleFileHash &RHS) {
216 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
219 friend bool operator!=(const PreambleFileHash &LHS,
220 const PreambleFileHash &RHS) {
221 return !(LHS == RHS);
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,
230 IntrusiveRefCntPtr<vfs::FileSystem> &VFS);
232 /// Manages the memory buffer or temporary file that stores the PCH.
234 /// Keeps track of the files that were used when computing the
235 /// preamble, with both their buffer size and their modification time.
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;
248 /// A set of callbacks to gather useful information while building a preamble.
249 class PreambleCallbacks {
251 virtual ~PreambleCallbacks() = default;
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
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();
274 enum class BuildPreambleError {
276 CouldntCreateTempFile,
277 CouldntCreateTargetInfo,
278 CouldntCreateVFSOverlay,
279 BeginSourceFileFailed,
283 class BuildPreambleErrorCategory final : public std::error_category {
285 const char *name() const noexcept override;
286 std::string message(int condition) const override;
289 std::error_code make_error_code(BuildPreambleError Error);
294 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};