|
|
|||
File indexing completed on 2026-05-10 08:36:55
0001 //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // Helper class to build precompiled preamble. 0010 // 0011 //===----------------------------------------------------------------------===// 0012 0013 #ifndef LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H 0014 #define LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H 0015 0016 #include "clang/Lex/Lexer.h" 0017 #include "clang/Lex/Preprocessor.h" 0018 #include "llvm/ADT/IntrusiveRefCntPtr.h" 0019 #include "llvm/ADT/StringRef.h" 0020 #include "llvm/Support/MD5.h" 0021 #include <cstddef> 0022 #include <memory> 0023 #include <system_error> 0024 #include <type_traits> 0025 0026 namespace llvm { 0027 class MemoryBuffer; 0028 class MemoryBufferRef; 0029 namespace vfs { 0030 class FileSystem; 0031 } 0032 } // namespace llvm 0033 0034 namespace clang { 0035 class CompilerInstance; 0036 class CompilerInvocation; 0037 class Decl; 0038 class DeclGroupRef; 0039 class PCHContainerOperations; 0040 0041 /// Runs lexer to compute suggested preamble bounds. 0042 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, 0043 const llvm::MemoryBufferRef &Buffer, 0044 unsigned MaxLines); 0045 0046 class PreambleCallbacks; 0047 0048 /// A class holding a PCH and all information to check whether it is valid to 0049 /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and 0050 /// CanReusePreamble + AddImplicitPreamble to make use of it. 0051 class PrecompiledPreamble { 0052 class PCHStorage; 0053 struct PreambleFileHash; 0054 0055 public: 0056 /// Try to build PrecompiledPreamble for \p Invocation. See 0057 /// BuildPreambleError for possible error codes. 0058 /// 0059 /// \param Invocation Original CompilerInvocation with options to compile the 0060 /// file. 0061 /// 0062 /// \param MainFileBuffer Buffer with the contents of the main file. 0063 /// 0064 /// \param Bounds Bounds of the preamble, result of calling 0065 /// ComputePreambleBounds. 0066 /// 0067 /// \param Diagnostics Diagnostics engine to be used while building the 0068 /// preamble. 0069 /// 0070 /// \param VFS An instance of vfs::FileSystem to be used for file 0071 /// accesses. 0072 /// 0073 /// \param PCHContainerOps An instance of PCHContainerOperations. 0074 /// 0075 /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in 0076 /// a temporary file. 0077 /// 0078 /// \param StoragePath The path to a directory, in which to create a temporary 0079 /// file to store PCH in. If empty, the default system temporary directory is 0080 /// used. This parameter is ignored if \p StoreInMemory is true. 0081 /// 0082 /// \param Callbacks A set of callbacks to be executed when building 0083 /// the preamble. 0084 static llvm::ErrorOr<PrecompiledPreamble> 0085 Build(const CompilerInvocation &Invocation, 0086 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, 0087 DiagnosticsEngine &Diagnostics, 0088 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, 0089 std::shared_ptr<PCHContainerOperations> PCHContainerOps, 0090 bool StoreInMemory, StringRef StoragePath, 0091 PreambleCallbacks &Callbacks); 0092 0093 PrecompiledPreamble(PrecompiledPreamble &&); 0094 PrecompiledPreamble &operator=(PrecompiledPreamble &&); 0095 ~PrecompiledPreamble(); 0096 0097 /// PreambleBounds used to build the preamble. 0098 PreambleBounds getBounds() const; 0099 0100 /// Returns the size, in bytes, that preamble takes on disk or in memory. 0101 /// For on-disk preambles returns 0 if filesystem operations fail. Intended to 0102 /// be used for logging and debugging purposes only. 0103 std::size_t getSize() const; 0104 0105 /// Returned string is not null-terminated. 0106 llvm::StringRef getContents() const { 0107 return {PreambleBytes.data(), PreambleBytes.size()}; 0108 } 0109 0110 /// Check whether PrecompiledPreamble can be reused for the new contents(\p 0111 /// MainFileBuffer) of the main file. 0112 bool CanReuse(const CompilerInvocation &Invocation, 0113 const llvm::MemoryBufferRef &MainFileBuffer, 0114 PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const; 0115 0116 /// Changes options inside \p CI to use PCH from this preamble. Also remaps 0117 /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble 0118 /// is accessible. 0119 /// Requires that CanReuse() is true. 0120 /// For in-memory preambles, PrecompiledPreamble instance continues to own the 0121 /// MemoryBuffer with the Preamble after this method returns. The caller is 0122 /// responsible for making sure the PrecompiledPreamble instance outlives the 0123 /// compiler run and the AST that will be using the PCH. 0124 void AddImplicitPreamble(CompilerInvocation &CI, 0125 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 0126 llvm::MemoryBuffer *MainFileBuffer) const; 0127 0128 /// Configure \p CI to use this preamble. 0129 /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true. 0130 /// If this preamble does not match the file, it may parse differently. 0131 void OverridePreamble(CompilerInvocation &CI, 0132 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 0133 llvm::MemoryBuffer *MainFileBuffer) const; 0134 0135 private: 0136 PrecompiledPreamble(std::unique_ptr<PCHStorage> Storage, 0137 std::vector<char> PreambleBytes, 0138 bool PreambleEndsAtStartOfLine, 0139 llvm::StringMap<PreambleFileHash> FilesInPreamble, 0140 llvm::StringSet<> MissingFiles); 0141 0142 /// Data used to determine if a file used in the preamble has been changed. 0143 struct PreambleFileHash { 0144 /// All files have size set. 0145 off_t Size = 0; 0146 0147 /// Modification time is set for files that are on disk. For memory 0148 /// buffers it is zero. 0149 time_t ModTime = 0; 0150 0151 /// Memory buffers have MD5 instead of modification time. We don't 0152 /// compute MD5 for on-disk files because we hope that modification time is 0153 /// enough to tell if the file was changed. 0154 llvm::MD5::MD5Result MD5 = {}; 0155 0156 static PreambleFileHash createForFile(off_t Size, time_t ModTime); 0157 static PreambleFileHash 0158 createForMemoryBuffer(const llvm::MemoryBufferRef &Buffer); 0159 0160 friend bool operator==(const PreambleFileHash &LHS, 0161 const PreambleFileHash &RHS) { 0162 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime && 0163 LHS.MD5 == RHS.MD5; 0164 } 0165 friend bool operator!=(const PreambleFileHash &LHS, 0166 const PreambleFileHash &RHS) { 0167 return !(LHS == RHS); 0168 } 0169 }; 0170 0171 /// Helper function to set up PCH for the preamble into \p CI and \p VFS to 0172 /// with the specified \p Bounds. 0173 void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI, 0174 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 0175 llvm::MemoryBuffer *MainFileBuffer) const; 0176 0177 /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p 0178 /// Storage is accessible to clang. This method is an implementation detail of 0179 /// AddImplicitPreamble. 0180 static void 0181 setupPreambleStorage(const PCHStorage &Storage, 0182 PreprocessorOptions &PreprocessorOpts, 0183 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS); 0184 0185 /// Manages the memory buffer or temporary file that stores the PCH. 0186 std::unique_ptr<PCHStorage> Storage; 0187 /// Keeps track of the files that were used when computing the 0188 /// preamble, with both their buffer size and their modification time. 0189 /// 0190 /// If any of the files have changed from one compile to the next, 0191 /// the preamble must be thrown away. 0192 llvm::StringMap<PreambleFileHash> FilesInPreamble; 0193 /// Files that were not found during preamble building. If any of these now 0194 /// exist then the preamble should not be reused. 0195 /// 0196 /// Storing *all* the missing files that could invalidate the preamble would 0197 /// make it too expensive to revalidate (when the include path has many 0198 /// entries, each #include will miss half of them on average). 0199 /// Instead, we track only files that could have satisfied an #include that 0200 /// was ultimately not found. 0201 llvm::StringSet<> MissingFiles; 0202 /// The contents of the file that was used to precompile the preamble. Only 0203 /// contains first PreambleBounds::Size bytes. Used to compare if the relevant 0204 /// part of the file has not changed, so that preamble can be reused. 0205 std::vector<char> PreambleBytes; 0206 /// See PreambleBounds::PreambleEndsAtStartOfLine 0207 bool PreambleEndsAtStartOfLine; 0208 }; 0209 0210 /// A set of callbacks to gather useful information while building a preamble. 0211 class PreambleCallbacks { 0212 public: 0213 virtual ~PreambleCallbacks() = default; 0214 0215 /// Called before FrontendAction::Execute. 0216 /// Can be used to store references to various CompilerInstance fields 0217 /// (e.g. SourceManager) that may be interesting to the consumers of other 0218 /// callbacks. 0219 virtual void BeforeExecute(CompilerInstance &CI); 0220 /// Called after FrontendAction::Execute(), but before 0221 /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of 0222 /// various CompilerInstance fields before they are destroyed. 0223 virtual void AfterExecute(CompilerInstance &CI); 0224 /// Called after PCH has been emitted. \p Writer may be used to retrieve 0225 /// information about AST, serialized in PCH. 0226 virtual void AfterPCHEmitted(ASTWriter &Writer); 0227 /// Called for each TopLevelDecl. 0228 /// NOTE: To allow more flexibility a custom ASTConsumer could probably be 0229 /// used instead, but having only this method allows a simpler API. 0230 virtual void HandleTopLevelDecl(DeclGroupRef DG); 0231 /// Creates wrapper class for PPCallbacks so we can also process information 0232 /// about includes that are inside of a preamble. Called after BeforeExecute. 0233 virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); 0234 /// The returned CommentHandler will be added to the preprocessor if not null. 0235 virtual CommentHandler *getCommentHandler(); 0236 /// Determines which function bodies are parsed, by default skips everything. 0237 /// Only used if FrontendOpts::SkipFunctionBodies is true. 0238 /// See ASTConsumer::shouldSkipFunctionBody. 0239 virtual bool shouldSkipFunctionBody(Decl *D) { return true; } 0240 }; 0241 0242 enum class BuildPreambleError { 0243 CouldntCreateTempFile = 1, 0244 CouldntCreateTargetInfo, 0245 BeginSourceFileFailed, 0246 CouldntEmitPCH, 0247 BadInputs 0248 }; 0249 0250 class BuildPreambleErrorCategory final : public std::error_category { 0251 public: 0252 const char *name() const noexcept override; 0253 std::string message(int condition) const override; 0254 }; 0255 0256 std::error_code make_error_code(BuildPreambleError Error); 0257 } // namespace clang 0258 0259 template <> 0260 struct std::is_error_code_enum<clang::BuildPreambleError> : std::true_type {}; 0261 0262 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|