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/TypeSerializer.h" 17 #include "llvm/DebugInfo/CodeView/TypeRecord.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 : Allocator(Allocator), Serializer(Allocator) {} 42 TypeTableBuilder(const TypeTableBuilder &) = delete; 43 TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; 44 45 bool empty() const { return Serializer.records().empty(); } 46 47 BumpPtrAllocator &getAllocator() const { return Allocator; } 48 49 template <typename T> TypeIndex writeKnownType(T &Record) { 50 static_assert(!std::is_same<T, FieldListRecord>::value, 51 "Can't serialize FieldList!"); 52 53 CVType Type; 54 Type.Type = static_cast<TypeLeafKind>(Record.getKind()); 55 if (auto EC = Serializer.visitTypeBegin(Type)) 56 return handleError(std::move(EC)); 57 if (auto EC = Serializer.visitKnownRecord(Type, Record)) 58 return handleError(std::move(EC)); 59 60 auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type); 61 if (!ExpectedIndex) 62 return handleError(ExpectedIndex.takeError()); 63 64 return *ExpectedIndex; 65 } 66 67 TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) { 68 return Serializer.insertRecordBytes(Record); 69 } 70 71 template <typename TFunc> void ForEachRecord(TFunc Func) { 72 uint32_t Index = TypeIndex::FirstNonSimpleIndex; 73 74 for (auto Record : Serializer.records()) { 75 Func(TypeIndex(Index), Record); 76 ++Index; 77 } 78 } 79 80 ArrayRef<MutableArrayRef<uint8_t>> records() const { 81 return Serializer.records(); 82 } 83 }; 84 85 class FieldListRecordBuilder { 86 TypeTableBuilder &TypeTable; 87 TypeSerializer TempSerializer; 88 CVType Type; 89 90 public: 91 explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable) 92 : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) { 93 Type.Type = TypeLeafKind::LF_FIELDLIST; 94 } 95 96 void begin() { 97 if (auto EC = TempSerializer.visitTypeBegin(Type)) 98 consumeError(std::move(EC)); 99 } 100 101 template <typename T> void writeMemberType(T &Record) { 102 CVMemberRecord CVMR; 103 CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); 104 if (auto EC = TempSerializer.visitMemberBegin(CVMR)) 105 consumeError(std::move(EC)); 106 if (auto EC = TempSerializer.visitKnownMember(CVMR, Record)) 107 consumeError(std::move(EC)); 108 if (auto EC = TempSerializer.visitMemberEnd(CVMR)) 109 consumeError(std::move(EC)); 110 } 111 112 TypeIndex end() { 113 if (auto EC = TempSerializer.visitTypeEnd(Type)) { 114 consumeError(std::move(EC)); 115 return TypeIndex(); 116 } 117 118 TypeIndex Index; 119 for (auto Record : TempSerializer.records()) { 120 Index = TypeTable.writeSerializedRecord(Record); 121 } 122 return Index; 123 } 124 125 /// Stop building the record. 126 void reset() { 127 if (auto EC = TempSerializer.visitTypeEnd(Type)) 128 consumeError(std::move(EC)); 129 } 130 }; 131 132 } // end namespace codeview 133 } // end namespace llvm 134 135 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H 136