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