1 //===--- Preamble.h - Reusing expensive parts of the AST ---------*- 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 // The vast majority of code in a typical translation unit is in the headers 10 // included at the top of the file. 11 // 12 // The preamble optimization says that we can parse this code once, and reuse 13 // the result multiple times. The preamble is invalidated by changes to the 14 // code in the preamble region, to the compile command, or to files on disk. 15 // 16 // This is the most important optimization in clangd: it allows operations like 17 // code-completion to have sub-second latency. It is supported by the 18 // PrecompiledPreamble functionality in clang, which wraps the techniques used 19 // by PCH files, modules etc into a convenient interface. 20 // 21 //===----------------------------------------------------------------------===// 22 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H 23 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H 24 25 #include "CollectMacros.h" 26 #include "Compiler.h" 27 #include "Diagnostics.h" 28 #include "FS.h" 29 #include "Headers.h" 30 #include "index/CanonicalIncludes.h" 31 #include "support/Path.h" 32 #include "clang/Frontend/CompilerInvocation.h" 33 #include "clang/Frontend/PrecompiledPreamble.h" 34 #include "clang/Lex/Lexer.h" 35 #include "clang/Tooling/CompilationDatabase.h" 36 #include "llvm/ADT/StringRef.h" 37 38 #include <memory> 39 #include <string> 40 #include <vector> 41 42 namespace clang { 43 namespace clangd { 44 45 /// The parsed preamble and associated data. 46 /// 47 /// As we must avoid re-parsing the preamble, any information that can only 48 /// be obtained during parsing must be eagerly captured and stored here. 49 struct PreambleData { PreambleDataPreambleData50 PreambleData(PrecompiledPreamble Preamble) : Preamble(std::move(Preamble)) {} 51 52 // Version of the ParseInputs this preamble was built from. 53 std::string Version; 54 tooling::CompileCommand CompileCommand; 55 PrecompiledPreamble Preamble; 56 std::vector<Diag> Diags; 57 // Processes like code completions and go-to-definitions will need #include 58 // information, and their compile action skips preamble range. 59 IncludeStructure Includes; 60 // Macros defined in the preamble section of the main file. 61 // Users care about headers vs main-file, not preamble vs non-preamble. 62 // These should be treated as main-file entities e.g. for code completion. 63 MainFileMacros Macros; 64 // Pragma marks defined in the preamble section of the main file. 65 std::vector<PragmaMark> Marks; 66 // Cache of FS operations performed when building the preamble. 67 // When reusing a preamble, this cache can be consumed to save IO. 68 std::unique_ptr<PreambleFileStatusCache> StatCache; 69 CanonicalIncludes CanonIncludes; 70 // Whether there was a (possibly-incomplete) include-guard on the main file. 71 // We need to propagate this information "by hand" to subsequent parses. 72 bool MainIsIncludeGuarded = false; 73 }; 74 75 using PreambleParsedCallback = std::function<void(ASTContext &, Preprocessor &, 76 const CanonicalIncludes &)>; 77 78 /// Timings and statistics from the premble build. Unlike PreambleData, these 79 /// do not need to be stored for later, but can be useful for logging, metrics, 80 /// etc. 81 struct PreambleBuildStats { 82 /// Total wall time it took to build preamble, in seconds. 83 double TotalBuildTime; 84 /// Time spent in filesystem operations during the build, in seconds. 85 double FileSystemTime; 86 87 /// Estimate of the memory used while building the preamble. 88 /// This memory has been released when buildPreamble returns. 89 /// For example, this includes the size of the in-memory AST (ASTContext). 90 size_t BuildSize; 91 /// The serialized size of the preamble. 92 /// This storage is needed while the preamble is used (but may be on disk). 93 size_t SerializedSize; 94 }; 95 96 /// Build a preamble for the new inputs unless an old one can be reused. 97 /// If \p PreambleCallback is set, it will be run on top of the AST while 98 /// building the preamble. 99 /// If Stats is not non-null, build statistics will be exported there. 100 std::shared_ptr<const PreambleData> 101 buildPreamble(PathRef FileName, CompilerInvocation CI, 102 const ParseInputs &Inputs, bool StoreInMemory, 103 PreambleParsedCallback PreambleCallback, 104 PreambleBuildStats *Stats = nullptr); 105 106 /// Returns true if \p Preamble is reusable for \p Inputs. Note that it will 107 /// return true when some missing headers are now available. 108 /// FIXME: Should return more information about the delta between \p Preamble 109 /// and \p Inputs, e.g. new headers. 110 bool isPreambleCompatible(const PreambleData &Preamble, 111 const ParseInputs &Inputs, PathRef FileName, 112 const CompilerInvocation &CI); 113 114 /// Stores information required to parse a TU using a (possibly stale) Baseline 115 /// preamble. Later on this information can be injected into the main file by 116 /// updating compiler invocation with \c apply. This injected section 117 /// approximately reflects additions to the preamble in Modified contents, e.g. 118 /// new include directives. 119 class PreamblePatch { 120 public: 121 enum class PatchType { MacroDirectives, All }; 122 /// \p Preamble is used verbatim. 123 static PreamblePatch unmodified(const PreambleData &Preamble); 124 /// Builds a patch that contains new PP directives introduced to the preamble 125 /// section of \p Modified compared to \p Baseline. 126 /// FIXME: This only handles include directives, we should at least handle 127 /// define/undef. 128 static PreamblePatch createFullPatch(llvm::StringRef FileName, 129 const ParseInputs &Modified, 130 const PreambleData &Baseline); 131 static PreamblePatch createMacroPatch(llvm::StringRef FileName, 132 const ParseInputs &Modified, 133 const PreambleData &Baseline); 134 135 /// Adjusts CI (which compiles the modified inputs) to be used with the 136 /// baseline preamble. This is done by inserting an artifical include to the 137 /// \p CI that contains new directives calculated in create. 138 void apply(CompilerInvocation &CI) const; 139 140 /// Returns #include directives from the \c Modified preamble that were 141 /// resolved using the \c Baseline preamble. This covers the new locations of 142 /// inclusions that were moved around, but not inclusions of new files. Those 143 /// will be recorded when parsing the main file: the includes in the injected 144 /// section will be resolved back to their spelled positions in the main file 145 /// using the presumed-location mechanism. 146 std::vector<Inclusion> preambleIncludes() const; 147 148 /// Returns preamble bounds for the Modified. modifiedBounds()149 PreambleBounds modifiedBounds() const { return ModifiedBounds; } 150 151 /// Returns textual patch contents. text()152 llvm::StringRef text() const { return PatchContents; } 153 154 /// Whether diagnostics generated using this patch are trustable. preserveDiagnostics()155 bool preserveDiagnostics() const { return PatchContents.empty(); } 156 157 private: 158 static PreamblePatch create(llvm::StringRef FileName, 159 const ParseInputs &Modified, 160 const PreambleData &Baseline, 161 PatchType PatchType); 162 163 PreamblePatch() = default; 164 std::string PatchContents; 165 std::string PatchFileName; 166 /// Includes that are present in both \p Baseline and \p Modified. Used for 167 /// patching includes of baseline preamble. 168 std::vector<Inclusion> PreambleIncludes; 169 PreambleBounds ModifiedBounds = {0, false}; 170 }; 171 172 /// Translates locations inside preamble patch to their main-file equivalent 173 /// using presumed locations. Returns \p Loc if it isn't inside preamble patch. 174 SourceLocation translatePreamblePatchLocation(SourceLocation Loc, 175 const SourceManager &SM); 176 177 } // namespace clangd 178 } // namespace clang 179 180 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H 181