clang-tools 23.0.0git
Preamble.h
Go to the documentation of this file.
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 "ModulesBuilder.h"
31
32#include "clang-include-cleaner/Record.h"
33#include "support/Path.h"
34#include "clang/Basic/SourceManager.h"
35#include "clang/Basic/TargetOptions.h"
36#include "clang/Frontend/CompilerInvocation.h"
37#include "clang/Frontend/PrecompiledPreamble.h"
38#include "clang/Lex/Lexer.h"
39#include "clang/Serialization/ModuleCache.h"
40#include "clang/Tooling/CompilationDatabase.h"
41#include "llvm/ADT/ArrayRef.h"
42#include "llvm/ADT/StringRef.h"
43
44#include <cstddef>
45#include <functional>
46#include <memory>
47#include <string>
48#include <utility>
49#include <vector>
50
51namespace clang {
52namespace clangd {
53
54/// The captured AST context.
55/// Keeps necessary structs for an ASTContext and Preprocessor alive.
56/// This enables consuming them after context that produced the AST is gone.
57/// (e.g. indexing a preamble ast on a separate thread). ASTContext stored
58/// inside is still not thread-safe.
59
61public:
62 CapturedASTCtx(CompilerInstance &Clang)
63 : ModCache(Clang.getModuleCachePtr()),
64 Invocation(Clang.getInvocationPtr()),
65 Diagnostics(Clang.getDiagnosticsPtr()), Target(Clang.getTargetPtr()),
66 AuxTarget(Clang.getAuxTarget()), FileMgr(Clang.getFileManagerPtr()),
67 SourceMgr(Clang.getSourceManagerPtr()), PP(Clang.getPreprocessorPtr()),
68 Context(Clang.getASTContextPtr()) {}
69
70 CapturedASTCtx(const CapturedASTCtx &) = delete;
74
75 ASTContext &getASTContext() { return *Context; }
76 Preprocessor &getPreprocessor() { return *PP; }
77 CompilerInvocation &getCompilerInvocation() { return *Invocation; }
78 FileManager &getFileManager() { return *FileMgr; }
79 void setStatCache(std::shared_ptr<PreambleFileStatusCache> StatCache) {
80 this->StatCache = StatCache;
81 }
82
83private:
84 std::shared_ptr<ModuleCache> ModCache;
85 std::shared_ptr<CompilerInvocation> Invocation;
86 IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
87 IntrusiveRefCntPtr<TargetInfo> Target;
88 IntrusiveRefCntPtr<TargetInfo> AuxTarget;
89 IntrusiveRefCntPtr<FileManager> FileMgr;
90 IntrusiveRefCntPtr<SourceManager> SourceMgr;
91 std::shared_ptr<Preprocessor> PP;
92 IntrusiveRefCntPtr<ASTContext> Context;
93 std::shared_ptr<PreambleFileStatusCache> StatCache;
94};
95
96/// The parsed preamble and associated data.
97///
98/// As we must avoid re-parsing the preamble, any information that can only
99/// be obtained during parsing must be eagerly captured and stored here.
101 PreambleData(PrecompiledPreamble Preamble) : Preamble(std::move(Preamble)) {}
102
103 // Version of the ParseInputs this preamble was built from.
104 std::string Version;
105 tooling::CompileCommand CompileCommand;
106 // Target options used when building the preamble. Changes in target can cause
107 // crashes when deserializing preamble, this enables consumers to use the
108 // same target (without reparsing CompileCommand).
109 std::unique_ptr<TargetOptions> TargetOpts = nullptr;
110 PrecompiledPreamble Preamble;
111 std::vector<Diag> Diags;
112 // Processes like code completions and go-to-definitions will need #include
113 // information, and their compile action skips preamble range.
115 // Captures #include-mapping information in #included headers.
116 std::shared_ptr<const include_cleaner::PragmaIncludes> Pragmas;
117 // Information about required module files for this preamble.
118 std::unique_ptr<PrerequisiteModules> RequiredModules;
119 // Macros defined in the preamble section of the main file.
120 // Users care about headers vs main-file, not preamble vs non-preamble.
121 // These should be treated as main-file entities e.g. for code completion.
123 // Pragma marks defined in the preamble section of the main file.
124 std::vector<PragmaMark> Marks;
125 // Cache of FS operations performed when building the preamble.
126 // When reusing a preamble, this cache can be consumed to save IO.
127 std::shared_ptr<PreambleFileStatusCache> StatCache;
128 // Whether there was a (possibly-incomplete) include-guard on the main file.
129 // We need to propagate this information "by hand" to subsequent parses.
131};
132
134 std::function<void(CapturedASTCtx ASTCtx,
135 std::shared_ptr<const include_cleaner::PragmaIncludes>)>;
136
137/// Timings and statistics from the premble build. Unlike PreambleData, these
138/// do not need to be stored for later, but can be useful for logging, metrics,
139/// etc.
141 /// Total wall time it took to build preamble, in seconds.
143 /// Time spent in filesystem operations during the build, in seconds.
145
146 /// Estimate of the memory used while building the preamble.
147 /// This memory has been released when buildPreamble returns.
148 /// For example, this includes the size of the in-memory AST (ASTContext).
149 size_t BuildSize;
150 /// The serialized size of the preamble.
151 /// This storage is needed while the preamble is used (but may be on disk).
153};
154
155/// Build a preamble for the new inputs unless an old one can be reused.
156/// If \p PreambleCallback is set, it will be run on top of the AST while
157/// building the preamble.
158/// If Stats is not non-null, build statistics will be exported there.
159std::shared_ptr<const PreambleData>
160buildPreamble(PathRef FileName, CompilerInvocation CI,
161 const ParseInputs &Inputs, bool StoreInMemory,
162 PreambleParsedCallback PreambleCallback,
163 PreambleBuildStats *Stats = nullptr);
164
165/// Returns true if \p Preamble is reusable for \p Inputs. Note that it will
166/// return true when some missing headers are now available.
167/// FIXME: Should return more information about the delta between \p Preamble
168/// and \p Inputs, e.g. new headers.
170 const ParseInputs &Inputs, PathRef FileName,
171 const CompilerInvocation &CI);
172
173/// Stores information required to parse a TU using a (possibly stale) Baseline
174/// preamble. Later on this information can be injected into the main file by
175/// updating compiler invocation with \c apply. This injected section
176/// approximately reflects additions to the preamble in Modified contents, e.g.
177/// new include directives.
178class PreamblePatch {
179public:
181 /// \p Preamble is used verbatim.
183 /// Builds a patch that contains new PP directives introduced to the preamble
184 /// section of \p Modified compared to \p Baseline.
185 /// FIXME: This only handles include directives, we should at least handle
186 /// define/undef.
187 static PreamblePatch createFullPatch(llvm::StringRef FileName,
188 const ParseInputs &Modified,
189 const PreambleData &Baseline);
190 static PreamblePatch createMacroPatch(llvm::StringRef FileName,
191 const ParseInputs &Modified,
192 const PreambleData &Baseline);
193 /// Returns the FileEntry for the preamble patch of MainFilePath in SM, if
194 /// any.
195 static OptionalFileEntryRef getPatchEntry(llvm::StringRef MainFilePath,
196 const SourceManager &SM);
197
198 /// Adjusts CI (which compiles the modified inputs) to be used with the
199 /// baseline preamble. This is done by inserting an artificial include to the
200 /// \p CI that contains new directives calculated in create.
201 void apply(CompilerInvocation &CI) const;
202
203 /// Returns #include directives from the \c Modified preamble that were
204 /// resolved using the \c Baseline preamble. This covers the new locations of
205 /// inclusions that were moved around, but not inclusions of new files. Those
206 /// will be recorded when parsing the main file: the includes in the injected
207 /// section will be resolved back to their spelled positions in the main file
208 /// using the presumed-location mechanism.
209 std::vector<Inclusion> preambleIncludes() const;
210
211 /// Returns preamble bounds for the Modified.
212 PreambleBounds modifiedBounds() const { return ModifiedBounds; }
213
214 /// Returns textual patch contents.
215 llvm::StringRef text() const { return PatchContents; }
216
217 /// Returns diag locations for Modified contents.
218 llvm::ArrayRef<Diag> patchedDiags() const { return PatchedDiags; }
219
220 static constexpr llvm::StringLiteral HeaderName = "__preamble_patch__.h";
221
222 llvm::ArrayRef<PragmaMark> marks() const;
223 const MainFileMacros &mainFileMacros() const;
224
225private:
226 static PreamblePatch create(llvm::StringRef FileName,
227 const ParseInputs &Modified,
228 const PreambleData &Baseline,
230
231 PreamblePatch() = default;
232 std::string PatchContents;
233 std::string PatchFileName;
234 // Includes that are present in both Baseline and Modified. Used for
235 // patching includes of baseline preamble.
236 std::vector<Inclusion> PreambleIncludes;
237 // Diags that were attached to a line preserved in Modified contents.
238 std::vector<Diag> PatchedDiags;
239 PreambleBounds ModifiedBounds = {0, false};
240 const PreambleData *Baseline = nullptr;
241 std::vector<PragmaMark> PatchedMarks;
242 MainFileMacros PatchedMacros;
243};
244
245PreambleBounds computePreambleBounds(const LangOptions &LangOpts,
246 const llvm::MemoryBufferRef &Buffer,
247 bool SkipPreambleBuild);
248
249} // namespace clangd
250} // namespace clang
251
252#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition Context.h:69
Stores information required to parse a TU using a (possibly stale) Baseline preamble.
Definition Preamble.h:178
static OptionalFileEntryRef getPatchEntry(llvm::StringRef MainFilePath, const SourceManager &SM)
Returns the FileEntry for the preamble patch of MainFilePath in SM, if any.
Definition Preamble.cpp:961
const MainFileMacros & mainFileMacros() const
Definition Preamble.cpp:955
llvm::ArrayRef< PragmaMark > marks() const
Definition Preamble.cpp:949
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition Preamble.cpp:912
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition Preamble.cpp:940
llvm::ArrayRef< Diag > patchedDiags() const
Returns diag locations for Modified contents.
Definition Preamble.h:218
llvm::StringRef text() const
Returns textual patch contents.
Definition Preamble.h:215
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition Preamble.cpp:906
static PreamblePatch createFullPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Builds a patch that contains new PP directives introduced to the preamble section of Modified compare...
Definition Preamble.cpp:900
static constexpr llvm::StringLiteral HeaderName
Definition Preamble.h:220
std::vector< Inclusion > preambleIncludes() const
Returns include directives from the Modified preamble that were resolved using the Baseline preamble.
Definition Preamble.cpp:936
PreambleBounds modifiedBounds() const
Returns preamble bounds for the Modified.
Definition Preamble.h:212
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:44
bool isPreambleCompatible(const PreambleData &Preamble, const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI)
Returns true if Preamble is reusable for Inputs.
Definition Preamble.cpp:723
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
Definition Preamble.cpp:573
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition Path.h:29
std::function< void(CapturedASTCtx ASTCtx, std::shared_ptr< const include_cleaner::PragmaIncludes >)> PreambleParsedCallback
Definition Preamble.h:133
PreambleBounds computePreambleBounds(const LangOptions &LangOpts, const llvm::MemoryBufferRef &Buffer, bool SkipPreambleBuild)
Definition Preamble.cpp:967
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
The captured AST context.
Definition Preamble.h:60
CapturedASTCtx & operator=(CapturedASTCtx &&)=default
CapturedASTCtx & operator=(const CapturedASTCtx &)=delete
CapturedASTCtx(const CapturedASTCtx &)=delete
void setStatCache(std::shared_ptr< PreambleFileStatusCache > StatCache)
Definition Preamble.h:79
CapturedASTCtx(CompilerInstance &Clang)
Definition Preamble.h:62
CapturedASTCtx(CapturedASTCtx &&)=default
CompilerInvocation & getCompilerInvocation()
Definition Preamble.h:77
Preprocessor & getPreprocessor()
Definition Preamble.h:76
FileManager & getFileManager()
Definition Preamble.h:78
ASTContext & getASTContext()
Definition Preamble.h:75
Information required to run clang, e.g. to parse AST or do code completion.
Definition Compiler.h:51
Timings and statistics from the premble build.
Definition Preamble.h:140
double FileSystemTime
Time spent in filesystem operations during the build, in seconds.
Definition Preamble.h:144
size_t BuildSize
Estimate of the memory used while building the preamble.
Definition Preamble.h:149
double TotalBuildTime
Total wall time it took to build preamble, in seconds.
Definition Preamble.h:142
size_t SerializedSize
The serialized size of the preamble.
Definition Preamble.h:152
The parsed preamble and associated data.
Definition Preamble.h:100
std::unique_ptr< TargetOptions > TargetOpts
Definition Preamble.h:109
std::vector< Diag > Diags
Definition Preamble.h:111
std::vector< PragmaMark > Marks
Definition Preamble.h:124
PrecompiledPreamble Preamble
Definition Preamble.h:110
std::unique_ptr< PrerequisiteModules > RequiredModules
Definition Preamble.h:118
std::shared_ptr< const include_cleaner::PragmaIncludes > Pragmas
Definition Preamble.h:116
PreambleData(PrecompiledPreamble Preamble)
Definition Preamble.h:101
std::shared_ptr< PreambleFileStatusCache > StatCache
Definition Preamble.h:127
tooling::CompileCommand CompileCommand
Definition Preamble.h:105
IncludeStructure Includes
Definition Preamble.h:114