]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/include/clang/Frontend/PrecompiledPreamble.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / include / clang / Frontend / PrecompiledPreamble.h
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_PRECOMPILED_PREAMBLE_H
14 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15
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"
21 #include <cstddef>
22 #include <memory>
23 #include <system_error>
24 #include <type_traits>
25
26 namespace llvm {
27 class MemoryBuffer;
28 namespace vfs {
29 class FileSystem;
30 }
31 } // namespace llvm
32
33 namespace clang {
34 class CompilerInstance;
35 class CompilerInvocation;
36 class DeclGroupRef;
37 class PCHContainerOperations;
38
39 /// Runs lexer to compute suggested preamble bounds.
40 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
41                                      llvm::MemoryBuffer *Buffer,
42                                      unsigned MaxLines);
43
44 class PreambleCallbacks;
45
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 {
50   class PCHStorage;
51   struct PreambleFileHash;
52
53 public:
54   /// Try to build PrecompiledPreamble for \p Invocation. See
55   /// BuildPreambleError for possible error codes.
56   ///
57   /// \param Invocation Original CompilerInvocation with options to compile the
58   /// file.
59   ///
60   /// \param MainFileBuffer Buffer with the contents of the main file.
61   ///
62   /// \param Bounds Bounds of the preamble, result of calling
63   /// ComputePreambleBounds.
64   ///
65   /// \param Diagnostics Diagnostics engine to be used while building the
66   /// preamble.
67   ///
68   /// \param VFS An instance of vfs::FileSystem to be used for file
69   /// accesses.
70   ///
71   /// \param PCHContainerOps An instance of PCHContainerOperations.
72   ///
73   /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
74   /// a temporary file.
75   ///
76   /// \param Callbacks A set of callbacks to be executed when building
77   /// the preamble.
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);
85
86   PrecompiledPreamble(PrecompiledPreamble &&) = default;
87   PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
88
89   /// PreambleBounds used to build the preamble.
90   PreambleBounds getBounds() const;
91
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;
96
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;
102
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
105   /// is accessible.
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;
114
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;
121
122 private:
123   PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
124                       bool PreambleEndsAtStartOfLine,
125                       llvm::StringMap<PreambleFileHash> FilesInPreamble);
126
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'
129   /// destruction.
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.
132   class TempPCHFile {
133   public:
134     // A main method used to construct TempPCHFile.
135     static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
136
137   private:
138     TempPCHFile(std::string FilePath);
139
140   public:
141     TempPCHFile(TempPCHFile &&Other);
142     TempPCHFile &operator=(TempPCHFile &&Other);
143
144     TempPCHFile(const TempPCHFile &) = delete;
145     ~TempPCHFile();
146
147     /// A path where temporary file is stored.
148     llvm::StringRef getFilePath() const;
149
150   private:
151     void RemoveFileIfPresent();
152
153   private:
154     llvm::Optional<std::string> FilePath;
155   };
156
157   class InMemoryPreamble {
158   public:
159     std::string Data;
160   };
161
162   class PCHStorage {
163   public:
164     enum class Kind { Empty, InMemory, TempFile };
165
166     PCHStorage() = default;
167     PCHStorage(TempPCHFile File);
168     PCHStorage(InMemoryPreamble Memory);
169
170     PCHStorage(const PCHStorage &) = delete;
171     PCHStorage &operator=(const PCHStorage &) = delete;
172
173     PCHStorage(PCHStorage &&Other);
174     PCHStorage &operator=(PCHStorage &&Other);
175
176     ~PCHStorage();
177
178     Kind getKind() const;
179
180     TempPCHFile &asFile();
181     const TempPCHFile &asFile() const;
182
183     InMemoryPreamble &asMemory();
184     const InMemoryPreamble &asMemory() const;
185
186   private:
187     void destroy();
188     void setEmpty();
189
190   private:
191     Kind StorageKind = Kind::Empty;
192     llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
193   };
194
195   /// Data used to determine if a file used in the preamble has been changed.
196   struct PreambleFileHash {
197     /// All files have size set.
198     off_t Size = 0;
199
200     /// Modification time is set for files that are on disk.  For memory
201     /// buffers it is zero.
202     time_t ModTime = 0;
203
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 = {};
208
209     static PreambleFileHash createForFile(off_t Size, time_t ModTime);
210     static PreambleFileHash
211     createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
212
213     friend bool operator==(const PreambleFileHash &LHS,
214                            const PreambleFileHash &RHS) {
215       return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
216              LHS.MD5 == RHS.MD5;
217     }
218     friend bool operator!=(const PreambleFileHash &LHS,
219                            const PreambleFileHash &RHS) {
220       return !(LHS == RHS);
221     }
222   };
223
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;
229
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.
233   static void
234   setupPreambleStorage(const PCHStorage &Storage,
235                        PreprocessorOptions &PreprocessorOpts,
236                        IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
237
238   /// Manages the memory buffer or temporary file that stores the PCH.
239   PCHStorage Storage;
240   /// Keeps track of the files that were used when computing the
241   /// preamble, with both their buffer size and their modification time.
242   ///
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;
252 };
253
254 /// A set of callbacks to gather useful information while building a preamble.
255 class PreambleCallbacks {
256 public:
257   virtual ~PreambleCallbacks() = default;
258
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
262   /// callbacks.
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();
280 };
281
282 enum class BuildPreambleError {
283   CouldntCreateTempFile = 1,
284   CouldntCreateTargetInfo,
285   BeginSourceFileFailed,
286   CouldntEmitPCH,
287   BadInputs
288 };
289
290 class BuildPreambleErrorCategory final : public std::error_category {
291 public:
292   const char *name() const noexcept override;
293   std::string message(int condition) const override;
294 };
295
296 std::error_code make_error_code(BuildPreambleError Error);
297 } // namespace clang
298
299 namespace std {
300 template <>
301 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
302 } // namespace std
303
304 #endif