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