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