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