1 //===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H 11 #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/DebugInfo/CodeView/CodeView.h" 15 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 16 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 17 #include "llvm/DebugInfo/CodeView/TypeSerializer.h" 18 #include "llvm/Support/Allocator.h" 19 #include "llvm/Support/Error.h" 20 #include <algorithm> 21 #include <cassert> 22 #include <cstdint> 23 #include <type_traits> 24 25 namespace llvm { 26 namespace codeview { 27 28 class TypeTableBuilder { 29 private: 30 TypeIndex handleError(Error EC) const { 31 assert(false && "Couldn't write Type!"); 32 consumeError(std::move(EC)); 33 return TypeIndex(); 34 } 35 36 BumpPtrAllocator &Allocator; 37 TypeSerializer Serializer; 38 39 public: 40 explicit TypeTableBuilder(BumpPtrAllocator &Allocator, 41 bool WriteUnique = true) 42 : Allocator(Allocator), Serializer(Allocator, WriteUnique) {} 43 TypeTableBuilder(const TypeTableBuilder &) = delete; 44 TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; 45 46 bool empty() const { return Serializer.records().empty(); } 47 48 BumpPtrAllocator &getAllocator() const { return Allocator; } 49 50 template <typename T> TypeIndex writeKnownType(T &Record) { 51 static_assert(!std::is_same<T, FieldListRecord>::value, 52 "Can't serialize FieldList!"); 53 54 CVType Type; 55 Type.Type = static_cast<TypeLeafKind>(Record.getKind()); 56 if (auto EC = Serializer.visitTypeBegin(Type)) 57 return handleError(std::move(EC)); 58 if (auto EC = Serializer.visitKnownRecord(Type, Record)) 59 return handleError(std::move(EC)); 60 61 auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type); 62 if (!ExpectedIndex) 63 return handleError(ExpectedIndex.takeError()); 64 65 return *ExpectedIndex; 66 } 67 68 TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) { 69 return Serializer.insertRecordBytes(Record); 70 } 71 72 TypeIndex writeSerializedRecord(const RemappedType &Record) { 73 return Serializer.insertRecord(Record); 74 } 75 76 template <typename TFunc> void ForEachRecord(TFunc Func) { 77 uint32_t Index = TypeIndex::FirstNonSimpleIndex; 78 79 for (auto Record : Serializer.records()) { 80 Func(TypeIndex(Index), Record); 81 ++Index; 82 } 83 } 84 85 ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); } 86 }; 87 88 class FieldListRecordBuilder { 89 TypeTableBuilder &TypeTable; 90 BumpPtrAllocator Allocator; 91 TypeSerializer TempSerializer; 92 CVType Type; 93 94 public: 95 explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable) 96 : TypeTable(TypeTable), TempSerializer(Allocator, false) { 97 Type.Type = TypeLeafKind::LF_FIELDLIST; 98 } 99 100 void begin() { 101 TempSerializer.reset(); 102 103 if (auto EC = TempSerializer.visitTypeBegin(Type)) 104 consumeError(std::move(EC)); 105 } 106 107 template <typename T> void writeMemberType(T &Record) { 108 CVMemberRecord CVMR; 109 CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); 110 if (auto EC = TempSerializer.visitMemberBegin(CVMR)) 111 consumeError(std::move(EC)); 112 if (auto EC = TempSerializer.visitKnownMember(CVMR, Record)) 113 consumeError(std::move(EC)); 114 if (auto EC = TempSerializer.visitMemberEnd(CVMR)) 115 consumeError(std::move(EC)); 116 } 117 118 TypeIndex end(bool Write) { 119 TypeIndex Index; 120 if (auto EC = TempSerializer.visitTypeEnd(Type)) { 121 consumeError(std::move(EC)); 122 return TypeIndex(); 123 } 124 125 if (Write) { 126 for (auto Record : TempSerializer.records()) 127 Index = TypeTable.writeSerializedRecord(Record); 128 } 129 130 return Index; 131 } 132 }; 133 134 } // end namespace codeview 135 } // end namespace llvm 136 137 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H 138