From 4727ac23947013a1f1cdd1f8ced7002f3bc06c72 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Mon, 17 Sep 2018 21:07:48 +0000 Subject: [PATCH] [PDB] Make the native reader support modified types. Previously for cv-qualified types, we would just ignore them and they would never get printed. Now we can enumerate them and cache them like any other symbol type. llvm-svn: 342414 --- .../DebugInfo/PDB/Native/NativeTypeBuiltin.h | 4 +- .../DebugInfo/PDB/Native/NativeTypeEnum.h | 17 ++-- .../llvm/DebugInfo/PDB/Native/SymbolCache.h | 6 ++ .../DebugInfo/PDB/Native/NativeEnumTypes.cpp | 40 +++++--- .../PDB/Native/NativeTypeBuiltin.cpp | 3 +- .../DebugInfo/PDB/Native/NativeTypeEnum.cpp | 48 +++++++--- .../PDB/Native/NativeTypePointer.cpp | 21 ++++- llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp | 91 +++++++++++++++---- .../PDB/Native/pdb-native-enums.test | 25 +++++ 9 files changed, 194 insertions(+), 61 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h index 571bae8b8fd8..2d874b333923 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h @@ -21,7 +21,8 @@ class NativeSession; class NativeTypeBuiltin : public NativeRawSymbol { public: - NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, PDB_BuiltinType T, + NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, + codeview::ModifierOptions Mods, PDB_BuiltinType T, uint64_t L); ~NativeTypeBuiltin() override; @@ -37,6 +38,7 @@ public: protected: NativeSession &Session; + codeview::ModifierOptions Mods; PDB_BuiltinType Type; uint64_t Length; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h index c099f83705eb..35a976612cff 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -18,11 +18,15 @@ namespace llvm { namespace pdb { -class NativeTypeEnum : public NativeRawSymbol, - public codeview::TypeVisitorCallbacks { +class NativeTypeEnum : public NativeRawSymbol { public: NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI, codeview::EnumRecord Record); + + NativeTypeEnum(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex ModifierTI, + codeview::ModifierRecord Modifier, + codeview::EnumRecord EnumRecord); ~NativeTypeEnum() override; void dump(raw_ostream &OS, int Indent) const override; @@ -30,11 +34,6 @@ public: std::unique_ptr findChildren(PDB_SymType Type) const override; - Error visitKnownRecord(codeview::CVType &CVR, - codeview::EnumRecord &Record) override; - Error visitKnownMember(codeview::CVMemberRecord &CVM, - codeview::EnumeratorRecord &Record) override; - PDB_BuiltinType getBuiltinType() const override; PDB_SymType getSymTag() const override; SymIndexId getUnmodifiedTypeId() const override; @@ -43,6 +42,9 @@ public: bool hasCastOperator() const override; uint64_t getLength() const override; std::string getName() const override; + bool isConstType() const override; + bool isVolatileType() const override; + bool isUnalignedType() const override; bool isNested() const override; bool hasOverloadedOperator() const override; bool hasNestedTypes() const override; @@ -57,6 +59,7 @@ public: protected: codeview::TypeIndex Index; codeview::EnumRecord Record; + Optional Modifiers; }; } // namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index c53b919b3c40..704f8b23fbe7 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -53,6 +53,12 @@ class SymbolCache { TI, std::move(Record), std::forward(ConstructorArgs)...); } + SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI, + codeview::CVType CVT); + + SymIndexId createSimpleType(codeview::TypeIndex TI, + codeview::ModifierOptions Mods); + public: SymbolCache(NativeSession &Session, DbiStream *Dbi); diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 1b7ee9841eab..97348a55d616 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -9,29 +9,44 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -namespace llvm { -namespace pdb { +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, - codeview::LazyRandomTypeCollection &Types, - codeview::TypeLeafKind Kind) + LazyRandomTypeCollection &Types, + TypeLeafKind Kind) : Matches(), Index(0), Session(PDBSession) { - for (auto Index = Types.getFirst(); Index; - Index = Types.getNext(Index.getValue())) { - if (Types.getType(Index.getValue()).kind() == Kind) - Matches.push_back(Index.getValue()); + Optional 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(CVT, MR)) { + consumeError(std::move(EC)); + } else if (!MR.ModifiedType.isSimple()) { + CVType UnmodifiedCVT = Types.getType(MR.ModifiedType); + if (UnmodifiedCVT.kind() == Kind) + Matches.push_back(*TI); + } + } + TI = Types.getNext(*TI); } } -NativeEnumTypes::NativeEnumTypes( - NativeSession &PDBSession, const std::vector &Matches, - codeview::TypeLeafKind Kind) +NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, + const std::vector &Matches, + TypeLeafKind Kind) : Matches(Matches), Index(0), Session(PDBSession) {} uint32_t NativeEnumTypes::getChildCount() const { @@ -53,6 +68,3 @@ std::unique_ptr NativeEnumTypes::getNext() { } void NativeEnumTypes::reset() { Index = 0; } - -} // namespace pdb -} // namespace llvm diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp index 6031bba663a1..a9197b7afda1 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp @@ -14,9 +14,10 @@ namespace llvm { namespace pdb { NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, + codeview::ModifierOptions Mods, PDB_BuiltinType T, uint64_t L) : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id), - Session(PDBSession), Type(T), Length(L) {} + Session(PDBSession), Mods(Mods), Type(T), Length(L) {} NativeTypeBuiltin::~NativeTypeBuiltin() {} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index e83cbfc803a1..cfc767f44229 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -28,6 +28,13 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index), 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::~NativeTypeEnum() {} void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const { @@ -38,6 +45,8 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const { dumpSymbolField(OS, "lexicalParentId", 0, Indent); dumpSymbolField(OS, "name", getName(), Indent); dumpSymbolField(OS, "typeId", getTypeId(), Indent); + if (Modifiers.hasValue()) + dumpSymbolField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent); dumpSymbolField(OS, "length", getLength(), Indent); dumpSymbolField(OS, "constructor", hasConstructor(), Indent); dumpSymbolField(OS, "constType", isConstType(), Indent); @@ -68,17 +77,6 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const { } } -Error NativeTypeEnum::visitKnownRecord(codeview::CVType &CVR, - codeview::EnumRecord &ER) { - Record = ER; - return Error::success(); -} - -Error NativeTypeEnum::visitKnownMember(codeview::CVMemberRecord &CVM, - codeview::EnumeratorRecord &R) { - return Error::success(); -} - PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { @@ -149,9 +147,10 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { } SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const { - // FIXME: If this is const, volatile, or unaligned, we should return the - // SymIndexId of the unmodified type here. - return 0; + if (!Modifiers) + return 0; + return Session.getSymbolCache().findSymbolByTypeIndex( + Modifiers->ModifiedType); } bool NativeTypeEnum::hasConstructor() const { @@ -215,3 +214,24 @@ bool NativeTypeEnum::isRefUdt() const { return false; } bool NativeTypeEnum::isValueUdt() const { return false; } bool NativeTypeEnum::isInterfaceUdt() const { return false; } + +bool NativeTypeEnum::isConstType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Const) != + ModifierOptions::None); +} + +bool NativeTypeEnum::isVolatileType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Volatile) != + ModifierOptions::None); +} + +bool NativeTypeEnum::isUnalignedType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) != + ModifierOptions::None); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp index 81fe004b3fda..f41d0a2e493f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp @@ -42,8 +42,6 @@ void NativeTypePointer::dump(raw_ostream &OS, int Indent) const { dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); } -bool NativeTypePointer::isConstType() const { return false; } - uint64_t NativeTypePointer::getLength() const { return Record.getSize(); } SymIndexId NativeTypePointer::getTypeId() const { @@ -68,8 +66,21 @@ bool NativeTypePointer::isPointerToMemberFunction() const { return Record.getMode() == PointerMode::PointerToMemberFunction; } -bool NativeTypePointer::isRestrictedType() const { return false; } +bool NativeTypePointer::isConstType() const { + return (Record.getOptions() & PointerOptions::Const) != PointerOptions::None; +} -bool NativeTypePointer::isVolatileType() const { return false; } +bool NativeTypePointer::isRestrictedType() const { + return (Record.getOptions() & PointerOptions::Restrict) != + PointerOptions::None; +} -bool NativeTypePointer::isUnalignedType() const { return false; } +bool NativeTypePointer::isVolatileType() const { + return (Record.getOptions() & PointerOptions::Volatile) != + PointerOptions::None; +} + +bool NativeTypePointer::isUnalignedType() const { + return (Record.getOptions() & PointerOptions::Unaligned) != + PointerOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index c3fabd71ee5b..d8b4d591a97c 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -60,6 +60,72 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { new NativeEnumTypes(Session, Types, Kind)); } +SymIndexId SymbolCache::createSimpleType(TypeIndex Index, + ModifierOptions Mods) { + // FIXME: We will eventually need to handle pointers to other simple types, + // which are still simple types in the world of CodeView TypeIndexes. + if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) + return 0; + + const auto Kind = Index.getSimpleKind(); + const auto It = std::find_if( + std::begin(BuiltinTypes), std::end(BuiltinTypes), + [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; }); + if (It == std::end(BuiltinTypes)) + return 0; + SymIndexId Id = Cache.size(); + Cache.emplace_back(llvm::make_unique(Session, Id, Mods, + It->Type, It->Size)); + TypeIndexToSymbolId[Index] = Id; + return Id; +} + +SymIndexId +SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, + codeview::CVType CVT) { + ModifierRecord Record; + if (auto EC = TypeDeserializer::deserializeAs(CVT, Record)) { + consumeError(std::move(EC)); + return 0; + } + + 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(UnmodifiedType, ER)) { + consumeError(std::move(EC)); + return 0; + } + return createSymbol(Record.ModifiedType, std::move(Record), + std::move(ER)); + } + case LF_STRUCTURE: + case LF_UNION: + case LF_CLASS: + // FIXME: Handle these + break; + 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(); +} + SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { // First see if it's already in our cache. const auto Entry = TypeIndexToSymbolId.find(Index); @@ -67,25 +133,8 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { return Entry->second; // Symbols for built-in types are created on the fly. - if (Index.isSimple()) { - // FIXME: We will eventually need to handle pointers to other simple types, - // which are still simple types in the world of CodeView TypeIndexes. - if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) - return 0; - const auto Kind = Index.getSimpleKind(); - const auto It = - std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes), - [Kind](const BuiltinTypeEntry &Builtin) { - return Builtin.Kind == Kind; - }); - if (It == std::end(BuiltinTypes)) - return 0; - SymIndexId Id = Cache.size(); - Cache.emplace_back( - llvm::make_unique(Session, Id, It->Type, It->Size)); - TypeIndexToSymbolId[Index] = Id; - return Id; - } + if (Index.isSimple()) + return createSimpleType(Index, ModifierOptions::None); // We need to instantiate and cache the desired type symbol. auto Tpi = Session.getPDBFile().getPDBTpiStream(); @@ -97,6 +146,7 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { codeview::CVType CVT = Types.getType(Index); // TODO(amccarth): Make this handle all types. SymIndexId Id = 0; + switch (CVT.kind()) { case codeview::LF_ENUM: Id = createSymbolForType(Index, std::move(CVT)); @@ -105,6 +155,9 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { Id = createSymbolForType(Index, std::move(CVT)); break; + case codeview::LF_MODIFIER: + Id = createSymbolForModifiedType(Index, std::move(CVT)); + break; default: Id = createSymbolPlaceholder(); break; diff --git a/llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test b/llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test index ed2eb6901905..6777f0b00d15 100644 --- a/llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test +++ b/llvm/test/DebugInfo/PDB/Native/pdb-native-enums.test @@ -6,6 +6,7 @@ ENUMS: enum FooClass::NestedEnum { ENUMS-NEXT: } +ENUMS: const volatile enum FooClass::NestedEnum DUMP: { DUMP-NEXT: symIndexId: 2 @@ -223,3 +224,27 @@ DUMP-NEXT: unalignedType: 0 DUMP-NEXT: isValueUdt: 0 DUMP-NEXT: volatileType: 0 DUMP-NEXT: } +DUMP-NEXT: { +DUMP-NEXT: symIndexId: 12 +DUMP-NEXT: symTag: 12 +DUMP-NEXT: baseType: 6 +DUMP-NEXT: lexicalParentId: 0 +DUMP-NEXT: name: FooClass::NestedEnum +DUMP-NEXT: typeId: 3 +DUMP-NEXT: length: 4 +DUMP-NEXT: constructor: 0 +DUMP-NEXT: constType: 1 +DUMP-NEXT: hasAssignmentOperator: 0 +DUMP-NEXT: hasCastOperator: 0 +DUMP-NEXT: hasNestedTypes: 0 +DUMP-NEXT: overloadedOperator: 0 +DUMP-NEXT: isInterfaceUdt: 0 +DUMP-NEXT: intrinsic: 0 +DUMP-NEXT: nested: 1 +DUMP-NEXT: packed: 0 +DUMP-NEXT: isRefUdt: 0 +DUMP-NEXT: scoped: 0 +DUMP-NEXT: unalignedType: 0 +DUMP-NEXT: isValueUdt: 0 +DUMP-NEXT: volatileType: 1 +DUMP-NEXT: }