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/ASTReader.h" 21 #include "clang/Serialization/ASTWriter.h" 22 #include "clang/Serialization/SourceLocationEncoding.h" 23 24 namespace clang { 25 26 class OpenACCClause; 27 class TypeLoc; 28 29 /// An object for streaming information to a record. 30 class ASTRecordWriter 31 : public serialization::DataStreamBasicWriter<ASTRecordWriter> { 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(ASTContext & Context,ASTWriter & W,ASTWriter::RecordDataImpl & Record)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. ASTRecordWriter(ASTRecordWriter & Parent,ASTWriter::RecordDataImpl & Record)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. getRecordData()78 ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } 79 80 /// Minimal vector-like interface. 81 /// @{ push_back(uint64_t N)82 void push_back(uint64_t N) { Record->push_back(N); } 83 template<typename InputIterator> append(InputIterator begin,InputIterator end)84 void append(InputIterator begin, InputIterator end) { 85 Record->append(begin, end); 86 } empty()87 bool empty() const { return Record->empty(); } size()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. AddOffset(uint64_t BitOffset)113 void AddOffset(uint64_t BitOffset) { 114 OffsetIndices.push_back(Record->size()); 115 Record->push_back(BitOffset); 116 } 117 AddLookupOffsets(const LookupBlockOffsets & Offsets)118 void AddLookupOffsets(const LookupBlockOffsets &Offsets) { 119 AddOffset(Offsets.LexicalOffset); 120 AddOffset(Offsets.VisibleOffset); 121 AddOffset(Offsets.ModuleLocalOffset); 122 AddOffset(Offsets.TULocalOffset); 123 } 124 125 /// Add the given statement or expression to the queue of 126 /// statements to emit. 127 /// 128 /// This routine should be used when emitting types and declarations 129 /// that have expressions as part of their formulation. Once the 130 /// type or declaration has been written, Emit() will write 131 /// the corresponding statements just after the record. AddStmt(Stmt * S)132 void AddStmt(Stmt *S) { 133 StmtsToEmit.push_back(S); 134 } writeStmtRef(const Stmt * S)135 void writeStmtRef(const Stmt *S) { 136 AddStmt(const_cast<Stmt*>(S)); 137 } 138 writeAttr(const Attr * A)139 void writeAttr(const Attr *A) { AddAttr(A); } 140 141 /// Write an BTFTypeTagAttr object. writeBTFTypeTagAttr(const BTFTypeTagAttr * A)142 void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); } 143 144 /// Add a definition for the given function to the queue of statements 145 /// to emit. 146 void AddFunctionDefinition(const FunctionDecl *FD); 147 148 /// Emit a source location. AddSourceLocation(SourceLocation Loc)149 void AddSourceLocation(SourceLocation Loc) { 150 return Writer->AddSourceLocation(Loc, *Record); 151 } writeSourceLocation(SourceLocation Loc)152 void writeSourceLocation(SourceLocation Loc) { 153 AddSourceLocation(Loc); 154 } 155 writeTypeCoupledDeclRefInfo(TypeCoupledDeclRefInfo Info)156 void writeTypeCoupledDeclRefInfo(TypeCoupledDeclRefInfo Info) { 157 writeDeclRef(Info.getDecl()); 158 writeBool(Info.isDeref()); 159 } 160 writeHLSLSpirvOperand(SpirvOperand Op)161 void writeHLSLSpirvOperand(SpirvOperand Op) { 162 QualType ResultType; 163 llvm::APInt Value; 164 165 if (Op.isConstant() || Op.isType()) 166 ResultType = Op.getResultType(); 167 if (Op.isConstant() || Op.isLiteral()) 168 Value = Op.getValue(); 169 170 Record->push_back(Op.getKind()); 171 writeQualType(ResultType); 172 writeAPInt(Value); 173 } 174 175 /// Emit a source range. AddSourceRange(SourceRange Range)176 void AddSourceRange(SourceRange Range) { 177 return Writer->AddSourceRange(Range, *Record); 178 } 179 writeBool(bool Value)180 void writeBool(bool Value) { 181 Record->push_back(Value); 182 } 183 writeUInt32(uint32_t Value)184 void writeUInt32(uint32_t Value) { 185 Record->push_back(Value); 186 } 187 writeUInt64(uint64_t Value)188 void writeUInt64(uint64_t Value) { 189 Record->push_back(Value); 190 } 191 writeUnsignedOrNone(UnsignedOrNone Value)192 void writeUnsignedOrNone(UnsignedOrNone Value) { 193 Record->push_back(Value.toInternalRepresentation()); 194 } 195 196 /// Emit an integral value. AddAPInt(const llvm::APInt & Value)197 void AddAPInt(const llvm::APInt &Value) { 198 writeAPInt(Value); 199 } 200 201 /// Emit a signed integral value. AddAPSInt(const llvm::APSInt & Value)202 void AddAPSInt(const llvm::APSInt &Value) { 203 writeAPSInt(Value); 204 } 205 206 /// Emit a floating-point value. 207 void AddAPFloat(const llvm::APFloat &Value); 208 209 /// Emit an APvalue. AddAPValue(const APValue & Value)210 void AddAPValue(const APValue &Value) { writeAPValue(Value); } 211 212 /// Emit a reference to an identifier. AddIdentifierRef(const IdentifierInfo * II)213 void AddIdentifierRef(const IdentifierInfo *II) { 214 return Writer->AddIdentifierRef(II, *Record); 215 } writeIdentifier(const IdentifierInfo * II)216 void writeIdentifier(const IdentifierInfo *II) { 217 AddIdentifierRef(II); 218 } 219 220 /// Emit a Selector (which is a smart pointer reference). 221 void AddSelectorRef(Selector S); writeSelector(Selector sel)222 void writeSelector(Selector sel) { 223 AddSelectorRef(sel); 224 } 225 226 /// Emit a CXXTemporary. 227 void AddCXXTemporary(const CXXTemporary *Temp); 228 229 /// Emit a C++ base specifier. 230 void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base); 231 232 /// Emit a set of C++ base specifiers. 233 void AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases); 234 235 /// Emit a reference to a type. AddTypeRef(QualType T)236 void AddTypeRef(QualType T) { 237 return Writer->AddTypeRef(getASTContext(), T, *Record); 238 } writeQualType(QualType T)239 void writeQualType(QualType T) { 240 AddTypeRef(T); 241 } 242 243 /// Emits a reference to a declarator info. 244 void AddTypeSourceInfo(TypeSourceInfo *TInfo); 245 246 /// Emits source location information for a type. Does not emit the type. 247 void AddTypeLoc(TypeLoc TL); 248 249 /// Emits a template argument location info. 250 void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, 251 const TemplateArgumentLocInfo &Arg); 252 253 /// Emits a template argument location. 254 void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg); 255 256 /// Emits an AST template argument list info. 257 void AddASTTemplateArgumentListInfo( 258 const ASTTemplateArgumentListInfo *ASTTemplArgList); 259 260 // Emits a concept reference. 261 void AddConceptReference(const ConceptReference *CR); 262 263 /// Emit a reference to a declaration. AddDeclRef(const Decl * D)264 void AddDeclRef(const Decl *D) { 265 return Writer->AddDeclRef(D, *Record); 266 } writeDeclRef(const Decl * D)267 void writeDeclRef(const Decl *D) { 268 AddDeclRef(D); 269 } 270 271 /// Emit a declaration name. AddDeclarationName(DeclarationName Name)272 void AddDeclarationName(DeclarationName Name) { 273 writeDeclarationName(Name); 274 } 275 276 void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, 277 DeclarationName Name); 278 void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo); 279 280 void AddQualifierInfo(const QualifierInfo &Info); 281 282 /// Emit a nested name specifier. AddNestedNameSpecifier(NestedNameSpecifier * NNS)283 void AddNestedNameSpecifier(NestedNameSpecifier *NNS) { 284 writeNestedNameSpecifier(NNS); 285 } 286 287 /// Emit a nested name specifier with source-location information. 288 void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); 289 290 /// Emit a template name. AddTemplateName(TemplateName Name)291 void AddTemplateName(TemplateName Name) { 292 writeTemplateName(Name); 293 } 294 295 /// Emit a template argument. AddTemplateArgument(const TemplateArgument & Arg)296 void AddTemplateArgument(const TemplateArgument &Arg) { 297 writeTemplateArgument(Arg); 298 } 299 300 /// Emit a template parameter list. 301 void AddTemplateParameterList(const TemplateParameterList *TemplateParams); 302 303 /// Emit a template argument list. 304 void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs); 305 306 /// Emit a UnresolvedSet structure. 307 void AddUnresolvedSet(const ASTUnresolvedSet &Set); 308 309 /// Emit a CXXCtorInitializer array. 310 void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits); 311 312 void AddCXXDefinitionData(const CXXRecordDecl *D); 313 314 /// Emit information about the initializer of a VarDecl. 315 void AddVarDeclInit(const VarDecl *VD); 316 317 /// Write an OMPTraitInfo object. 318 void writeOMPTraitInfo(const OMPTraitInfo *TI); 319 320 void writeOMPClause(OMPClause *C); 321 322 /// Writes data related to the OpenMP directives. 323 void writeOMPChildren(OMPChildren *Data); 324 325 void writeOpenACCVarList(const OpenACCClauseWithVarList *C); 326 327 void writeOpenACCIntExprList(ArrayRef<Expr *> Exprs); 328 329 /// Writes out a single OpenACC Clause. 330 void writeOpenACCClause(const OpenACCClause *C); 331 332 /// Writes out a list of OpenACC clauses. 333 void writeOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses); 334 335 void AddOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A); 336 337 /// Emit a string. AddString(StringRef Str)338 void AddString(StringRef Str) { 339 return Writer->AddString(Str, *Record); 340 } 341 342 /// Emit a path. AddPath(StringRef Path)343 void AddPath(StringRef Path) { 344 return Writer->AddPath(Path, *Record); 345 } 346 347 /// Emit a version tuple. AddVersionTuple(const VersionTuple & Version)348 void AddVersionTuple(const VersionTuple &Version) { 349 return Writer->AddVersionTuple(Version, *Record); 350 } 351 352 // Emit an attribute. 353 void AddAttr(const Attr *A); 354 355 /// Emit a list of attributes. 356 void AddAttributes(ArrayRef<const Attr*> Attrs); 357 }; 358 359 } // end namespace clang 360 361 #endif 362