diff options
Diffstat (limited to 'lib/DebugInfo/CodeView')
-rw-r--r-- | lib/DebugInfo/CodeView/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 41 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp | 10 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp | 91 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabase.cpp | 73 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp | 65 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDumpVisitor.cpp | 9 |
7 files changed, 228 insertions, 63 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 410d5a3777d4..8d9353ae5f5e 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -13,7 +13,7 @@ add_llvm_library(LLVMDebugInfoCodeView ModuleDebugFragmentVisitor.cpp ModuleDebugInlineeLinesFragment.cpp ModuleDebugLineFragment.cpp - ModuleDebugUnknownFragment.cpp + RandomAccessTypeVisitor.cpp RecordSerialization.cpp StringTable.cpp SymbolRecordMapping.cpp diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index 0069ee3cc904..b6ed0453d9c4 100644 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -26,8 +26,7 @@ CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) : Callbacks(Callbacks) {} template <typename T> -static Error visitKnownRecord(CVTypeVisitor &Visitor, CVType &Record, - TypeVisitorCallbacks &Callbacks) { +static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) { TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type); T KnownRecord(RK); if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord)) @@ -76,7 +75,7 @@ void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) { Handlers.push_back(&Handler); } -Error CVTypeVisitor::visitTypeRecord(CVType &Record) { +Expected<bool> CVTypeVisitor::handleTypeServer(CVType &Record) { if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) { auto TS = deserializeTypeServerRecord(Record); if (!TS) @@ -90,16 +89,16 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) { // If the handler processed the record, return success. if (*ExpectedResult) - return Error::success(); + return true; // Otherwise keep searching for a handler, eventually falling out and // using the default record handler. } } + return false; +} - if (auto EC = Callbacks.visitTypeBegin(Record)) - return EC; - +Error CVTypeVisitor::finishVisitation(CVType &Record) { switch (Record.Type) { default: if (auto EC = Callbacks.visitUnknownType(Record)) @@ -107,7 +106,7 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) { break; #define TYPE_RECORD(EnumName, EnumVal, Name) \ case EnumName: { \ - if (auto EC = visitKnownRecord<Name##Record>(*this, Record, Callbacks)) \ + if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks)) \ return EC; \ break; \ } @@ -124,6 +123,32 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) { return Error::success(); } +Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) { + auto ExpectedResult = handleTypeServer(Record); + if (!ExpectedResult) + return ExpectedResult.takeError(); + if (*ExpectedResult) + return Error::success(); + + if (auto EC = Callbacks.visitTypeBegin(Record, Index)) + return EC; + + return finishVisitation(Record); +} + +Error CVTypeVisitor::visitTypeRecord(CVType &Record) { + auto ExpectedResult = handleTypeServer(Record); + if (!ExpectedResult) + return ExpectedResult.takeError(); + if (*ExpectedResult) + return Error::success(); + + if (auto EC = Callbacks.visitTypeBegin(Record)) + return EC; + + return finishVisitation(Record); +} + static Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks) { if (auto EC = Callbacks.visitMemberBegin(Record)) diff --git a/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp b/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp deleted file mode 100644 index 9fd2cb8ed3e8..000000000000 --- a/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp +++ /dev/null @@ -1,10 +0,0 @@ -//===- ModuleDebugUnknownFragment.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/ModuleDebugUnknownFragment.h"
\ No newline at end of file diff --git a/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp b/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp new file mode 100644 index 000000000000..4cb9acbe07d9 --- /dev/null +++ b/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp @@ -0,0 +1,91 @@ +//===- RandomAccessTypeVisitor.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/RandomAccessTypeVisitor.h" + +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +using namespace llvm; +using namespace llvm::codeview; + +RandomAccessTypeVisitor::RandomAccessTypeVisitor( + const CVTypeArray &Types, uint32_t NumRecords, + PartialOffsetArray PartialOffsets) + : Database(NumRecords), Types(Types), DatabaseVisitor(Database), + InternalVisitor(Pipeline), PartialOffsets(PartialOffsets) { + Pipeline.addCallbackToPipeline(Deserializer); + Pipeline.addCallbackToPipeline(DatabaseVisitor); + + KnownOffsets.resize(Database.capacity()); +} + +Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI, + TypeVisitorCallbacks &Callbacks) { + assert(TI.toArrayIndex() < Database.capacity()); + + if (!Database.contains(TI)) { + if (auto EC = visitRangeForType(TI)) + return EC; + } + + assert(Database.contains(TI)); + auto &Record = Database.getTypeRecord(TI); + CVTypeVisitor V(Callbacks); + return V.visitTypeRecord(Record, TI); +} + +Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) { + if (PartialOffsets.empty()) { + TypeIndex TIB(TypeIndex::FirstNonSimpleIndex); + TypeIndex TIE = TIB + Database.capacity(); + return visitRange(TIB, 0, TIE); + } + + auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI, + [](TypeIndex Value, const TypeIndexOffset &IO) { + return Value < IO.Type; + }); + + assert(Next != PartialOffsets.begin()); + auto Prev = std::prev(Next); + + TypeIndex TIB = Prev->Type; + TypeIndex TIE; + if (Next == PartialOffsets.end()) { + TIE = TypeIndex::fromArrayIndex(Database.capacity()); + } else { + TIE = Next->Type; + } + + if (auto EC = visitRange(TIB, Prev->Offset, TIE)) + return EC; + return Error::success(); +} + +Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset, + TypeIndex End) { + + auto RI = Types.at(BeginOffset); + assert(RI != Types.end()); + + while (Begin != End) { + assert(!Database.contains(Begin)); + if (auto EC = InternalVisitor.visitTypeRecord(*RI, Begin)) + return EC; + KnownOffsets[Begin.toArrayIndex()] = BeginOffset; + + BeginOffset += RI.getRecordLength(); + ++Begin; + ++RI; + } + + return Error::success(); +} diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp index 5b8841041f88..7924440e5e29 100644 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ b/lib/DebugInfo/CodeView/TypeDatabase.cpp @@ -65,20 +65,32 @@ static const SimpleTypeEntry SimpleTypeNames[] = { {"__bool64*", SimpleTypeKind::Boolean64}, }; -TypeDatabase::TypeDatabase(uint32_t ExpectedSize) : TypeNameStorage(Allocator) { - CVUDTNames.reserve(ExpectedSize); - TypeRecords.reserve(ExpectedSize); +TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { + CVUDTNames.resize(Capacity); + TypeRecords.resize(Capacity); + ValidRecords.resize(Capacity); } -/// Gets the type index for the next type record. -TypeIndex TypeDatabase::getNextTypeIndex() const { - return TypeIndex(TypeIndex::FirstNonSimpleIndex + CVUDTNames.size()); +TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) { + TypeIndex TI; + TI = getAppendIndex(); + if (TI.toArrayIndex() >= capacity()) + grow(); + recordType(Name, TI, Data); + return TI; } -/// Records the name of a type, and reserves its type index. -void TypeDatabase::recordType(StringRef Name, const CVType &Data) { - CVUDTNames.push_back(Name); - TypeRecords.push_back(Data); +void TypeDatabase::recordType(StringRef Name, TypeIndex Index, + const CVType &Data) { + 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. @@ -104,24 +116,47 @@ StringRef TypeDatabase::getTypeName(TypeIndex Index) const { return "<unknown simple type>"; } - uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex; - if (I < CVUDTNames.size()) - return CVUDTNames[I]; + if (contains(Index)) + return CVUDTNames[Index.toArrayIndex()]; return "<unknown UDT>"; } const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const { - return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex]; + assert(contains(Index)); + return TypeRecords[Index.toArrayIndex()]; } CVType &TypeDatabase::getTypeRecord(TypeIndex Index) { - return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex]; + 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); } -bool TypeDatabase::containsTypeIndex(TypeIndex Index) const { - uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex; - return I < CVUDTNames.size(); +uint32_t TypeDatabase::size() const { return Count; } + +uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); } + +void TypeDatabase::grow() { + TypeRecords.emplace_back(); + CVUDTNames.emplace_back(); + ValidRecords.resize(ValidRecords.size() + 1); } -uint32_t TypeDatabase::size() const { return CVUDTNames.size(); } +bool TypeDatabase::empty() const { return size() == 0; } + +TypeIndex TypeDatabase::getAppendIndex() const { + if (empty()) + return TypeIndex::fromArrayIndex(0); + + int Index = ValidRecords.find_last(); + assert(Index != -1); + return TypeIndex::fromArrayIndex(Index) + 1; +} diff --git a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp index c234afd2288b..8d97f8b1cb40 100644 --- a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp @@ -15,7 +15,7 @@ using namespace llvm; using namespace llvm::codeview; -Error TypeDatabaseVisitor::visitTypeBegin(CVRecord<TypeLeafKind> &Record) { +Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) { assert(!IsInFieldList); // Reset Name to the empty string. If the visitor sets it, we know it. Name = ""; @@ -28,6 +28,22 @@ Error TypeDatabaseVisitor::visitTypeBegin(CVRecord<TypeLeafKind> &Record) { 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); @@ -39,7 +55,12 @@ Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) { // 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. - TypeDB.recordType(Name, CVR); + if (CurrentTypeIndex) + TypeDB->recordType(Name, *CurrentTypeIndex, CVR); + else + TypeDB->appendType(Name, CVR); + + CurrentTypeIndex.reset(); return Error::success(); } @@ -73,13 +94,13 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { uint32_t Size = Indices.size(); SmallString<256> TypeName("("); for (uint32_t I = 0; I < Size; ++I) { - StringRef ArgTypeName = TypeDB.getTypeName(Indices[I]); + StringRef ArgTypeName = getTypeName(Indices[I]); TypeName.append(ArgTypeName); if (I + 1 != Size) TypeName.append(", "); } TypeName.push_back(')'); - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); return Error::success(); } @@ -89,13 +110,13 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, uint32_t Size = Indices.size(); SmallString<256> TypeName("\""); for (uint32_t I = 0; I < Size; ++I) { - StringRef ArgTypeName = TypeDB.getTypeName(Indices[I]); + StringRef ArgTypeName = getTypeName(Indices[I]); TypeName.append(ArgTypeName); if (I + 1 != Size) TypeName.append("\" \""); } TypeName.push_back('\"'); - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); return Error::success(); } @@ -132,26 +153,26 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { - StringRef ReturnTypeName = TypeDB.getTypeName(Proc.getReturnType()); - StringRef ArgListTypeName = TypeDB.getTypeName(Proc.getArgumentList()); + StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); + StringRef ArgListTypeName = getTypeName(Proc.getArgumentList()); SmallString<256> TypeName(ReturnTypeName); TypeName.push_back(' '); TypeName.append(ArgListTypeName); - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); return Error::success(); } Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) { - StringRef ReturnTypeName = TypeDB.getTypeName(MF.getReturnType()); - StringRef ClassTypeName = TypeDB.getTypeName(MF.getClassType()); - StringRef ArgListTypeName = TypeDB.getTypeName(MF.getArgumentList()); + 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 = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); return Error::success(); } @@ -171,13 +192,13 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { if (Ptr.isPointerToMember()) { const MemberPointerInfo &MI = Ptr.getMemberInfo(); - StringRef PointeeName = TypeDB.getTypeName(Ptr.getReferentType()); - StringRef ClassName = TypeDB.getTypeName(MI.getContainingType()); + StringRef PointeeName = getTypeName(Ptr.getReferentType()); + StringRef ClassName = getTypeName(MI.getContainingType()); SmallString<256> TypeName(PointeeName); TypeName.push_back(' '); TypeName.append(ClassName); TypeName.append("::*"); - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); } else { SmallString<256> TypeName; if (Ptr.isConst()) @@ -187,7 +208,7 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { if (Ptr.isUnaligned()) TypeName.append("__unaligned "); - TypeName.append(TypeDB.getTypeName(Ptr.getReferentType())); + TypeName.append(getTypeName(Ptr.getReferentType())); if (Ptr.getMode() == PointerMode::LValueReference) TypeName.append("&"); @@ -197,7 +218,7 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { TypeName.append("*"); if (!TypeName.empty()) - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); } return Error::success(); } @@ -205,7 +226,7 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); - StringRef ModifiedName = TypeDB.getTypeName(Mod.getModifiedType()); + StringRef ModifiedName = getTypeName(Mod.getModifiedType()); SmallString<256> TypeName; if (Mods & uint16_t(ModifierOptions::Const)) TypeName.append("const "); @@ -214,14 +235,14 @@ Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { if (Mods & uint16_t(ModifierOptions::Unaligned)) TypeName.append("__unaligned "); TypeName.append(ModifiedName); - Name = TypeDB.saveTypeName(TypeName); + Name = saveTypeName(TypeName); return Error::success(); } Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableShapeRecord &Shape) { - Name = TypeDB.saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + - " methods>"); + Name = + saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + " methods>"); return Error::success(); } diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 870d95221e7d..27a6e0987886 100644 --- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -173,10 +173,13 @@ void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const { } Error TypeDumpVisitor::visitTypeBegin(CVType &Record) { + TypeIndex TI = getSourceDB().getAppendIndex(); + return visitTypeBegin(Record, TI); +} + +Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { W->startLine() << getLeafTypeName(Record.Type); - W->getOStream() << " (" - << HexNumber(getSourceDB().getNextTypeIndex().getIndex()) - << ")"; + W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")"; W->getOStream() << " {\n"; W->indent(); W->printEnum("TypeLeafKind", unsigned(Record.Type), |