diff options
Diffstat (limited to 'lib/DebugInfo/CodeView')
-rw-r--r-- | lib/DebugInfo/CodeView/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 2 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp | 30 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/EnumTables.cpp | 10 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp | 157 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/SymbolDumper.cpp | 2 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/SymbolRecordMapping.cpp | 2 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabase.cpp | 146 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp | 330 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeDumpVisitor.cpp | 2 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp | 82 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeName.cpp | 243 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/TypeTableCollection.cpp | 58 |
13 files changed, 465 insertions, 602 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index f916695a8439..b94bb0c80c79 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -24,11 +24,10 @@ add_llvm_library(LLVMDebugInfoCodeView SymbolRecordMapping.cpp SymbolDumper.cpp SymbolSerializer.cpp - TypeDatabase.cpp - TypeDatabaseVisitor.cpp TypeDumpVisitor.cpp TypeIndex.cpp TypeIndexDiscovery.cpp + TypeName.cpp TypeRecordMapping.cpp TypeSerializer.cpp TypeStreamMerger.cpp diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index f0debd9e9702..22f166a2335d 100644 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -12,8 +12,6 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 334c5e002bbc..d69eca018e0c 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -53,12 +53,16 @@ DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container) : Subsection(std::move(Subsection)), Container(Container) {} +DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( + const DebugSubsectionRecord &Contents, CodeViewContainer Container) + : Contents(Contents), Container(Container) {} + uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { - // The length of the entire subsection is always padded to 4 bytes, regardless - // of the container kind. - uint32_t Size = sizeof(DebugSubsectionHeader) + - alignTo(Subsection->calculateSerializedSize(), 4); - return Size; + uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() + : Contents.getRecordData().getLength(); + // The length of the entire subsection is always padded to 4 bytes, + // regardless of the container kind. + return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4); } Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { @@ -66,16 +70,22 @@ Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { "Debug Subsection not properly aligned"); DebugSubsectionHeader Header; - Header.Kind = uint32_t(Subsection->kind()); + Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind()); // The value written into the Header's Length field is only padded to the // container's alignment - Header.Length = - alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); + uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() + : Contents.getRecordData().getLength(); + Header.Length = alignTo(DataSize, alignOf(Container)); if (auto EC = Writer.writeObject(Header)) return EC; - if (auto EC = Subsection->commit(Writer)) - return EC; + if (Subsection) { + if (auto EC = Subsection->commit(Writer)) + return EC; + } else { + if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) + return EC; + } if (auto EC = Writer.padToAlignment(4)) return EC; diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp index 01d8ccf2d31e..ec00af28395e 100644 --- a/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/lib/DebugInfo/CodeView/EnumTables.cpp @@ -82,6 +82,13 @@ static const EnumEntry<uint16_t> RegisterNames[] = { CV_ENUM_CLASS_ENT(RegisterId, R15), }; +static const EnumEntry<uint32_t> PublicSymFlagNames[] = { + CV_ENUM_CLASS_ENT(PublicSymFlags, Code), + CV_ENUM_CLASS_ENT(PublicSymFlags, Function), + CV_ENUM_CLASS_ENT(PublicSymFlags, Managed), + CV_ENUM_CLASS_ENT(PublicSymFlags, MSIL), +}; + static const EnumEntry<uint8_t> ProcSymFlagNames[] = { CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP), CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), @@ -338,6 +345,9 @@ ArrayRef<EnumEntry<uint16_t>> getRegisterNames() { return makeArrayRef(RegisterNames); } +ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames() { + return makeArrayRef(PublicSymFlagNames); +} ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames() { return makeArrayRef(ProcSymFlagNames); } diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index 39eb4099ce9e..20f7e72c3af3 100644 --- a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -11,7 +11,7 @@ #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" @@ -31,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint) LazyRandomTypeCollection::LazyRandomTypeCollection( const CVTypeArray &Types, uint32_t RecordCountHint, PartialOffsetArray PartialOffsets) - : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database), - PartialOffsets(PartialOffsets) { - KnownOffsets.resize(Database.capacity()); + : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) { + Records.resize(RecordCountHint); } LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data, uint32_t RecordCountHint) : LazyRandomTypeCollection(RecordCountHint) { - reset(Data); } LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data, @@ -52,50 +50,88 @@ 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<uint8_t> 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<uint8_t> Data, + uint32_t RecordCountHint) { + reset(toStringRef(Data), RecordCountHint); +} + +uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) { + error(ensureTypeExists(Index)); + assert(contains(Index)); + + return Records[Index.toArrayIndex()].Offset; } 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) { - if (!Index.isSimple()) { - // Try to make sure the type exists. Even if it doesn't though, it may be - // because we're dumping a symbol stream with no corresponding type stream - // present, in which case we still want to be able to print <unknown UDT> - // for the type names. - consumeError(ensureTypeExists(Index)); + if (Index.isNoneType() || Index.isSimple()) + return TypeIndex::simpleTypeName(Index); + + // Try to make sure the type exists. Even if it doesn't though, it may be + // because we're dumping a symbol stream with no corresponding type stream + // present, in which case we still want to be able to print <unknown UDT> + // for the type names. + if (auto EC = ensureTypeExists(Index)) { + consumeError(std::move(EC)); + return "<unknown UDT>"; } - return Database.getTypeName(Index); + uint32_t I = Index.toArrayIndex(); + ensureCapacityFor(Index); + if (Records[I].Name.data() == nullptr) { + StringRef Result = NameStorage.save(computeTypeName(*this, Index)); + Records[I].Name = Result; + } + 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) { @@ -111,7 +147,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 @@ -122,13 +158,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(); } @@ -157,34 +192,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; } @@ -194,36 +226,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/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 36abafc079ed..b9fa9b6a6ad7 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { DictScope S(W, "PublicSym"); - printTypeIndex("Type", Public.Index); + W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames()); W.printNumber("Seg", Public.Segment); W.printNumber("Off", Public.Offset); W.printString("Name", Public.Name); diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index d731dc1b0a37..923837a45d9f 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -361,7 +361,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { - error(IO.mapInteger(Public.Index)); + error(IO.mapEnum(Public.Flags)); error(IO.mapInteger(Public.Offset)); error(IO.mapInteger(Public.Segment)); error(IO.mapStringZ(Public.Name)); diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp deleted file mode 100644 index 08f848b36a9d..000000000000 --- 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 "<unknown UDT>"; -} - -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<const TypeDatabase *>(this)->getTypeName(Index); -} - -bool TypeDatabase::contains(TypeIndex Index) { - return static_cast<const TypeDatabase *>(this)->contains(Index); -} - -uint32_t TypeDatabase::size() { - return static_cast<const TypeDatabase *>(this)->size(); -} - -uint32_t TypeDatabase::capacity() { - return static_cast<const TypeDatabase *>(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<TypeIndex> 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<TypeIndex> TypeDatabase::getFirst() { - int N = ValidRecords.find_first(); - if (N == -1) - return None; - return TypeIndex::fromArrayIndex(N); -} - -Optional<TypeIndex> 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 8d97f8b1cb40..000000000000 --- 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 = "<field list>"; - return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &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<uint16_t>(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("<vftable " + utostr(Shape.getEntryCount()) + " methods>"); - 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/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 04b0384d8190..589966705015 100644 --- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -13,8 +13,6 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/Formatters.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/BinaryByteStream.h" diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index 8704cea60786..1226d5be3f3c 100644 --- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -357,6 +357,82 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind, } } +static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind, + SmallVectorImpl<TiReference> &Refs) { + uint32_t Count; + // FIXME: In the future it would be nice if we could avoid hardcoding these + // values. One idea is to define some structures representing these types + // that would allow the use of offsetof(). + switch (Kind) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_LPROC32_DPC: + case SymbolKind::S_LPROC32_DPC_ID: + Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID + break; + case SymbolKind::S_UDT: + Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT + break; + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: + Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type + break; + case SymbolKind::S_BUILDINFO: + Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags + break; + case SymbolKind::S_LOCAL: + Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type + break; + case SymbolKind::S_CONSTANT: + Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type + break; + case SymbolKind::S_REGREL32: + Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type + break; + case SymbolKind::S_CALLSITEINFO: + Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature + break; + case SymbolKind::S_CALLERS: + case SymbolKind::S_CALLEES: + // The record is a count followed by an array of type indices. + Count = *reinterpret_cast<const ulittle32_t *>(Content.data()); + Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees + break; + case SymbolKind::S_INLINESITE: + Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee + break; + + // Defranges don't have types, just registers and code offsets. + case SymbolKind::S_DEFRANGE_REGISTER: + case SymbolKind::S_DEFRANGE_REGISTER_REL: + case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL: + case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: + case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER: + case SymbolKind::S_DEFRANGE_SUBFIELD: + break; + + // No type refernces. + case SymbolKind::S_LABEL32: + case SymbolKind::S_OBJNAME: + case SymbolKind::S_COMPILE: + case SymbolKind::S_COMPILE2: + case SymbolKind::S_COMPILE3: + case SymbolKind::S_BLOCK32: + case SymbolKind::S_FRAMEPROC: + break; + // Scope ending symbols. + case SymbolKind::S_END: + case SymbolKind::S_INLINESITE_END: + case SymbolKind::S_PROC_ID_END: + break; + default: + return false; // Unknown symbol. + } + return true; +} + void llvm::codeview::discoverTypeIndices(const CVType &Type, SmallVectorImpl<TiReference> &Refs) { ::discoverTypeIndices(Type.content(), Type.kind(), Refs); @@ -369,3 +445,9 @@ void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData, TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind)); ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs); } + +bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym, + SmallVectorImpl<TiReference> &Refs) { + SymbolKind K = Sym.kind(); + return ::discoverTypeIndices(Sym.content(), K, Refs); +} diff --git a/lib/DebugInfo/CodeView/TypeName.cpp b/lib/DebugInfo/CodeView/TypeName.cpp new file mode 100644 index 000000000000..2eb8b81862f3 --- /dev/null +++ b/lib/DebugInfo/CodeView/TypeName.cpp @@ -0,0 +1,243 @@ +//===- TypeName.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/TypeName.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; + +namespace { +class TypeNameComputer : public TypeVisitorCallbacks { + /// The type collection. Used to calculate names of nested types. + TypeCollection &Types; + TypeIndex CurrentTypeIndex = TypeIndex::None(); + + /// Name of the current type. Only valid before visitTypeEnd. + SmallString<256> Name; + +public: + explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {} + + StringRef name() const { return Name; } + + /// 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; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; +} // namespace + +Error TypeNameComputer::visitTypeBegin(CVType &Record) { + llvm_unreachable("Must call visitTypeBegin with a TypeIndex!"); + return Error::success(); +} + +Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) { + // Reset Name to the empty string. If the visitor sets it, we know it. + Name = ""; + CurrentTypeIndex = Index; + return Error::success(); +} + +Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); } + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + FieldListRecord &FieldList) { + Name = "<field list>"; + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, + StringIdRecord &String) { + Name = String.getString(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { + auto Indices = Args.getIndices(); + uint32_t Size = Indices.size(); + Name = "("; + for (uint32_t I = 0; I < Size; ++I) { + assert(Indices[I] < CurrentTypeIndex); + + Name.append(Types.getTypeName(Indices[I])); + if (I + 1 != Size) + Name.append(", "); + } + Name.push_back(')'); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + StringListRecord &Strings) { + auto Indices = Strings.getIndices(); + uint32_t Size = Indices.size(); + Name = "\""; + for (uint32_t I = 0; I < Size; ++I) { + Name.append(Types.getTypeName(Indices[I])); + if (I + 1 != Size) + Name.append("\" \""); + } + Name.push_back('\"'); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) { + Name = Class.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) { + Name = Union.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { + Name = Enum.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { + Name = AT.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { + Name = VFT.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { + Name = Id.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { + StringRef Ret = Types.getTypeName(Proc.getReturnType()); + StringRef Params = Types.getTypeName(Proc.getArgumentList()); + Name = formatv("{0} {1}", Ret, Params).sstr<256>(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + MemberFunctionRecord &MF) { + StringRef Ret = Types.getTypeName(MF.getReturnType()); + StringRef Class = Types.getTypeName(MF.getClassType()); + StringRef Params = Types.getTypeName(MF.getArgumentList()); + Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { + Name = Func.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { + Name = TS.getName(); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { + + if (Ptr.isPointerToMember()) { + const MemberPointerInfo &MI = Ptr.getMemberInfo(); + + StringRef Pointee = Types.getTypeName(Ptr.getReferentType()); + StringRef Class = Types.getTypeName(MI.getContainingType()); + Name = formatv("{0} {1}::*", Pointee, Class); + } else { + if (Ptr.isConst()) + Name.append("const "); + if (Ptr.isVolatile()) + Name.append("volatile "); + if (Ptr.isUnaligned()) + Name.append("__unaligned "); + + Name.append(Types.getTypeName(Ptr.getReferentType())); + + if (Ptr.getMode() == PointerMode::LValueReference) + Name.append("&"); + else if (Ptr.getMode() == PointerMode::RValueReference) + Name.append("&&"); + else if (Ptr.getMode() == PointerMode::Pointer) + Name.append("*"); + } + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { + uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); + + SmallString<256> TypeName; + if (Mods & uint16_t(ModifierOptions::Const)) + Name.append("const "); + if (Mods & uint16_t(ModifierOptions::Volatile)) + Name.append("volatile "); + if (Mods & uint16_t(ModifierOptions::Unaligned)) + Name.append("__unaligned "); + Name.append(Types.getTypeName(Mod.getModifiedType())); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + VFTableShapeRecord &Shape) { + Name = formatv("<vftable {0} methods>", Shape.getEntryCount()); + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord( + CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + UdtSourceLineRecord &SourceLine) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + MethodOverloadListRecord &Overloads) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) { + return Error::success(); +} + +std::string llvm::codeview::computeTypeName(TypeCollection &Types, + TypeIndex Index) { + TypeNameComputer Computer(Types); + CVType Record = Types.getType(Index); + if (auto EC = visitTypeRecord(Record, Index, Computer)) { + consumeError(std::move(EC)); + return "<unknown UDT>"; + } + return Computer.name(); +} diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp index 8d974d522f28..4eca5aeaa0ae 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<bool>(EC)); - if (EC) - consumeError(std::move(EC)); -} - TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records) - : Records(Records), Database(Records.size()) {} + : NameStorage(Allocator), Records(Records) { + Names.resize(Records.size()); +} Optional<TypeIndex> TypeTableCollection::getFirst() { if (empty()) @@ -34,50 +30,38 @@ Optional<TypeIndex> TypeTableCollection::getFirst() { } Optional<TypeIndex> 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<CVType> 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<uint8_t> Bytes = Records[Index.toArrayIndex()]; + const RecordPrefix *Prefix = + reinterpret_cast<const RecordPrefix *>(Bytes.data()); + TypeLeafKind Kind = static_cast<TypeLeafKind>(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(); -} |