1 //===- GlobalTypeTableBuilder.cpp -----------------------------------------===// 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 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" 11 #include "llvm/ADT/ArrayRef.h" 12 #include "llvm/ADT/DenseSet.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/DebugInfo/CodeView/CodeView.h" 15 #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" 16 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 17 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 18 #include "llvm/Support/Allocator.h" 19 #include "llvm/Support/BinaryByteStream.h" 20 #include "llvm/Support/BinaryStreamWriter.h" 21 #include "llvm/Support/Endian.h" 22 #include "llvm/Support/Error.h" 23 #include <algorithm> 24 #include <cassert> 25 #include <cstdint> 26 #include <cstring> 27 28 using namespace llvm; 29 using namespace llvm::codeview; 30 nextTypeIndex() const31TypeIndex GlobalTypeTableBuilder::nextTypeIndex() const { 32 return TypeIndex::fromArrayIndex(SeenRecords.size()); 33 } 34 GlobalTypeTableBuilder(BumpPtrAllocator & Storage)35GlobalTypeTableBuilder::GlobalTypeTableBuilder(BumpPtrAllocator &Storage) 36 : RecordStorage(Storage) { 37 SeenRecords.reserve(4096); 38 } 39 40 GlobalTypeTableBuilder::~GlobalTypeTableBuilder() = default; 41 getFirst()42Optional<TypeIndex> GlobalTypeTableBuilder::getFirst() { 43 if (empty()) 44 return None; 45 46 return TypeIndex(TypeIndex::FirstNonSimpleIndex); 47 } 48 getNext(TypeIndex Prev)49Optional<TypeIndex> GlobalTypeTableBuilder::getNext(TypeIndex Prev) { 50 if (++Prev == nextTypeIndex()) 51 return None; 52 return Prev; 53 } 54 getType(TypeIndex Index)55CVType GlobalTypeTableBuilder::getType(TypeIndex Index) { 56 CVType Type; 57 Type.RecordData = SeenRecords[Index.toArrayIndex()]; 58 if (!Type.RecordData.empty()) { 59 assert(Type.RecordData.size() >= sizeof(RecordPrefix)); 60 const RecordPrefix *P = 61 reinterpret_cast<const RecordPrefix *>(Type.RecordData.data()); 62 Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind)); 63 } 64 return Type; 65 } 66 getTypeName(TypeIndex Index)67StringRef GlobalTypeTableBuilder::getTypeName(TypeIndex Index) { 68 llvm_unreachable("Method not implemented"); 69 } 70 contains(TypeIndex Index)71bool GlobalTypeTableBuilder::contains(TypeIndex Index) { 72 if (Index.isSimple() || Index.isNoneType()) 73 return false; 74 75 return Index.toArrayIndex() < SeenRecords.size(); 76 } 77 size()78uint32_t GlobalTypeTableBuilder::size() { return SeenRecords.size(); } 79 capacity()80uint32_t GlobalTypeTableBuilder::capacity() { return SeenRecords.size(); } 81 records() const82ArrayRef<ArrayRef<uint8_t>> GlobalTypeTableBuilder::records() const { 83 return SeenRecords; 84 } 85 hashes() const86ArrayRef<GloballyHashedType> GlobalTypeTableBuilder::hashes() const { 87 return SeenHashes; 88 } 89 reset()90void GlobalTypeTableBuilder::reset() { 91 HashedRecords.clear(); 92 SeenRecords.clear(); 93 } 94 insertRecordBytes(ArrayRef<uint8_t> Record)95TypeIndex GlobalTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> Record) { 96 GloballyHashedType GHT = 97 GloballyHashedType::hashType(Record, SeenHashes, SeenHashes); 98 return insertRecordAs(GHT, Record.size(), 99 [Record](MutableArrayRef<uint8_t> Data) { 100 assert(Data.size() == Record.size()); 101 ::memcpy(Data.data(), Record.data(), Record.size()); 102 return Data; 103 }); 104 } 105 106 TypeIndex insertRecord(ContinuationRecordBuilder & Builder)107GlobalTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) { 108 TypeIndex TI; 109 auto Fragments = Builder.end(nextTypeIndex()); 110 assert(!Fragments.empty()); 111 for (auto C : Fragments) 112 TI = insertRecordBytes(C.RecordData); 113 return TI; 114 } 115