]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Frontend/PrecompiledPreamble.h
Import OpenCSD -- an ARM CoreSight(tm) Trace Decode Library.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Frontend / PrecompiledPreamble.h
1 //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Helper class to build precompiled preamble.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
16
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"
22 #include <cstddef>
23 #include <memory>
24 #include <system_error>
25 #include <type_traits>
26
27 namespace llvm {
28 class MemoryBuffer;
29 }
30
31 namespace clang {
32 namespace vfs {
33 class FileSystem;
34 }
35
36 class CompilerInstance;
37 class CompilerInvocation;
38 class DeclGroupRef;
39 class PCHContainerOperations;
40
41 /// \brief Runs lexer to compute suggested preamble bounds.
42 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
43                                      llvm::MemoryBuffer *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   /// \brief 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 Callbacks A set of callbacks to be executed when building
79   /// the preamble.
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);
86
87   PrecompiledPreamble(PrecompiledPreamble &&) = default;
88   PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
89
90   /// PreambleBounds used to build the preamble.
91   PreambleBounds getBounds() const;
92
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;
97
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;
103
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
106   /// is accessible.
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;
114
115 private:
116   PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
117                       bool PreambleEndsAtStartOfLine,
118                       llvm::StringMap<PreambleFileHash> FilesInPreamble);
119
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'
122   /// destruction.
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.
125   class TempPCHFile {
126   public:
127     // A main method used to construct TempPCHFile.
128     static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
129
130     /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
131     static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
132                                                             StringRef Suffix);
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);
137
138   private:
139     TempPCHFile(std::string FilePath);
140
141   public:
142     TempPCHFile(TempPCHFile &&Other);
143     TempPCHFile &operator=(TempPCHFile &&Other);
144
145     TempPCHFile(const TempPCHFile &) = delete;
146     ~TempPCHFile();
147
148     /// A path where temporary file is stored.
149     llvm::StringRef getFilePath() const;
150
151   private:
152     void RemoveFileIfPresent();
153
154   private:
155     llvm::Optional<std::string> FilePath;
156   };
157
158   class InMemoryPreamble {
159   public:
160     std::string Data;
161   };
162
163   class PCHStorage {
164   public:
165     enum class Kind { Empty, InMemory, TempFile };
166
167     PCHStorage() = default;
168     PCHStorage(TempPCHFile File);
169     PCHStorage(InMemoryPreamble Memory);
170
171     PCHStorage(const PCHStorage &) = delete;
172     PCHStorage &operator=(const PCHStorage &) = delete;
173
174     PCHStorage(PCHStorage &&Other);
175     PCHStorage &operator=(PCHStorage &&Other);
176
177     ~PCHStorage();
178
179     Kind getKind() const;
180
181     TempPCHFile &asFile();
182     const TempPCHFile &asFile() const;
183
184     InMemoryPreamble &asMemory();
185     const InMemoryPreamble &asMemory() const;
186
187   private:
188     void destroy();
189     void setEmpty();
190
191   private:
192     Kind StorageKind = Kind::Empty;
193     llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
194   };
195
196   /// Data used to determine if a file used in the preamble has been changed.
197   struct PreambleFileHash {
198     /// All files have size set.
199     off_t Size = 0;
200
201     /// Modification time is set for files that are on disk.  For memory
202     /// buffers it is zero.
203     time_t ModTime = 0;
204
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 = {};
209
210     static PreambleFileHash createForFile(off_t Size, time_t ModTime);
211     static PreambleFileHash
212     createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
213
214     friend bool operator==(const PreambleFileHash &LHS,
215                            const PreambleFileHash &RHS) {
216       return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
217              LHS.MD5 == RHS.MD5;
218     }
219     friend bool operator!=(const PreambleFileHash &LHS,
220                            const PreambleFileHash &RHS) {
221       return !(LHS == RHS);
222     }
223   };
224
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);
231
232   /// Manages the memory buffer or temporary file that stores the PCH.
233   PCHStorage Storage;
234   /// Keeps track of the files that were used when computing the
235   /// preamble, with both their buffer size and their modification time.
236   ///
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;
246 };
247
248 /// A set of callbacks to gather useful information while building a preamble.
249 class PreambleCallbacks {
250 public:
251   virtual ~PreambleCallbacks() = default;
252
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
256   /// callbacks.
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();
272 };
273
274 enum class BuildPreambleError {
275   PreambleIsEmpty = 1,
276   CouldntCreateTempFile,
277   CouldntCreateTargetInfo,
278   CouldntCreateVFSOverlay,
279   BeginSourceFileFailed,
280   CouldntEmitPCH
281 };
282
283 class BuildPreambleErrorCategory final : public std::error_category {
284 public:
285   const char *name() const noexcept override;
286   std::string message(int condition) const override;
287 };
288
289 std::error_code make_error_code(BuildPreambleError Error);
290 } // namespace clang
291
292 namespace std {
293 template <>
294 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
295 } // namespace std
296
297 #endif