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 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. 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. 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. 72 ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } 73 74 /// Minimal vector-like interface. 75 /// @{ 76 void push_back(uint64_t N) { Record->push_back(N); } 77 template<typename InputIterator> 78 void append(InputIterator begin, InputIterator end) { 79 Record->append(begin, end); 80 } 81 bool empty() const { return Record->empty(); } 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. 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. 119 void AddStmt(Stmt *S) { 120 StmtsToEmit.push_back(S); 121 } 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. 131 void AddSourceLocation(SourceLocation Loc) { 132 return Writer->AddSourceLocation(Loc, *Record); 133 } 134 void writeSourceLocation(SourceLocation Loc) { 135 AddSourceLocation(Loc); 136 } 137 138 /// Emit a source range. 139 void AddSourceRange(SourceRange Range) { 140 return Writer->AddSourceRange(Range, *Record); 141 } 142 143 void writeBool(bool Value) { 144 Record->push_back(Value); 145 } 146 147 void writeUInt32(uint32_t Value) { 148 Record->push_back(Value); 149 } 150 151 void writeUInt64(uint64_t Value) { 152 Record->push_back(Value); 153 } 154 155 /// Emit an integral value. 156 void AddAPInt(const llvm::APInt &Value) { 157 writeAPInt(Value); 158 } 159 160 /// Emit a signed integral 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. 169 void AddAPValue(const APValue &Value) { writeAPValue(Value); } 170 171 /// Emit a reference to an identifier. 172 void AddIdentifierRef(const IdentifierInfo *II) { 173 return Writer->AddIdentifierRef(II, *Record); 174 } 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); 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. 195 void AddTypeRef(QualType T) { 196 return Writer->AddTypeRef(T, *Record); 197 } 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. 220 void AddDeclRef(const Decl *D) { 221 return Writer->AddDeclRef(D, *Record); 222 } 223 void writeDeclRef(const Decl *D) { 224 AddDeclRef(D); 225 } 226 227 /// Emit a declaration 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. 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. 247 void AddTemplateName(TemplateName Name) { 248 writeTemplateName(Name); 249 } 250 251 /// Emit a template argument. 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. 282 void AddString(StringRef Str) { 283 return Writer->AddString(Str, *Record); 284 } 285 286 /// Emit a path. 287 void AddPath(StringRef Path) { 288 return Writer->AddPath(Path, *Record); 289 } 290 291 /// Emit a version tuple. 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