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