1 | //===- ASTRecordWriter.h - Helper classes for writing 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 | // This file defines the ASTRecordWriter class, a helper class useful |
10 | // when serializing AST. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H |
15 | #define LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H |
16 | |
17 | #include "clang/AST/AbstractBasicWriter.h" |
18 | #include "clang/AST/OpenMPClause.h" |
19 | #include "clang/Serialization/ASTWriter.h" |
20 | #include "clang/Serialization/SourceLocationEncoding.h" |
21 | |
22 | namespace clang { |
23 | |
24 | class OpenACCClause; |
25 | class TypeLoc; |
26 | |
27 | /// An object for streaming information to a record. |
28 | class ASTRecordWriter |
29 | : public serialization::DataStreamBasicWriter<ASTRecordWriter> { |
30 | using LocSeq = SourceLocationSequence; |
31 | |
32 | ASTWriter *Writer; |
33 | ASTWriter::RecordDataImpl *Record; |
34 | |
35 | /// Statements that we've encountered while serializing a |
36 | /// declaration or type. |
37 | SmallVector<Stmt *, 16> StmtsToEmit; |
38 | |
39 | /// Indices of record elements that describe offsets within the |
40 | /// bitcode. These will be converted to offsets relative to the current |
41 | /// record when emitted. |
42 | SmallVector<unsigned, 8> OffsetIndices; |
43 | |
44 | /// Flush all of the statements and expressions that have |
45 | /// been added to the queue via AddStmt(). |
46 | void FlushStmts(); |
47 | void FlushSubStmts(); |
48 | |
49 | void PrepareToEmit(uint64_t MyOffset) { |
50 | // Convert offsets into relative form. |
51 | for (unsigned I : OffsetIndices) { |
52 | auto &StoredOffset = (*Record)[I]; |
53 | assert(StoredOffset < MyOffset && "invalid offset" ); |
54 | if (StoredOffset) |
55 | StoredOffset = MyOffset - StoredOffset; |
56 | } |
57 | OffsetIndices.clear(); |
58 | } |
59 | |
60 | public: |
61 | /// Construct a ASTRecordWriter that uses the default encoding scheme. |
62 | ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record) |
63 | : DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {} |
64 | |
65 | /// Construct a ASTRecordWriter that uses the same encoding scheme as another |
66 | /// ASTRecordWriter. |
67 | ASTRecordWriter(ASTRecordWriter &Parent, ASTWriter::RecordDataImpl &Record) |
68 | : DataStreamBasicWriter(Parent.getASTContext()), Writer(Parent.Writer), |
69 | Record(&Record) {} |
70 | |
71 | /// Copying an ASTRecordWriter is almost certainly a bug. |
72 | ASTRecordWriter(const ASTRecordWriter &) = delete; |
73 | ASTRecordWriter &operator=(const ASTRecordWriter &) = delete; |
74 | |
75 | /// Extract the underlying record storage. |
76 | ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } |
77 | |
78 | /// Minimal vector-like interface. |
79 | /// @{ |
80 | void push_back(uint64_t N) { Record->push_back(Elt: N); } |
81 | template<typename InputIterator> |
82 | void append(InputIterator begin, InputIterator end) { |
83 | Record->append(begin, end); |
84 | } |
85 | bool empty() const { return Record->empty(); } |
86 | size_t size() const { return Record->size(); } |
87 | uint64_t &operator[](size_t N) { return (*Record)[N]; } |
88 | /// @} |
89 | |
90 | /// Emit the record to the stream, followed by its substatements, and |
91 | /// return its offset. |
92 | // FIXME: Allow record producers to suggest Abbrevs. |
93 | uint64_t Emit(unsigned Code, unsigned Abbrev = 0) { |
94 | uint64_t Offset = Writer->Stream.GetCurrentBitNo(); |
95 | PrepareToEmit(MyOffset: Offset); |
96 | Writer->Stream.EmitRecord(Code, Vals: *Record, Abbrev); |
97 | FlushStmts(); |
98 | return Offset; |
99 | } |
100 | |
101 | /// Emit the record to the stream, preceded by its substatements. |
102 | uint64_t EmitStmt(unsigned Code, unsigned Abbrev = 0) { |
103 | FlushSubStmts(); |
104 | PrepareToEmit(MyOffset: Writer->Stream.GetCurrentBitNo()); |
105 | Writer->Stream.EmitRecord(Code, Vals: *Record, Abbrev); |
106 | return Writer->Stream.GetCurrentBitNo(); |
107 | } |
108 | |
109 | /// Add a bit offset into the record. This will be converted into an |
110 | /// offset relative to the current record when emitted. |
111 | void AddOffset(uint64_t BitOffset) { |
112 | OffsetIndices.push_back(Elt: Record->size()); |
113 | Record->push_back(Elt: BitOffset); |
114 | } |
115 | |
116 | /// Add the given statement or expression to the queue of |
117 | /// statements to emit. |
118 | /// |
119 | /// This routine should be used when emitting types and declarations |
120 | /// that have expressions as part of their formulation. Once the |
121 | /// type or declaration has been written, Emit() will write |
122 | /// the corresponding statements just after the record. |
123 | void AddStmt(Stmt *S) { |
124 | StmtsToEmit.push_back(Elt: S); |
125 | } |
126 | void writeStmtRef(const Stmt *S) { |
127 | AddStmt(S: const_cast<Stmt*>(S)); |
128 | } |
129 | |
130 | /// Write an BTFTypeTagAttr object. |
131 | void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); } |
132 | |
133 | /// Add a definition for the given function to the queue of statements |
134 | /// to emit. |
135 | void AddFunctionDefinition(const FunctionDecl *FD); |
136 | |
137 | /// Emit a source location. |
138 | void AddSourceLocation(SourceLocation Loc, LocSeq *Seq = nullptr) { |
139 | return Writer->AddSourceLocation(Loc, Record&: *Record, Seq); |
140 | } |
141 | void writeSourceLocation(SourceLocation Loc) { |
142 | AddSourceLocation(Loc); |
143 | } |
144 | |
145 | void writeTypeCoupledDeclRefInfo(TypeCoupledDeclRefInfo Info) { |
146 | writeDeclRef(Info.getDecl()); |
147 | writeBool(Value: Info.isDeref()); |
148 | } |
149 | |
150 | /// Emit a source range. |
151 | void AddSourceRange(SourceRange Range, LocSeq *Seq = nullptr) { |
152 | return Writer->AddSourceRange(Range, Record&: *Record, Seq); |
153 | } |
154 | |
155 | void writeBool(bool Value) { |
156 | Record->push_back(Elt: Value); |
157 | } |
158 | |
159 | void writeUInt32(uint32_t Value) { |
160 | Record->push_back(Elt: Value); |
161 | } |
162 | |
163 | void writeUInt64(uint64_t Value) { |
164 | Record->push_back(Elt: Value); |
165 | } |
166 | |
167 | /// Emit an integral value. |
168 | void AddAPInt(const llvm::APInt &Value) { |
169 | writeAPInt(Value); |
170 | } |
171 | |
172 | /// Emit a signed integral value. |
173 | void AddAPSInt(const llvm::APSInt &Value) { |
174 | writeAPSInt(Value); |
175 | } |
176 | |
177 | /// Emit a floating-point value. |
178 | void AddAPFloat(const llvm::APFloat &Value); |
179 | |
180 | /// Emit an APvalue. |
181 | void AddAPValue(const APValue &Value) { writeAPValue(Value); } |
182 | |
183 | /// Emit a reference to an identifier. |
184 | void AddIdentifierRef(const IdentifierInfo *II) { |
185 | return Writer->AddIdentifierRef(II, Record&: *Record); |
186 | } |
187 | void writeIdentifier(const IdentifierInfo *II) { |
188 | AddIdentifierRef(II); |
189 | } |
190 | |
191 | /// Emit a Selector (which is a smart pointer reference). |
192 | void AddSelectorRef(Selector S); |
193 | void writeSelector(Selector sel) { |
194 | AddSelectorRef(S: sel); |
195 | } |
196 | |
197 | /// Emit a CXXTemporary. |
198 | void AddCXXTemporary(const CXXTemporary *Temp); |
199 | |
200 | /// Emit a C++ base specifier. |
201 | void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base); |
202 | |
203 | /// Emit a set of C++ base specifiers. |
204 | void AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases); |
205 | |
206 | /// Emit a reference to a type. |
207 | void AddTypeRef(QualType T) { |
208 | return Writer->AddTypeRef(T, Record&: *Record); |
209 | } |
210 | void writeQualType(QualType T) { |
211 | AddTypeRef(T); |
212 | } |
213 | |
214 | /// Emits a reference to a declarator info. |
215 | void AddTypeSourceInfo(TypeSourceInfo *TInfo); |
216 | |
217 | /// Emits source location information for a type. Does not emit the type. |
218 | void AddTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr); |
219 | |
220 | /// Emits a template argument location info. |
221 | void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, |
222 | const TemplateArgumentLocInfo &Arg); |
223 | |
224 | /// Emits a template argument location. |
225 | void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg); |
226 | |
227 | /// Emits an AST template argument list info. |
228 | void AddASTTemplateArgumentListInfo( |
229 | const ASTTemplateArgumentListInfo *ASTTemplArgList); |
230 | |
231 | // Emits a concept reference. |
232 | void AddConceptReference(const ConceptReference *CR); |
233 | |
234 | /// Emit a reference to a declaration. |
235 | void AddDeclRef(const Decl *D) { |
236 | return Writer->AddDeclRef(D, Record&: *Record); |
237 | } |
238 | void writeDeclRef(const Decl *D) { |
239 | AddDeclRef(D); |
240 | } |
241 | |
242 | /// Emit a declaration name. |
243 | void AddDeclarationName(DeclarationName Name) { |
244 | writeDeclarationName(Name); |
245 | } |
246 | |
247 | void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, |
248 | DeclarationName Name); |
249 | void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo); |
250 | |
251 | void AddQualifierInfo(const QualifierInfo &Info); |
252 | |
253 | /// Emit a nested name specifier. |
254 | void AddNestedNameSpecifier(NestedNameSpecifier *NNS) { |
255 | writeNestedNameSpecifier(NNS); |
256 | } |
257 | |
258 | /// Emit a nested name specifier with source-location information. |
259 | void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); |
260 | |
261 | /// Emit a template name. |
262 | void AddTemplateName(TemplateName Name) { |
263 | writeTemplateName(Name); |
264 | } |
265 | |
266 | /// Emit a template argument. |
267 | void AddTemplateArgument(const TemplateArgument &Arg) { |
268 | writeTemplateArgument(Arg); |
269 | } |
270 | |
271 | /// Emit a template parameter list. |
272 | void AddTemplateParameterList(const TemplateParameterList *TemplateParams); |
273 | |
274 | /// Emit a template argument list. |
275 | void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs); |
276 | |
277 | /// Emit a UnresolvedSet structure. |
278 | void AddUnresolvedSet(const ASTUnresolvedSet &Set); |
279 | |
280 | /// Emit a CXXCtorInitializer array. |
281 | void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits); |
282 | |
283 | void AddCXXDefinitionData(const CXXRecordDecl *D); |
284 | |
285 | /// Emit information about the initializer of a VarDecl. |
286 | void AddVarDeclInit(const VarDecl *VD); |
287 | |
288 | /// Write an OMPTraitInfo object. |
289 | void writeOMPTraitInfo(const OMPTraitInfo *TI); |
290 | |
291 | void writeOMPClause(OMPClause *C); |
292 | |
293 | /// Writes data related to the OpenMP directives. |
294 | void writeOMPChildren(OMPChildren *Data); |
295 | |
296 | /// Writes out a single OpenACC Clause. |
297 | void writeOpenACCClause(const OpenACCClause *C); |
298 | |
299 | /// Writes out a list of OpenACC clauses. |
300 | void writeOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses); |
301 | |
302 | /// Emit a string. |
303 | void AddString(StringRef Str) { |
304 | return Writer->AddString(Str, Record&: *Record); |
305 | } |
306 | |
307 | /// Emit a path. |
308 | void AddPath(StringRef Path) { |
309 | return Writer->AddPath(Path, Record&: *Record); |
310 | } |
311 | |
312 | /// Emit a version tuple. |
313 | void AddVersionTuple(const VersionTuple &Version) { |
314 | return Writer->AddVersionTuple(Version, Record&: *Record); |
315 | } |
316 | |
317 | // Emit an attribute. |
318 | void AddAttr(const Attr *A); |
319 | |
320 | /// Emit a list of attributes. |
321 | void AddAttributes(ArrayRef<const Attr*> Attrs); |
322 | }; |
323 | |
324 | } // end namespace clang |
325 | |
326 | #endif |
327 | |