1 | //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Helper class to build precompiled preamble. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H |
14 | #define LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H |
15 | |
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/MD5.h" |
21 | #include <cstddef> |
22 | #include <memory> |
23 | #include <system_error> |
24 | #include <type_traits> |
25 | |
26 | namespace llvm { |
27 | class MemoryBuffer; |
28 | class MemoryBufferRef; |
29 | namespace vfs { |
30 | class FileSystem; |
31 | } |
32 | } // namespace llvm |
33 | |
34 | namespace clang { |
35 | class CompilerInstance; |
36 | class CompilerInvocation; |
37 | class Decl; |
38 | class DeclGroupRef; |
39 | class PCHContainerOperations; |
40 | |
41 | /// Runs lexer to compute suggested preamble bounds. |
42 | PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, |
43 | const llvm::MemoryBufferRef &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. |
51 | class PrecompiledPreamble { |
52 | class PCHStorage; |
53 | struct PreambleFileHash; |
54 | |
55 | public: |
56 | /// 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 StoragePath The path to a directory, in which to create a temporary |
79 | /// file to store PCH in. If empty, the default system temporary directory is |
80 | /// used. This parameter is ignored if \p StoreInMemory is true. |
81 | /// |
82 | /// \param Callbacks A set of callbacks to be executed when building |
83 | /// the preamble. |
84 | static llvm::ErrorOr<PrecompiledPreamble> |
85 | Build(const CompilerInvocation &Invocation, |
86 | const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, |
87 | DiagnosticsEngine &Diagnostics, |
88 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, |
89 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
90 | bool StoreInMemory, StringRef StoragePath, |
91 | PreambleCallbacks &Callbacks); |
92 | |
93 | PrecompiledPreamble(PrecompiledPreamble &&); |
94 | PrecompiledPreamble &operator=(PrecompiledPreamble &&); |
95 | ~PrecompiledPreamble(); |
96 | |
97 | /// PreambleBounds used to build the preamble. |
98 | PreambleBounds getBounds() const; |
99 | |
100 | /// Returns the size, in bytes, that preamble takes on disk or in memory. |
101 | /// For on-disk preambles returns 0 if filesystem operations fail. Intended to |
102 | /// be used for logging and debugging purposes only. |
103 | std::size_t getSize() const; |
104 | |
105 | /// Returned string is not null-terminated. |
106 | llvm::StringRef getContents() const { |
107 | return {PreambleBytes.data(), PreambleBytes.size()}; |
108 | } |
109 | |
110 | /// Check whether PrecompiledPreamble can be reused for the new contents(\p |
111 | /// MainFileBuffer) of the main file. |
112 | bool CanReuse(const CompilerInvocation &Invocation, |
113 | const llvm::MemoryBufferRef &MainFileBuffer, |
114 | PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const; |
115 | |
116 | /// Changes options inside \p CI to use PCH from this preamble. Also remaps |
117 | /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble |
118 | /// is accessible. |
119 | /// Requires that CanReuse() is true. |
120 | /// For in-memory preambles, PrecompiledPreamble instance continues to own the |
121 | /// MemoryBuffer with the Preamble after this method returns. The caller is |
122 | /// responsible for making sure the PrecompiledPreamble instance outlives the |
123 | /// compiler run and the AST that will be using the PCH. |
124 | void AddImplicitPreamble(CompilerInvocation &CI, |
125 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, |
126 | llvm::MemoryBuffer *MainFileBuffer) const; |
127 | |
128 | /// Configure \p CI to use this preamble. |
129 | /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true. |
130 | /// If this preamble does not match the file, it may parse differently. |
131 | void OverridePreamble(CompilerInvocation &CI, |
132 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, |
133 | llvm::MemoryBuffer *MainFileBuffer) const; |
134 | |
135 | private: |
136 | PrecompiledPreamble(std::unique_ptr<PCHStorage> Storage, |
137 | std::vector<char> PreambleBytes, |
138 | bool PreambleEndsAtStartOfLine, |
139 | llvm::StringMap<PreambleFileHash> FilesInPreamble, |
140 | llvm::StringSet<> MissingFiles); |
141 | |
142 | /// Data used to determine if a file used in the preamble has been changed. |
143 | struct PreambleFileHash { |
144 | /// All files have size set. |
145 | off_t Size = 0; |
146 | |
147 | /// Modification time is set for files that are on disk. For memory |
148 | /// buffers it is zero. |
149 | time_t ModTime = 0; |
150 | |
151 | /// Memory buffers have MD5 instead of modification time. We don't |
152 | /// compute MD5 for on-disk files because we hope that modification time is |
153 | /// enough to tell if the file was changed. |
154 | llvm::MD5::MD5Result MD5 = {}; |
155 | |
156 | static PreambleFileHash createForFile(off_t Size, time_t ModTime); |
157 | static PreambleFileHash |
158 | createForMemoryBuffer(const llvm::MemoryBufferRef &Buffer); |
159 | |
160 | friend bool operator==(const PreambleFileHash &LHS, |
161 | const PreambleFileHash &RHS) { |
162 | return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime && |
163 | LHS.MD5 == RHS.MD5; |
164 | } |
165 | friend bool operator!=(const PreambleFileHash &LHS, |
166 | const PreambleFileHash &RHS) { |
167 | return !(LHS == RHS); |
168 | } |
169 | }; |
170 | |
171 | /// Helper function to set up PCH for the preamble into \p CI and \p VFS to |
172 | /// with the specified \p Bounds. |
173 | void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI, |
174 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, |
175 | llvm::MemoryBuffer *MainFileBuffer) const; |
176 | |
177 | /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p |
178 | /// Storage is accessible to clang. This method is an implementation detail of |
179 | /// AddImplicitPreamble. |
180 | static void |
181 | setupPreambleStorage(const PCHStorage &Storage, |
182 | PreprocessorOptions &PreprocessorOpts, |
183 | IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS); |
184 | |
185 | /// Manages the memory buffer or temporary file that stores the PCH. |
186 | std::unique_ptr<PCHStorage> Storage; |
187 | /// Keeps track of the files that were used when computing the |
188 | /// preamble, with both their buffer size and their modification time. |
189 | /// |
190 | /// If any of the files have changed from one compile to the next, |
191 | /// the preamble must be thrown away. |
192 | llvm::StringMap<PreambleFileHash> FilesInPreamble; |
193 | /// Files that were not found during preamble building. If any of these now |
194 | /// exist then the preamble should not be reused. |
195 | /// |
196 | /// Storing *all* the missing files that could invalidate the preamble would |
197 | /// make it too expensive to revalidate (when the include path has many |
198 | /// entries, each #include will miss half of them on average). |
199 | /// Instead, we track only files that could have satisfied an #include that |
200 | /// was ultimately not found. |
201 | llvm::StringSet<> MissingFiles; |
202 | /// The contents of the file that was used to precompile the preamble. Only |
203 | /// contains first PreambleBounds::Size bytes. Used to compare if the relevant |
204 | /// part of the file has not changed, so that preamble can be reused. |
205 | std::vector<char> PreambleBytes; |
206 | /// See PreambleBounds::PreambleEndsAtStartOfLine |
207 | bool PreambleEndsAtStartOfLine; |
208 | }; |
209 | |
210 | /// A set of callbacks to gather useful information while building a preamble. |
211 | class PreambleCallbacks { |
212 | public: |
213 | virtual ~PreambleCallbacks() = default; |
214 | |
215 | /// Called before FrontendAction::Execute. |
216 | /// Can be used to store references to various CompilerInstance fields |
217 | /// (e.g. SourceManager) that may be interesting to the consumers of other |
218 | /// callbacks. |
219 | virtual void BeforeExecute(CompilerInstance &CI); |
220 | /// Called after FrontendAction::Execute(), but before |
221 | /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of |
222 | /// various CompilerInstance fields before they are destroyed. |
223 | virtual void AfterExecute(CompilerInstance &CI); |
224 | /// Called after PCH has been emitted. \p Writer may be used to retrieve |
225 | /// information about AST, serialized in PCH. |
226 | virtual void AfterPCHEmitted(ASTWriter &Writer); |
227 | /// Called for each TopLevelDecl. |
228 | /// NOTE: To allow more flexibility a custom ASTConsumer could probably be |
229 | /// used instead, but having only this method allows a simpler API. |
230 | virtual void HandleTopLevelDecl(DeclGroupRef DG); |
231 | /// Creates wrapper class for PPCallbacks so we can also process information |
232 | /// about includes that are inside of a preamble. Called after BeforeExecute. |
233 | virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); |
234 | /// The returned CommentHandler will be added to the preprocessor if not null. |
235 | virtual CommentHandler *getCommentHandler(); |
236 | /// Determines which function bodies are parsed, by default skips everything. |
237 | /// Only used if FrontendOpts::SkipFunctionBodies is true. |
238 | /// See ASTConsumer::shouldSkipFunctionBody. |
239 | virtual bool shouldSkipFunctionBody(Decl *D) { return true; } |
240 | }; |
241 | |
242 | enum class BuildPreambleError { |
243 | CouldntCreateTempFile = 1, |
244 | CouldntCreateTargetInfo, |
245 | BeginSourceFileFailed, |
246 | CouldntEmitPCH, |
247 | BadInputs |
248 | }; |
249 | |
250 | class BuildPreambleErrorCategory final : public std::error_category { |
251 | public: |
252 | const char *name() const noexcept override; |
253 | std::string message(int condition) const override; |
254 | }; |
255 | |
256 | std::error_code make_error_code(BuildPreambleError Error); |
257 | } // namespace clang |
258 | |
259 | namespace std { |
260 | template <> |
261 | struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {}; |
262 | } // namespace std |
263 | |
264 | #endif |
265 | |