//===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" #include #include #include #include namespace llvm { namespace codeview { class TypeTableBuilder { private: TypeIndex handleError(Error EC) const { assert(false && "Couldn't write Type!"); consumeError(std::move(EC)); return TypeIndex(); } BumpPtrAllocator &Allocator; TypeSerializer Serializer; public: explicit TypeTableBuilder(BumpPtrAllocator &Allocator) : Allocator(Allocator), Serializer(Allocator) {} TypeTableBuilder(const TypeTableBuilder &) = delete; TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; bool empty() const { return Serializer.records().empty(); } BumpPtrAllocator &getAllocator() const { return Allocator; } template TypeIndex writeKnownType(T &Record) { static_assert(!std::is_same::value, "Can't serialize FieldList!"); CVType Type; Type.Type = static_cast(Record.getKind()); if (auto EC = Serializer.visitTypeBegin(Type)) return handleError(std::move(EC)); if (auto EC = Serializer.visitKnownRecord(Type, Record)) return handleError(std::move(EC)); auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type); if (!ExpectedIndex) return handleError(ExpectedIndex.takeError()); return *ExpectedIndex; } TypeIndex writeSerializedRecord(MutableArrayRef Record) { return Serializer.insertRecordBytes(Record); } template void ForEachRecord(TFunc Func) { uint32_t Index = TypeIndex::FirstNonSimpleIndex; for (auto Record : Serializer.records()) { Func(TypeIndex(Index), Record); ++Index; } } ArrayRef> records() const { return Serializer.records(); } }; class FieldListRecordBuilder { TypeTableBuilder &TypeTable; TypeSerializer TempSerializer; CVType Type; public: explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable) : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) { Type.Type = TypeLeafKind::LF_FIELDLIST; } void begin() { if (auto EC = TempSerializer.visitTypeBegin(Type)) consumeError(std::move(EC)); } template void writeMemberType(T &Record) { CVMemberRecord CVMR; CVMR.Kind = static_cast(Record.getKind()); if (auto EC = TempSerializer.visitMemberBegin(CVMR)) consumeError(std::move(EC)); if (auto EC = TempSerializer.visitKnownMember(CVMR, Record)) consumeError(std::move(EC)); if (auto EC = TempSerializer.visitMemberEnd(CVMR)) consumeError(std::move(EC)); } TypeIndex end() { if (auto EC = TempSerializer.visitTypeEnd(Type)) { consumeError(std::move(EC)); return TypeIndex(); } TypeIndex Index; for (auto Record : TempSerializer.records()) { Index = TypeTable.writeSerializedRecord(Record); } return Index; } }; } // end namespace codeview } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H