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