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