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 & Writer,ASTWriter::RecordDataImpl & Record)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. ASTRecordWriter(ASTRecordWriter & Parent,ASTWriter::RecordDataImpl & Record)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. getRecordData()71 ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } 72 73 /// Minimal vector-like interface. 74 /// @{ push_back(uint64_t N)75 void push_back(uint64_t N) { Record->push_back(N); } 76 template<typename InputIterator> append(InputIterator begin,InputIterator end)77 void append(InputIterator begin, InputIterator end) { 78 Record->append(begin, end); 79 } empty()80 bool empty() const { return Record->empty(); } size()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. AddOffset(uint64_t BitOffset)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. AddStmt(Stmt * S)118 void AddStmt(Stmt *S) { 119 StmtsToEmit.push_back(S); 120 } writeStmtRef(const Stmt * S)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. AddSourceLocation(SourceLocation Loc)130 void AddSourceLocation(SourceLocation Loc) { 131 return Writer->AddSourceLocation(Loc, *Record); 132 } writeSourceLocation(SourceLocation Loc)133 void writeSourceLocation(SourceLocation Loc) { 134 AddSourceLocation(Loc); 135 } 136 137 /// Emit a source range. AddSourceRange(SourceRange Range)138 void AddSourceRange(SourceRange Range) { 139 return Writer->AddSourceRange(Range, *Record); 140 } 141 writeBool(bool Value)142 void writeBool(bool Value) { 143 Record->push_back(Value); 144 } 145 writeUInt32(uint32_t Value)146 void writeUInt32(uint32_t Value) { 147 Record->push_back(Value); 148 } 149 writeUInt64(uint64_t Value)150 void writeUInt64(uint64_t Value) { 151 Record->push_back(Value); 152 } 153 154 /// Emit an integral value. AddAPInt(const llvm::APInt & Value)155 void AddAPInt(const llvm::APInt &Value) { 156 writeAPInt(Value); 157 } 158 159 /// Emit a signed integral value. AddAPSInt(const llvm::APSInt & 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. AddIdentifierRef(const IdentifierInfo * II)171 void AddIdentifierRef(const IdentifierInfo *II) { 172 return Writer->AddIdentifierRef(II, *Record); 173 } writeIdentifier(const IdentifierInfo * II)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); writeSelector(Selector sel)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. AddTypeRef(QualType T)194 void AddTypeRef(QualType T) { 195 return Writer->AddTypeRef(T, *Record); 196 } writeQualType(QualType T)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. AddDeclRef(const Decl * D)219 void AddDeclRef(const Decl *D) { 220 return Writer->AddDeclRef(D, *Record); 221 } writeDeclRef(const Decl * D)222 void writeDeclRef(const Decl *D) { 223 AddDeclRef(D); 224 } 225 226 /// Emit a declaration name. AddDeclarationName(DeclarationName 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. AddNestedNameSpecifier(NestedNameSpecifier * NNS)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. AddTemplateName(TemplateName Name)246 void AddTemplateName(TemplateName Name) { 247 writeTemplateName(Name); 248 } 249 250 /// Emit a template argument. AddTemplateArgument(const TemplateArgument & Arg)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 /// Emit information about the initializer of a VarDecl. 270 void AddVarDeclInit(const VarDecl *VD); 271 272 /// Write an OMPTraitInfo object. 273 void writeOMPTraitInfo(const OMPTraitInfo *TI); 274 275 void writeOMPClause(OMPClause *C); 276 277 /// Writes data related to the OpenMP directives. 278 void writeOMPChildren(OMPChildren *Data); 279 280 /// Emit a string. AddString(StringRef Str)281 void AddString(StringRef Str) { 282 return Writer->AddString(Str, *Record); 283 } 284 285 /// Emit a path. AddPath(StringRef Path)286 void AddPath(StringRef Path) { 287 return Writer->AddPath(Path, *Record); 288 } 289 290 /// Emit a version tuple. AddVersionTuple(const VersionTuple & Version)291 void AddVersionTuple(const VersionTuple &Version) { 292 return Writer->AddVersionTuple(Version, *Record); 293 } 294 295 // Emit an attribute. 296 void AddAttr(const Attr *A); 297 298 /// Emit a list of attributes. 299 void AddAttributes(ArrayRef<const Attr*> Attrs); 300 }; 301 302 } // end namespace clang 303 304 #endif 305