diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h index 4c6bbedc6bb..44040e04388 100644 --- a/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -27,9 +27,12 @@ namespace codeview { template class CVRecord { public: - CVRecord() = default; + CVRecord() : Type(static_cast(0)) {} + CVRecord(Kind K, ArrayRef Data) : Type(K), RecordData(Data) {} + bool valid() const { return Type != static_cast(0); } + uint32_t length() const { return RecordData.size(); } Kind kind() const { return Type; } ArrayRef data() const { return RecordData; } diff --git a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h index 950815ef897..3c678d6169c 100644 --- a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h +++ b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -11,18 +11,15 @@ #define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" +#include "llvm/Support/StringSaver.h" namespace llvm { namespace codeview { -class TypeDatabase; -class TypeVisitorCallbacks; - /// \brief Provides amortized O(1) random access to a CodeView type stream. /// Normally to access a type from a type stream, you must know its byte /// offset into the type stream, because type records are variable-lengthed. @@ -47,6 +44,11 @@ class TypeVisitorCallbacks; /// of O(N/M) and an amortized time of O(1). class LazyRandomTypeCollection : public TypeCollection { typedef FixedStreamArray PartialOffsetArray; + struct CacheEntry { + CVType Type; + uint32_t Offset; + StringRef Name; + }; public: explicit LazyRandomTypeCollection(uint32_t RecordCountHint); @@ -56,8 +58,8 @@ public: PartialOffsetArray PartialOffsets); LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint); - void reset(ArrayRef Data); - void reset(StringRef Data); + void reset(ArrayRef Data, uint32_t RecordCountHint); + void reset(StringRef Data, uint32_t RecordCountHint); CVType getType(TypeIndex Index) override; StringRef getTypeName(TypeIndex Index) override; @@ -68,32 +70,26 @@ public: Optional getNext(TypeIndex Prev) override; private: - const TypeDatabase &database() const { return Database; } Error ensureTypeExists(TypeIndex Index); + void ensureCapacityFor(TypeIndex Index); Error visitRangeForType(TypeIndex TI); Error fullScanForType(TypeIndex TI); - Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End); - Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record); + void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End); + + /// Number of actual records. + uint32_t Count = 0; + + /// The largest type index which we've visited. + TypeIndex LargestTypeIndex = TypeIndex::None(); BumpPtrAllocator Allocator; StringSaver NameStorage; - SmallVector TypeNames; - - /// Visited records get automatically added to the type database. - TypeDatabase Database; - /// The type array to allow random access visitation of. CVTypeArray Types; - /// The database visitor which adds new records to the database. - TypeDatabaseVisitor DatabaseVisitor; - - /// A vector mapping type indices to type offset. For every record that has - /// been visited, contains the absolute offset of that record in the record - /// array. - std::vector KnownOffsets; + std::vector Records; /// An array of index offsets for the given type stream, allowing log(N) /// lookups of a type record by index. Similar to KnownOffsets but only diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/include/llvm/DebugInfo/CodeView/TypeDatabase.h deleted file mode 100644 index a743e7f7085..00000000000 --- a/include/llvm/DebugInfo/CodeView/TypeDatabase.h +++ /dev/null @@ -1,84 +0,0 @@ -//===- TypeDatabase.h - A collection of CodeView type records ---*- 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_TYPEDATABASE_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H - -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/StringSaver.h" - -namespace llvm { -namespace codeview { -class TypeDatabase : public TypeCollection { - friend class RandomAccessTypeVisitor; - -public: - explicit TypeDatabase(uint32_t Capacity); - - /// Records the name of a type, and reserves its type index. - TypeIndex appendType(StringRef Name, const CVType &Data); - - /// Records the name of a type, and reserves its type index. - void recordType(StringRef Name, TypeIndex Index, const CVType &Data); - - /// Saves the name in a StringSet and creates a stable StringRef. - StringRef saveTypeName(StringRef TypeName); - - StringRef getTypeName(TypeIndex Index) const; - - const CVType &getTypeRecord(TypeIndex Index) const; - CVType &getTypeRecord(TypeIndex Index); - - bool contains(TypeIndex Index) const; - uint32_t size() const; - uint32_t capacity() const; - bool empty() const; - - CVType getType(TypeIndex Index) override; - StringRef getTypeName(TypeIndex Index) override; - bool contains(TypeIndex Index) override; - uint32_t size() override; - uint32_t capacity() override; - - Optional getFirst() override; - Optional getNext(TypeIndex Prev) override; - - Optional largestTypeIndexLessThan(TypeIndex TI) const; - -private: - TypeIndex getAppendIndex() const; - - void grow(); - void grow(TypeIndex Index); - - BumpPtrAllocator Allocator; - - uint32_t Count = 0; - TypeIndex LargestTypeIndex; - - /// All user defined type records in .debug$T live in here. Type indices - /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to - /// index into this vector. - SmallVector CVUDTNames; - SmallVector TypeRecords; - - StringSaver TypeNameStorage; - - BitVector ValidRecords; -}; -} -} - -#endif \ No newline at end of file diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h deleted file mode 100644 index 77dbc91a7d3..00000000000 --- a/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h +++ /dev/null @@ -1,62 +0,0 @@ -//===-- TypeDatabaseVisitor.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_TYPEDATABASEVISITOR_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H - -#include "llvm/ADT/PointerUnion.h" - -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" - -namespace llvm { -namespace codeview { - -/// Dumper for CodeView type streams found in COFF object files and PDB files. -class TypeDatabaseVisitor : public TypeVisitorCallbacks { -public: - explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(&TypeDB) {} - - /// Paired begin/end actions for all types. Receives all record data, - /// including the fixed-length record prefix. - Error visitTypeBegin(CVType &Record) override; - Error visitTypeBegin(CVType &Record, TypeIndex Index) override; - Error visitTypeEnd(CVType &Record) override; - Error visitMemberBegin(CVMemberRecord &Record) override; - Error visitMemberEnd(CVMemberRecord &Record) override; - -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" - -private: - StringRef getTypeName(TypeIndex Index) const; - StringRef saveTypeName(StringRef Name); - - bool IsInFieldList = false; - - /// Name of the current type. Only valid before visitTypeEnd. - StringRef Name; - /// Current type index. Only valid before visitTypeEnd, and if we are - /// visiting a random access type database. - Optional CurrentTypeIndex; - - TypeDatabase *TypeDB; -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h index 42b62ba2b6c..80326a0ffd3 100644 --- a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h +++ b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h @@ -11,7 +11,9 @@ #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/Support/StringSaver.h" + +#include namespace llvm { namespace codeview { @@ -30,11 +32,10 @@ public: uint32_t capacity() override; private: - bool hasCapacityFor(TypeIndex Index) const; - void ensureTypeExists(TypeIndex Index); - + BumpPtrAllocator Allocator; + StringSaver NameStorage; + std::vector Names; ArrayRef> Records; - TypeDatabase Database; }; } } diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 2d24dcc52fb..b94bb0c80c7 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -24,8 +24,6 @@ add_llvm_library(LLVMDebugInfoCodeView SymbolRecordMapping.cpp SymbolDumper.cpp SymbolSerializer.cpp - TypeDatabase.cpp - TypeDatabaseVisitor.cpp TypeDumpVisitor.cpp TypeIndex.cpp TypeIndexDiscovery.cpp diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index 551963ea306..f06d9c84311 100644 --- a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -11,7 +11,6 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeName.h" #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" @@ -32,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint) LazyRandomTypeCollection::LazyRandomTypeCollection( const CVTypeArray &Types, uint32_t RecordCountHint, PartialOffsetArray PartialOffsets) - : NameStorage(Allocator), Database(RecordCountHint), Types(Types), - DatabaseVisitor(Database), PartialOffsets(PartialOffsets) { - KnownOffsets.resize(Database.capacity()); + : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) { + Records.resize(RecordCountHint); } LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef Data, uint32_t RecordCountHint) : LazyRandomTypeCollection(RecordCountHint) { - reset(Data); } LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data, @@ -53,22 +50,28 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t NumRecords) : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {} -void LazyRandomTypeCollection::reset(StringRef Data) { - reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end())); -} - -void LazyRandomTypeCollection::reset(ArrayRef Data) { +void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) { + Count = 0; PartialOffsets = PartialOffsetArray(); BinaryStreamReader Reader(Data, support::little); error(Reader.readArray(Types, Reader.getLength())); - KnownOffsets.resize(Database.capacity()); + // Clear and then resize, to make sure existing data gets destroyed. + Records.clear(); + Records.resize(RecordCountHint); +} + +void LazyRandomTypeCollection::reset(ArrayRef Data, + uint32_t RecordCountHint) { + reset(toStringRef(Data), RecordCountHint); } CVType LazyRandomTypeCollection::getType(TypeIndex Index) { error(ensureTypeExists(Index)); - return Database.getTypeRecord(Index); + assert(contains(Index)); + + return Records[Index.toArrayIndex()].Type; } StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) { @@ -85,30 +88,43 @@ StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) { } uint32_t I = Index.toArrayIndex(); - if (I >= TypeNames.size()) - TypeNames.resize(I + 1); - - if (TypeNames[I].data() == nullptr) { + ensureCapacityFor(Index); + if (Records[I].Name.data() == nullptr) { StringRef Result = NameStorage.save(computeTypeName(*this, Index)); - TypeNames[I] = Result; + Records[I].Name = Result; } - return TypeNames[I]; + return Records[I].Name; } bool LazyRandomTypeCollection::contains(TypeIndex Index) { - return Database.contains(Index); + if (Records.size() <= Index.toArrayIndex()) + return false; + if (!Records[Index.toArrayIndex()].Type.valid()) + return false; + return true; } -uint32_t LazyRandomTypeCollection::size() { return Database.size(); } +uint32_t LazyRandomTypeCollection::size() { return Count; } -uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); } +uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); } Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) { - if (!Database.contains(TI)) { - if (auto EC = visitRangeForType(TI)) - return EC; - } - return Error::success(); + if (contains(TI)) + return Error::success(); + + return visitRangeForType(TI); +} + +void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) { + uint32_t MinSize = Index.toArrayIndex() + 1; + + if (MinSize <= capacity()) + return; + + uint32_t NewCapacity = MinSize * 3 / 2; + + assert(NewCapacity > capacity()); + Records.resize(NewCapacity); } Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { @@ -124,7 +140,7 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { auto Prev = std::prev(Next); TypeIndex TIB = Prev->Type; - if (Database.contains(TIB)) { + if (contains(TIB)) { // They've asked us to fetch a type index, but the entry we found in the // partial offsets array has already been visited. Since we visit an entire // block every time, that means this record should have been previously @@ -135,13 +151,12 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { TypeIndex TIE; if (Next == PartialOffsets.end()) { - TIE = TypeIndex::fromArrayIndex(Database.capacity()); + TIE = TypeIndex::fromArrayIndex(capacity()); } else { TIE = Next->Type; } - if (auto EC = visitRange(TIB, Prev->Offset, TIE)) - return EC; + visitRange(TIB, Prev->Offset, TIE); return Error::success(); } @@ -170,34 +185,31 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) { assert(PartialOffsets.empty()); TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0); - uint32_t Offset = 0; auto Begin = Types.begin(); - if (!Database.empty()) { + if (Count > 0) { // In the case of type streams which we don't know the number of records of, // it's possible to search for a type index triggering a full scan, but then // later additional records are added since we didn't know how many there // would be until we did a full visitation, then you try to access the new // type triggering another full scan. To avoid this, we assume that if the - // database has some records, this must be what's going on. So we ask the - // database for the largest type index less than the one we're searching for - // and only do the forward scan from there. - auto Prev = Database.largestTypeIndexLessThan(TI); - assert(Prev.hasValue() && "Empty database with valid types?"); - Offset = KnownOffsets[Prev->toArrayIndex()]; - CurrentTI = *Prev; - ++CurrentTI; + // database has some records, this must be what's going on. We can also + // assume that this index must be larger than the largest type index we've + // visited, so we start from there and scan forward. + uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset; + CurrentTI = LargestTypeIndex + 1; Begin = Types.at(Offset); ++Begin; - Offset = Begin.offset(); } auto End = Types.end(); while (Begin != End) { - if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin)) - return EC; - - Offset += Begin.getRecordLength(); + ensureCapacityFor(CurrentTI); + LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI); + auto Idx = CurrentTI.toArrayIndex(); + Records[Idx].Type = *Begin; + Records[Idx].Offset = Begin.offset(); + ++Count; ++Begin; ++CurrentTI; } @@ -207,36 +219,19 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) { return Error::success(); } -Error LazyRandomTypeCollection::visitRange(TypeIndex Begin, - uint32_t BeginOffset, - TypeIndex End) { - +void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset, + TypeIndex End) { auto RI = Types.at(BeginOffset); assert(RI != Types.end()); + ensureCapacityFor(End); while (Begin != End) { - if (auto EC = visitOneRecord(Begin, BeginOffset, *RI)) - return EC; - - BeginOffset += RI.getRecordLength(); + LargestTypeIndex = std::max(LargestTypeIndex, Begin); + auto Idx = Begin.toArrayIndex(); + Records[Idx].Type = *RI; + Records[Idx].Offset = RI.offset(); + ++Count; ++Begin; ++RI; } - - return Error::success(); -} - -Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset, - CVType &Record) { - assert(!Database.contains(TI)); - if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor)) - return EC; - // Keep the KnownOffsets array the same size as the Database's capacity. Since - // we don't always know how many records are in the type stream, we need to be - // prepared for the database growing and receicing a type index that can't fit - // in our current buffer. - if (KnownOffsets.size() < Database.capacity()) - KnownOffsets.resize(Database.capacity()); - KnownOffsets[TI.toArrayIndex()] = Offset; - return Error::success(); } diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp deleted file mode 100644 index 08f848b36a9..00000000000 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//===- TypeDatabase.cpp --------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" - -using namespace llvm; -using namespace llvm::codeview; - -TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { - CVUDTNames.resize(Capacity); - TypeRecords.resize(Capacity); - ValidRecords.resize(Capacity); -} - -TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) { - LargestTypeIndex = getAppendIndex(); - if (LargestTypeIndex.toArrayIndex() >= capacity()) - grow(); - recordType(Name, LargestTypeIndex, Data); - return LargestTypeIndex; -} - -void TypeDatabase::recordType(StringRef Name, TypeIndex Index, - const CVType &Data) { - LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex); - - if (LargestTypeIndex.toArrayIndex() >= capacity()) - grow(Index); - - uint32_t AI = Index.toArrayIndex(); - - assert(!contains(Index)); - assert(AI < capacity()); - - CVUDTNames[AI] = Name; - TypeRecords[AI] = Data; - ValidRecords.set(AI); - ++Count; -} - -/// Saves the name in a StringSet and creates a stable StringRef. -StringRef TypeDatabase::saveTypeName(StringRef TypeName) { - return TypeNameStorage.save(TypeName); -} - -StringRef TypeDatabase::getTypeName(TypeIndex Index) const { - if (Index.isNoneType() || Index.isSimple()) - return TypeIndex::simpleTypeName(Index); - - if (contains(Index)) - return CVUDTNames[Index.toArrayIndex()]; - - return ""; -} - -const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const { - assert(contains(Index)); - return TypeRecords[Index.toArrayIndex()]; -} - -CVType &TypeDatabase::getTypeRecord(TypeIndex Index) { - assert(contains(Index)); - return TypeRecords[Index.toArrayIndex()]; -} - -bool TypeDatabase::contains(TypeIndex Index) const { - uint32_t AI = Index.toArrayIndex(); - if (AI >= capacity()) - return false; - - return ValidRecords.test(AI); -} - -uint32_t TypeDatabase::size() const { return Count; } - -uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); } - -CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); } - -StringRef TypeDatabase::getTypeName(TypeIndex Index) { - return static_cast(this)->getTypeName(Index); -} - -bool TypeDatabase::contains(TypeIndex Index) { - return static_cast(this)->contains(Index); -} - -uint32_t TypeDatabase::size() { - return static_cast(this)->size(); -} - -uint32_t TypeDatabase::capacity() { - return static_cast(this)->capacity(); -} - -void TypeDatabase::grow() { grow(LargestTypeIndex + 1); } - -void TypeDatabase::grow(TypeIndex NewIndex) { - uint32_t NewSize = NewIndex.toArrayIndex() + 1; - - if (NewSize <= capacity()) - return; - - uint32_t NewCapacity = NewSize * 3 / 2; - - TypeRecords.resize(NewCapacity); - CVUDTNames.resize(NewCapacity); - ValidRecords.resize(NewCapacity); -} - -bool TypeDatabase::empty() const { return size() == 0; } - -Optional TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const { - uint32_t AI = TI.toArrayIndex(); - int N = ValidRecords.find_prev(AI); - if (N == -1) - return None; - return TypeIndex::fromArrayIndex(N); -} - -TypeIndex TypeDatabase::getAppendIndex() const { - if (empty()) - return TypeIndex::fromArrayIndex(0); - - return LargestTypeIndex + 1; -} - -Optional TypeDatabase::getFirst() { - int N = ValidRecords.find_first(); - if (N == -1) - return None; - return TypeIndex::fromArrayIndex(N); -} - -Optional TypeDatabase::getNext(TypeIndex Prev) { - int N = ValidRecords.find_next(Prev.toArrayIndex()); - if (N == -1) - return None; - return TypeIndex::fromArrayIndex(N); -} diff --git a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp deleted file mode 100644 index 8d97f8b1cb4..00000000000 --- a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//===- TypeDatabaseVisitor.cpp -------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" - -#include "llvm/ADT/SmallString.h" - -using namespace llvm; - -using namespace llvm::codeview; - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) { - assert(!IsInFieldList); - // Reset Name to the empty string. If the visitor sets it, we know it. - Name = ""; - - if (Record.Type == LF_FIELDLIST) { - // Record that we're in a field list so that members do not get assigned - // type indices. - IsInFieldList = true; - } - return Error::success(); -} - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { - if (auto EC = visitTypeBegin(Record)) - return EC; - - CurrentTypeIndex = Index; - return Error::success(); -} - -StringRef TypeDatabaseVisitor::getTypeName(TypeIndex Index) const { - return TypeDB->getTypeName(Index); -} - -StringRef TypeDatabaseVisitor::saveTypeName(StringRef Name) { - return TypeDB->saveTypeName(Name); -} - -Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) { - if (CVR.Type == LF_FIELDLIST) { - assert(IsInFieldList); - IsInFieldList = false; - } - assert(!IsInFieldList); - - // Record every type that is not a field list member, even if Name is empty. - // CVUDTNames is indexed by type index, and must have one entry for every - // type. Field list members are not recorded, and are only referenced by - // their containing field list record. - if (CurrentTypeIndex) - TypeDB->recordType(Name, *CurrentTypeIndex, CVR); - else - TypeDB->appendType(Name, CVR); - - CurrentTypeIndex.reset(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) { - assert(IsInFieldList); - // Reset Name to the empty string. If the visitor sets it, we know it. - Name = ""; - return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) { - assert(IsInFieldList); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - FieldListRecord &FieldList) { - Name = ""; - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVRecord &CVR, - StringIdRecord &String) { - // Put this in the database so it gets printed with LF_UDT_SRC_LINE. - Name = String.getString(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { - auto Indices = Args.getIndices(); - uint32_t Size = Indices.size(); - SmallString<256> TypeName("("); - for (uint32_t I = 0; I < Size; ++I) { - StringRef ArgTypeName = getTypeName(Indices[I]); - TypeName.append(ArgTypeName); - if (I + 1 != Size) - TypeName.append(", "); - } - TypeName.push_back(')'); - Name = saveTypeName(TypeName); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - StringListRecord &Strings) { - auto Indices = Strings.getIndices(); - uint32_t Size = Indices.size(); - SmallString<256> TypeName("\""); - for (uint32_t I = 0; I < Size; ++I) { - StringRef ArgTypeName = getTypeName(Indices[I]); - TypeName.append(ArgTypeName); - if (I + 1 != Size) - TypeName.append("\" \""); - } - TypeName.push_back('\"'); - Name = saveTypeName(TypeName); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) { - Name = Class.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) { - Name = Union.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { - Name = Enum.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { - Name = AT.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { - Name = VFT.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - MemberFuncIdRecord &Id) { - Name = Id.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - ProcedureRecord &Proc) { - StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); - StringRef ArgListTypeName = getTypeName(Proc.getArgumentList()); - SmallString<256> TypeName(ReturnTypeName); - TypeName.push_back(' '); - TypeName.append(ArgListTypeName); - Name = saveTypeName(TypeName); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - MemberFunctionRecord &MF) { - StringRef ReturnTypeName = getTypeName(MF.getReturnType()); - StringRef ClassTypeName = getTypeName(MF.getClassType()); - StringRef ArgListTypeName = getTypeName(MF.getArgumentList()); - SmallString<256> TypeName(ReturnTypeName); - TypeName.push_back(' '); - TypeName.append(ClassTypeName); - TypeName.append("::"); - TypeName.append(ArgListTypeName); - Name = saveTypeName(TypeName); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { - Name = Func.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - TypeServer2Record &TS) { - Name = TS.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { - - if (Ptr.isPointerToMember()) { - const MemberPointerInfo &MI = Ptr.getMemberInfo(); - - StringRef PointeeName = getTypeName(Ptr.getReferentType()); - StringRef ClassName = getTypeName(MI.getContainingType()); - SmallString<256> TypeName(PointeeName); - TypeName.push_back(' '); - TypeName.append(ClassName); - TypeName.append("::*"); - Name = saveTypeName(TypeName); - } else { - SmallString<256> TypeName; - if (Ptr.isConst()) - TypeName.append("const "); - if (Ptr.isVolatile()) - TypeName.append("volatile "); - if (Ptr.isUnaligned()) - TypeName.append("__unaligned "); - - TypeName.append(getTypeName(Ptr.getReferentType())); - - if (Ptr.getMode() == PointerMode::LValueReference) - TypeName.append("&"); - else if (Ptr.getMode() == PointerMode::RValueReference) - TypeName.append("&&"); - else if (Ptr.getMode() == PointerMode::Pointer) - TypeName.append("*"); - - if (!TypeName.empty()) - Name = saveTypeName(TypeName); - } - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { - uint16_t Mods = static_cast(Mod.getModifiers()); - - StringRef ModifiedName = getTypeName(Mod.getModifiedType()); - SmallString<256> TypeName; - if (Mods & uint16_t(ModifierOptions::Const)) - TypeName.append("const "); - if (Mods & uint16_t(ModifierOptions::Volatile)) - TypeName.append("volatile "); - if (Mods & uint16_t(ModifierOptions::Unaligned)) - TypeName.append("__unaligned "); - TypeName.append(ModifiedName); - Name = saveTypeName(TypeName); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - VFTableShapeRecord &Shape) { - Name = - saveTypeName(""); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - NestedTypeRecord &Nested) { - Name = Nested.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - OneMethodRecord &Method) { - Name = Method.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - OverloadedMethodRecord &Method) { - Name = Method.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - DataMemberRecord &Field) { - Name = Field.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - StaticDataMemberRecord &Field) { - Name = Field.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - EnumeratorRecord &Enum) { - Name = Enum.getName(); - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - BaseClassRecord &Base) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - VirtualBaseClassRecord &VBase) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - ListContinuationRecord &Cont) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( - CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, - UdtSourceLineRecord &SourceLine) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( - CVType &CVR, MethodOverloadListRecord &Overloads) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) { - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, - VFPtrRecord &VFP) { - return Error::success(); -} diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp index 8d974d522f2..4eca5aeaa0a 100644 --- a/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ b/lib/DebugInfo/CodeView/TypeTableCollection.cpp @@ -10,7 +10,7 @@ #include "llvm/DebugInfo/CodeView/TypeTableCollection.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeName.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/BinaryStreamReader.h" @@ -18,14 +18,10 @@ using namespace llvm; using namespace llvm::codeview; -static void error(Error &&EC) { - assert(!static_cast(EC)); - if (EC) - consumeError(std::move(EC)); -} - TypeTableCollection::TypeTableCollection(ArrayRef> Records) - : Records(Records), Database(Records.size()) {} + : NameStorage(Allocator), Records(Records) { + Names.resize(Records.size()); +} Optional TypeTableCollection::getFirst() { if (empty()) @@ -34,50 +30,38 @@ Optional TypeTableCollection::getFirst() { } Optional TypeTableCollection::getNext(TypeIndex Prev) { + assert(contains(Prev)); ++Prev; - assert(Prev.toArrayIndex() <= size()); if (Prev.toArrayIndex() == size()) return None; return Prev; } -void TypeTableCollection::ensureTypeExists(TypeIndex Index) { - assert(hasCapacityFor(Index)); - - if (Database.contains(Index)) - return; - - BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little); - - CVType Type; - uint32_t Len; - VarStreamArrayExtractor Extract; - error(Extract(Bytes, Len, Type)); - - TypeDatabaseVisitor DBV(Database); - error(codeview::visitTypeRecord(Type, Index, DBV)); - assert(Database.contains(Index)); -} - CVType TypeTableCollection::getType(TypeIndex Index) { - ensureTypeExists(Index); - return Database.getTypeRecord(Index); + assert(Index.toArrayIndex() < Records.size()); + ArrayRef Bytes = Records[Index.toArrayIndex()]; + const RecordPrefix *Prefix = + reinterpret_cast(Bytes.data()); + TypeLeafKind Kind = static_cast(uint16_t(Prefix->RecordKind)); + return CVType(Kind, Bytes); } StringRef TypeTableCollection::getTypeName(TypeIndex Index) { - if (!Index.isSimple()) - ensureTypeExists(Index); - return Database.getTypeName(Index); + if (Index.isNoneType() || Index.isSimple()) + return TypeIndex::simpleTypeName(Index); + + uint32_t I = Index.toArrayIndex(); + if (Names[I].data() == nullptr) { + StringRef Result = NameStorage.save(computeTypeName(*this, Index)); + Names[I] = Result; + } + return Names[I]; } bool TypeTableCollection::contains(TypeIndex Index) { - return Database.contains(Index); + return Index.toArrayIndex() <= size(); } uint32_t TypeTableCollection::size() { return Records.size(); } uint32_t TypeTableCollection::capacity() { return Records.size(); } - -bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const { - return Index.toArrayIndex() < Records.size(); -} diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index cd8c02affd4..bb30180325e 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -1099,7 +1099,7 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - Types.reset(Data); + Types.reset(Data, 100); TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes); error(codeview::visitTypeStream(Types, TDV));