//===- ASTRecordWriter.h - Helper classes for writing AST -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the ASTRecordWriter class, a helper class useful // when serializing AST. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H #define LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H #include "clang/AST/AbstractBasicWriter.h" #include "clang/AST/OpenMPClause.h" #include "clang/Serialization/ASTWriter.h" #include "clang/Serialization/SourceLocationEncoding.h" namespace clang { class TypeLoc; /// An object for streaming information to a record. class ASTRecordWriter : public serialization::DataStreamBasicWriter { using LocSeq = SourceLocationSequence; ASTWriter *Writer; ASTWriter::RecordDataImpl *Record; /// Statements that we've encountered while serializing a /// declaration or type. SmallVector StmtsToEmit; /// Indices of record elements that describe offsets within the /// bitcode. These will be converted to offsets relative to the current /// record when emitted. SmallVector OffsetIndices; /// Flush all of the statements and expressions that have /// been added to the queue via AddStmt(). void FlushStmts(); void FlushSubStmts(); void PrepareToEmit(uint64_t MyOffset) { // Convert offsets into relative form. for (unsigned I : OffsetIndices) { auto &StoredOffset = (*Record)[I]; assert(StoredOffset < MyOffset && "invalid offset"); if (StoredOffset) StoredOffset = MyOffset - StoredOffset; } OffsetIndices.clear(); } public: /// Construct a ASTRecordWriter that uses the default encoding scheme. ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record) : DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {} /// Construct a ASTRecordWriter that uses the same encoding scheme as another /// ASTRecordWriter. ASTRecordWriter(ASTRecordWriter &Parent, ASTWriter::RecordDataImpl &Record) : DataStreamBasicWriter(Parent.getASTContext()), Writer(Parent.Writer), Record(&Record) {} /// Copying an ASTRecordWriter is almost certainly a bug. ASTRecordWriter(const ASTRecordWriter &) = delete; ASTRecordWriter &operator=(const ASTRecordWriter &) = delete; /// Extract the underlying record storage. ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } /// Minimal vector-like interface. /// @{ void push_back(uint64_t N) { Record->push_back(N); } template void append(InputIterator begin, InputIterator end) { Record->append(begin, end); } bool empty() const { return Record->empty(); } size_t size() const { return Record->size(); } uint64_t &operator[](size_t N) { return (*Record)[N]; } /// @} /// Emit the record to the stream, followed by its substatements, and /// return its offset. // FIXME: Allow record producers to suggest Abbrevs. uint64_t Emit(unsigned Code, unsigned Abbrev = 0) { uint64_t Offset = Writer->Stream.GetCurrentBitNo(); PrepareToEmit(Offset); Writer->Stream.EmitRecord(Code, *Record, Abbrev); FlushStmts(); return Offset; } /// Emit the record to the stream, preceded by its substatements. uint64_t EmitStmt(unsigned Code, unsigned Abbrev = 0) { FlushSubStmts(); PrepareToEmit(Writer->Stream.GetCurrentBitNo()); Writer->Stream.EmitRecord(Code, *Record, Abbrev); return Writer->Stream.GetCurrentBitNo(); } /// Add a bit offset into the record. This will be converted into an /// offset relative to the current record when emitted. void AddOffset(uint64_t BitOffset) { OffsetIndices.push_back(Record->size()); Record->push_back(BitOffset); } /// Add the given statement or expression to the queue of /// statements to emit. /// /// This routine should be used when emitting types and declarations /// that have expressions as part of their formulation. Once the /// type or declaration has been written, Emit() will write /// the corresponding statements just after the record. void AddStmt(Stmt *S) { StmtsToEmit.push_back(S); } void writeStmtRef(const Stmt *S) { AddStmt(const_cast(S)); } /// Write an BTFTypeTagAttr object. void writeBTFTypeTagAttr(const BTFTypeTagAttr *A) { AddAttr(A); } /// Add a definition for the given function to the queue of statements /// to emit. void AddFunctionDefinition(const FunctionDecl *FD); /// Emit a source location. void AddSourceLocation(SourceLocation Loc, LocSeq *Seq = nullptr) { return Writer->AddSourceLocation(Loc, *Record, Seq); } void writeSourceLocation(SourceLocation Loc) { AddSourceLocation(Loc); } /// Emit a source range. void AddSourceRange(SourceRange Range, LocSeq *Seq = nullptr) { return Writer->AddSourceRange(Range, *Record, Seq); } void writeBool(bool Value) { Record->push_back(Value); } void writeUInt32(uint32_t Value) { Record->push_back(Value); } void writeUInt64(uint64_t Value) { Record->push_back(Value); } /// Emit an integral value. void AddAPInt(const llvm::APInt &Value) { writeAPInt(Value); } /// Emit a signed integral value. void AddAPSInt(const llvm::APSInt &Value) { writeAPSInt(Value); } /// Emit a floating-point value. void AddAPFloat(const llvm::APFloat &Value); /// Emit an APvalue. void AddAPValue(const APValue &Value) { writeAPValue(Value); } /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II) { return Writer->AddIdentifierRef(II, *Record); } void writeIdentifier(const IdentifierInfo *II) { AddIdentifierRef(II); } /// Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector S); void writeSelector(Selector sel) { AddSelectorRef(sel); } /// Emit a CXXTemporary. void AddCXXTemporary(const CXXTemporary *Temp); /// Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base); /// Emit a set of C++ base specifiers. void AddCXXBaseSpecifiers(ArrayRef Bases); /// Emit a reference to a type. void AddTypeRef(QualType T) { return Writer->AddTypeRef(T, *Record); } void writeQualType(QualType T) { AddTypeRef(T); } /// Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo); /// Emits source location information for a type. Does not emit the type. void AddTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr); /// Emits a template argument location info. void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg); /// Emits a template argument location. void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg); /// Emits an AST template argument list info. void AddASTTemplateArgumentListInfo( const ASTTemplateArgumentListInfo *ASTTemplArgList); // Emits a concept reference. void AddConceptReference(const ConceptReference *CR); /// Emit a reference to a declaration. void AddDeclRef(const Decl *D) { return Writer->AddDeclRef(D, *Record); } void writeDeclRef(const Decl *D) { AddDeclRef(D); } /// Emit a declaration name. void AddDeclarationName(DeclarationName Name) { writeDeclarationName(Name); } void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, DeclarationName Name); void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo); void AddQualifierInfo(const QualifierInfo &Info); /// Emit a nested name specifier. void AddNestedNameSpecifier(NestedNameSpecifier *NNS) { writeNestedNameSpecifier(NNS); } /// Emit a nested name specifier with source-location information. void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); /// Emit a template name. void AddTemplateName(TemplateName Name) { writeTemplateName(Name); } /// Emit a template argument. void AddTemplateArgument(const TemplateArgument &Arg) { writeTemplateArgument(Arg); } /// Emit a template parameter list. void AddTemplateParameterList(const TemplateParameterList *TemplateParams); /// Emit a template argument list. void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs); /// Emit a UnresolvedSet structure. void AddUnresolvedSet(const ASTUnresolvedSet &Set); /// Emit a CXXCtorInitializer array. void AddCXXCtorInitializers(ArrayRef CtorInits); void AddCXXDefinitionData(const CXXRecordDecl *D); /// Emit information about the initializer of a VarDecl. void AddVarDeclInit(const VarDecl *VD); /// Write an OMPTraitInfo object. void writeOMPTraitInfo(const OMPTraitInfo *TI); void writeOMPClause(OMPClause *C); /// Writes data related to the OpenMP directives. void writeOMPChildren(OMPChildren *Data); /// Emit a string. void AddString(StringRef Str) { return Writer->AddString(Str, *Record); } /// Emit a path. void AddPath(StringRef Path) { return Writer->AddPath(Path, *Record); } /// Emit a version tuple. void AddVersionTuple(const VersionTuple &Version) { return Writer->AddVersionTuple(Version, *Record); } // Emit an attribute. void AddAttr(const Attr *A); /// Emit a list of attributes. void AddAttributes(ArrayRef Attrs); }; } // end namespace clang #endif