diff options
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp | 53 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp | 117 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp | 221 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp | 80 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp | 32 |
10 files changed, 431 insertions, 131 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 0515788d85e..e1bdffd30ee 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -34,6 +34,7 @@ add_llvm_library(LLVMDebugInfoCodeView TypeIndex.cpp TypeIndexDiscovery.cpp TypeHashing.cpp + TypeRecordHelpers.cpp TypeRecordMapping.cpp TypeStreamMerger.cpp TypeTableCollection.cpp diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp new file mode 100644 index 00000000000..2a66474cf5b --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp @@ -0,0 +1,53 @@ +//===- TypeRecordHelpers.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/TypeRecordHelpers.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +using namespace llvm; +using namespace llvm::codeview; + +template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { + RecordT Record; + if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { + consumeError(std::move(EC)); + return ClassOptions::None; + } + return Record.getOptions(); +} + +bool llvm::codeview::isUdtForwardRef(CVType CVT) { + ClassOptions UdtOptions = ClassOptions::None; + switch (CVT.kind()) { + case LF_STRUCTURE: + case LF_CLASS: + case LF_INTERFACE: + UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); + break; + case LF_ENUM: + UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); + break; + case LF_UNION: + UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); + break; + default: + return false; + } + return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; +} + +TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) { + assert(CVT.kind() == LF_MODIFIER); + SmallVector<TypeIndex, 1> Refs; + discoverTypeIndices(CVT, Refs); + return Refs.front(); +} diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 8bf16c505cb..db39ba3b0ee 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -55,6 +55,7 @@ add_pdb_impl_folder(Native Native/NativeTypeBuiltin.cpp Native/NativeTypeEnum.cpp Native/NativeTypePointer.cpp + Native/NativeTypeUDT.cpp Native/NamedStreamMap.cpp Native/NativeSession.cpp Native/PDBFile.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 97348a55d61..f16b776dc65 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" @@ -22,21 +23,24 @@ using namespace llvm::pdb; NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, LazyRandomTypeCollection &Types, - TypeLeafKind Kind) + std::vector<codeview::TypeLeafKind> Kinds) : Matches(), Index(0), Session(PDBSession) { Optional<TypeIndex> TI = Types.getFirst(); while (TI) { CVType CVT = Types.getType(*TI); TypeLeafKind K = CVT.kind(); - if (K == Kind) - Matches.push_back(*TI); - else if (K == TypeLeafKind::LF_MODIFIER) { - ModifierRecord MR; - if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) { - consumeError(std::move(EC)); - } else if (!MR.ModifiedType.isSimple()) { - CVType UnmodifiedCVT = Types.getType(MR.ModifiedType); - if (UnmodifiedCVT.kind() == Kind) + if (llvm::is_contained(Kinds, K)) { + // Don't add forward refs, we'll find those later while enumerating. + if (!isUdtForwardRef(CVT)) + Matches.push_back(*TI); + } else if (K == TypeLeafKind::LF_MODIFIER) { + TypeIndex ModifiedTI = getModifiedType(CVT); + if (!ModifiedTI.isSimple()) { + CVType UnmodifiedCVT = Types.getType(ModifiedTI); + // LF_MODIFIERs point to forward refs, but don't worry about that + // here. We're pushing the TypeIndex of the LF_MODIFIER itself, + // so we'll worry about resolving forward refs later. + if (llvm::is_contained(Kinds, UnmodifiedCVT.kind())) Matches.push_back(*TI); } } @@ -44,11 +48,6 @@ NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, } } -NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, - const std::vector<TypeIndex> &Matches, - TypeLeafKind Kind) - : Matches(Matches), Index(0), Session(PDBSession) {} - uint32_t NativeEnumTypes::getChildCount() const { return static_cast<uint32_t>(Matches.size()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index 97d20d4d3bb..ca173808358 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -45,6 +45,10 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const { return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM); case PDB_SymType::PointerType: return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER); + case PDB_SymType::UDT: + return Session.getSymbolCache().createTypeEnumerator( + {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION, + codeview::LF_INTERFACE}); default: break; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 1a8c75db998..62950cb3e52 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -31,68 +31,68 @@ void NativeRawSymbol::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLines() const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index 0994be4af42..37176fe083b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -40,8 +40,7 @@ namespace { class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks { public: NativeEnumEnumEnumerators(NativeSession &Session, - const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum); + const NativeTypeEnum &ClassParent); uint32_t getChildCount() const override; std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; @@ -56,7 +55,6 @@ private: NativeSession &Session; const NativeTypeEnum &ClassParent; - const codeview::EnumRecord &CVEnum; std::vector<EnumeratorRecord> Enumerators; Optional<TypeIndex> ContinuationIndex; uint32_t Index = 0; @@ -64,13 +62,12 @@ private: } // namespace NativeEnumEnumEnumerators::NativeEnumEnumEnumerators( - NativeSession &Session, const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum) - : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) { + NativeSession &Session, const NativeTypeEnum &ClassParent) + : Session(Session), ClassParent(ClassParent) { TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); LazyRandomTypeCollection &Types = Tpi.typeCollection(); - ContinuationIndex = CVEnum.FieldList; + ContinuationIndex = ClassParent.getEnumRecord().FieldList; while (ContinuationIndex) { CVType FieldList = Types.getType(*ContinuationIndex); assert(FieldList.kind() == LF_FIELDLIST); @@ -100,10 +97,10 @@ NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const { if (Index >= getChildCount()) return nullptr; - SymIndexId Id = - Session.getSymbolCache() - .getOrCreateFieldListMember<NativeSymbolEnumerator>( - CVEnum.FieldList, Index, ClassParent, Enumerators[Index]); + SymIndexId Id = Session.getSymbolCache() + .getOrCreateFieldListMember<NativeSymbolEnumerator>( + ClassParent.getEnumRecord().FieldList, Index, + ClassParent, Enumerators[Index]); return Session.getSymbolCache().getSymbolById(Id); } @@ -122,11 +119,10 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, Record(std::move(Record)) {} NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, - codeview::TypeIndex ModifierTI, - codeview::ModifierRecord Modifier, - codeview::EnumRecord EnumRecord) - : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI), - Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {} + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::Enum, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} NativeTypeEnum::~NativeTypeEnum() {} @@ -173,22 +169,20 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const { const NativeTypeEnum *ClassParent = nullptr; if (!Modifiers) ClassParent = this; - else { - NativeRawSymbol &NRS = - Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId()); - assert(NRS.getSymTag() == PDB_SymType::Enum); - ClassParent = static_cast<NativeTypeEnum *>(&NRS); - } - return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent, - Record); + else + ClassParent = UnmodifiedType; + return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); } PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { - Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType()); + if (UnmodifiedType) + return UnmodifiedType->getBuiltinType(); + + Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType()); - codeview::TypeIndex Underlying = Record.getUnderlyingType(); + codeview::TypeIndex Underlying = Record->getUnderlyingType(); // This indicates a corrupt record. if (!Underlying.isSimple() || @@ -255,67 +249,101 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { } SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const { - if (!Modifiers) - return 0; - - return Session.getSymbolCache().findSymbolByTypeIndex( - Modifiers->ModifiedType); + return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0; } bool NativeTypeEnum::hasConstructor() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConstructorOrDestructor); } bool NativeTypeEnum::hasAssignmentOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedAssignmentOperator); } bool NativeTypeEnum::hasNestedTypes() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return bool(Record->getOptions() & codeview::ClassOptions::ContainsNestedClass); } bool NativeTypeEnum::isIntrinsic() const { - return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic); + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic); } bool NativeTypeEnum::hasCastOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConversionOperator); } uint64_t NativeTypeEnum::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + const auto Id = Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); const auto UnderlyingType = Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); return UnderlyingType ? UnderlyingType->getLength() : 0; } -std::string NativeTypeEnum::getName() const { return Record.getName(); } +std::string NativeTypeEnum::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Record->getName(); +} bool NativeTypeEnum::isNested() const { - return bool(Record.getOptions() & codeview::ClassOptions::Nested); + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return bool(Record->getOptions() & codeview::ClassOptions::Nested); } bool NativeTypeEnum::hasOverloadedOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedOperator); } bool NativeTypeEnum::isPacked() const { - return bool(Record.getOptions() & codeview::ClassOptions::Packed); + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return bool(Record->getOptions() & codeview::ClassOptions::Packed); } bool NativeTypeEnum::isScoped() const { - return bool(Record.getOptions() & codeview::ClassOptions::Scoped); + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return bool(Record->getOptions() & codeview::ClassOptions::Scoped); } SymIndexId NativeTypeEnum::getTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getTypeId(); + return Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); } bool NativeTypeEnum::isRefUdt() const { return false; } @@ -346,6 +374,9 @@ bool NativeTypeEnum::isUnalignedType() const { } const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const { + if (UnmodifiedType) + return UnmodifiedType->getUnderlyingBuiltinType(); + return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>( getTypeId()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp new file mode 100644 index 00000000000..3abf91dcc6a --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -0,0 +1,221 @@ +//===- NativeTypeUDT.cpp - info about class/struct type ---------*- 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/PDB/Native/NativeTypeUDT.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ClassRecord CR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Class(std::move(CR)), Tag(Class.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::UnionRecord UR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Union(std::move(UR)), Tag(Union.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} + +NativeTypeUDT::~NativeTypeUDT() {} + +void NativeTypeUDT::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + if (Modifiers.hasValue()) + dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, + Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + if (getUdtKind() != PDB_UdtType::Union) + dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(), + Indent); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "udtKind", getUdtKind(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent); + dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent); + dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent); + dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent); + dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent); + dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent); + dumpSymbolField(OS, "nested", isNested(), Indent); + dumpSymbolField(OS, "packed", isPacked(), Indent); + dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent); + dumpSymbolField(OS, "scoped", isScoped(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::string NativeTypeUDT::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Tag->getName(); +} + +SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; } + +SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getSymIndexId(); + + return 0; +} + +SymIndexId NativeTypeUDT::getVirtualTableShapeId() const { + if (UnmodifiedType) + return UnmodifiedType->getVirtualTableShapeId(); + + if (Class) + return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape); + + return 0; +} + +uint64_t NativeTypeUDT::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + + if (Class) + return Class->getSize(); + + return Union->getSize(); +} + +PDB_UdtType NativeTypeUDT::getUdtKind() const { + if (UnmodifiedType) + return UnmodifiedType->getUdtKind(); + + switch (Tag->Kind) { + case TypeRecordKind::Class: + return PDB_UdtType::Class; + case TypeRecordKind::Union: + return PDB_UdtType::Union; + case TypeRecordKind::Struct: + return PDB_UdtType::Struct; + case TypeRecordKind::Interface: + return PDB_UdtType::Interface; + default: + llvm_unreachable("Unexected udt kind"); + } +} + +bool NativeTypeUDT::hasConstructor() const { + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return (Tag->Options & ClassOptions::HasConstructorOrDestructor) != + ClassOptions::None; +} + +bool NativeTypeUDT::isConstType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Const) != + ModifierOptions::None; +} + +bool NativeTypeUDT::hasAssignmentOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasCastOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return (Tag->Options & ClassOptions::HasConversionOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasNestedTypes() const { + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return (Tag->Options & ClassOptions::ContainsNestedClass) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasOverloadedOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::isInterfaceUdt() const { return false; } + +bool NativeTypeUDT::isIntrinsic() const { + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None; +} + +bool NativeTypeUDT::isNested() const { + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return (Tag->Options & ClassOptions::Nested) != ClassOptions::None; +} + +bool NativeTypeUDT::isPacked() const { + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return (Tag->Options & ClassOptions::Packed) != ClassOptions::None; +} + +bool NativeTypeUDT::isRefUdt() const { return false; } + +bool NativeTypeUDT::isScoped() const { + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None; +} + +bool NativeTypeUDT::isValueUdt() const { return false; } + +bool NativeTypeUDT::isUnalignedType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Unaligned) != + ModifierOptions::None; +} + +bool NativeTypeUDT::isVolatileType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Volatile) != + ModifierOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index d714177509d..4fd7adf1632 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,6 +1,7 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" @@ -9,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" @@ -50,10 +52,18 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) if (Dbi) Compilands.resize(Dbi->modules().getModuleCount()); + + auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); + Tpi.buildHashMap(); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { + return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); } std::unique_ptr<IPDBEnumSymbols> -SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { +SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { auto Tpi = Session.getPDBFile().getPDBTpiStream(); if (!Tpi) { consumeError(Tpi.takeError()); @@ -61,7 +71,7 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { } auto &Types = Tpi->typeCollection(); return std::unique_ptr<IPDBEnumSymbols>( - new NativeEnumTypes(Session, Types, Kind)); + new NativeEnumTypes(Session, Types, std::move(Kinds))); } SymIndexId SymbolCache::createSimpleType(TypeIndex Index, @@ -98,38 +108,24 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, if (Record.ModifiedType.isSimple()) return createSimpleType(Record.ModifiedType, Record.Modifiers); - auto Tpi = Session.getPDBFile().getPDBTpiStream(); - if (!Tpi) { - consumeError(Tpi.takeError()); - return 0; - } - codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); - - codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType); - - switch (UnmodifiedType.kind()) { - case LF_ENUM: { - EnumRecord ER; - if (auto EC = - TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) { - consumeError(std::move(EC)); - return 0; - } - return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record), - std::move(ER)); - } - case LF_STRUCTURE: - case LF_UNION: - case LF_CLASS: - // FIXME: Handle these - break; + // Make sure we create and cache a record for the unmodified type. + SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); + NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; + + switch (UnmodifiedNRS.getSymTag()) { + case PDB_SymType::Enum: + return createSymbol<NativeTypeEnum>( + static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); + case PDB_SymType::UDT: + return createSymbol<NativeTypeUDT>( + static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); default: // No other types can be modified. (LF_POINTER, for example, records // its modifiers a different way. assert(false && "Invalid LF_MODIFIER record"); break; } - return createSymbolPlaceholder(); + return 0; } SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { @@ -150,13 +146,37 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { } codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); codeview::CVType CVT = Types.getType(Index); - // TODO(amccarth): Make this handle all types. - SymIndexId Id = 0; + if (isUdtForwardRef(CVT)) { + Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); + + if (!EFD) + consumeError(EFD.takeError()); + else if (*EFD != Index) { + assert(!isUdtForwardRef(Types.getType(*EFD))); + SymIndexId Result = findSymbolByTypeIndex(*EFD); + // Record a mapping from ForwardRef -> SymIndex of complete type so that + // we'll take the fast path next time. + TypeIndexToSymbolId[Index] = Result; + return Result; + } + } + + // At this point if we still have a forward ref udt it means the full decl was + // not in the PDB. We just have to deal with it and use the forward ref. + SymIndexId Id = 0; switch (CVT.kind()) { case codeview::LF_ENUM: Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); break; + case codeview::LF_CLASS: + case codeview::LF_STRUCTURE: + case codeview::LF_INTERFACE: + Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); + break; + case codeview::LF_UNION: + Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); + break; case codeview::LF_POINTER: Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, std::move(CVT)); diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index 311c3859acf..96221f7d6ec 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -11,9 +11,8 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" -#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -161,35 +160,6 @@ void TpiStream::buildHashMap() { bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); } -template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { - RecordT Record; - if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { - consumeError(std::move(EC)); - return ClassOptions::None; - } - return Record.getOptions(); -} - -static bool isUdtForwardRef(CVType CVT) { - ClassOptions UdtOptions = ClassOptions::None; - switch (CVT.kind()) { - case LF_STRUCTURE: - case LF_CLASS: - case LF_INTERFACE: - UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); - break; - case LF_ENUM: - UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); - break; - case LF_UNION: - UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); - break; - default: - return false; - } - return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; -} - Expected<TypeIndex> TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const { CVType F = Types->getType(ForwardRefTI); |