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