From: Zachary Turner Date: Sat, 29 Sep 2018 23:28:19 +0000 (+0000) Subject: [PDB] Better native API support for pointers. X-Git-Tag: llvmorg-8.0.0-rc1~7604 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6ca6a03c51b67cb94528a05e1efe502e2e61d9e4;p=platform%2Fupstream%2Fllvm.git [PDB] Better native API support for pointers. We didn't properly detect when a pointer was a member pointer, and when that was the case we were not properly returning class parent info. This caused member pointers to render incorrectly in pretty mode. However, we didn't even have pretty tests for pointers in native mode, so those are also added now to ensure this. llvm-svn: 343393 --- diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h index e2f25d1..bcb7431 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h @@ -33,6 +33,7 @@ public: void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const override; + SymIndexId getClassParentId() const override; bool isConstType() const override; uint64_t getLength() const override; bool isReference() const override; @@ -44,7 +45,12 @@ public: bool isVolatileType() const override; bool isUnalignedType() const override; + bool isSingleInheritance() const override; + bool isMultipleInheritance() const override; + bool isVirtualInheritance() const override; + protected: + bool isMemberPointer() const; codeview::TypeIndex TI; Optional Record; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index 9bc0b16..300d672 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -25,6 +25,7 @@ public: void dumpRight(PDBSymDumper &Dumper) const override; FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_ID_METHOD(getClassParent) FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(isReference) diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp index 4545f7e..bd8ecb6 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp @@ -37,6 +37,11 @@ void NativeTypePointer::dump(raw_ostream &OS, int Indent, PdbSymbolIdField RecurseIdFields) const { NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + if (isMemberPointer()) { + dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session, + PdbSymbolIdField::ClassParent, ShowIdFields, + RecurseIdFields); + } dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, PdbSymbolIdField::LexicalParent, ShowIdFields, RecurseIdFields); @@ -50,10 +55,27 @@ void NativeTypePointer::dump(raw_ostream &OS, int Indent, dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent); dumpSymbolField(OS, "reference", isReference(), Indent); dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent); + if (isMemberPointer()) { + if (isSingleInheritance()) + dumpSymbolField(OS, "isSingleInheritance", 1, Indent); + else if (isMultipleInheritance()) + dumpSymbolField(OS, "isMultipleInheritance", 1, Indent); + else if (isVirtualInheritance()) + dumpSymbolField(OS, "isVirtualInheritance", 1, Indent); + } dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); } +SymIndexId NativeTypePointer::getClassParentId() const { + if (!isMemberPointer()) + return 0; + + assert(Record); + const MemberPointerInfo &MPI = Record->getMemberInfo(); + return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType); +} + uint64_t NativeTypePointer::getLength() const { if (Record) return Record->getSize(); @@ -133,3 +155,40 @@ bool NativeTypePointer::isUnalignedType() const { return (Record->getOptions() & PointerOptions::Unaligned) != PointerOptions::None; } + +static inline bool isInheritanceKind(const MemberPointerInfo &MPI, + PointerToMemberRepresentation P1, + PointerToMemberRepresentation P2) { + return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2); +} + +bool NativeTypePointer::isSingleInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::SingleInheritanceData, + PointerToMemberRepresentation::SingleInheritanceFunction); +} + +bool NativeTypePointer::isMultipleInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::MultipleInheritanceData, + PointerToMemberRepresentation::MultipleInheritanceFunction); +} + +bool NativeTypePointer::isVirtualInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::VirtualInheritanceData, + PointerToMemberRepresentation::VirtualInheritanceFunction); +} + +bool NativeTypePointer::isMemberPointer() const { + return isPointerToDataMember() || isPointerToMemberFunction(); +} diff --git a/llvm/test/DebugInfo/PDB/Native/pdb-native-pointers.test b/llvm/test/DebugInfo/PDB/Native/pdb-native-pointers.test index 5bc739b..51dc665 100644 --- a/llvm/test/DebugInfo/PDB/Native/pdb-native-pointers.test +++ b/llvm/test/DebugInfo/PDB/Native/pdb-native-pointers.test @@ -2,9 +2,42 @@ ; being checked against is golden output generated by llvm-pdbutil without ; the -native flag. Then we check that we generate the same output. +; RUN: llvm-pdbutil pretty -native -pointers \ +; RUN: %p/../Inputs/every-pointer.pdb | FileCheck %s --check-prefix=PRETTY ; RUN: llvm-pdbutil diadump -no-ids -native -pointers \ ; RUN: %p/../Inputs/every-pointer.pdb | FileCheck %s +; PRETTY: Pointers: (29 items) +; PRETTY-NEXT: char** +; PRETTY-NEXT: struct Foo* +; PRETTY-NEXT: int& +; PRETTY-NEXT: const int* +; PRETTY-NEXT: volatile int* +; PRETTY-NEXT: const volatile int* +; PRETTY-NEXT: int* +; PRETTY-NEXT: int* +; PRETTY-NEXT: struct __vc_attributes::event_sourceAttribute* +; PRETTY-NEXT: struct __vc_attributes::helper_attributes::v1_alttypeAttribute* +; PRETTY-NEXT: struct __vc_attributes::helper_attributes::usageAttribute* +; PRETTY-NEXT: struct __vc_attributes::threadingAttribute* +; PRETTY-NEXT: struct __vc_attributes::aggregatableAttribute* +; PRETTY-NEXT: struct __vc_attributes::event_receiverAttribute* +; PRETTY-NEXT: struct __vc_attributes::moduleAttribute* +; PRETTY-NEXT: const char* +; PRETTY-NEXT: int&& +; PRETTY-NEXT: struct Foo* +; PRETTY-NEXT: void (__cdecl Foo::*)() +; PRETTY-NEXT: int Foo::* +; PRETTY-NEXT: int (__cdecl Foo::*)() +; PRETTY-NEXT: void (__cdecl *)() +; PRETTY-NEXT: unaligned struct Foo* +; PRETTY-NEXT: struct Foo* +; PRETTY-NEXT: const struct Foo* +; PRETTY-NEXT: volatile struct Foo* +; PRETTY-NEXT: const volatile struct Foo* +; PRETTY-NEXT: struct Foo&& +; PRETTY-NEXT: struct Foo + ; CHECK: { ; CHECK-NEXT: symTag: PointerType ; CHECK-NEXT: length: 8 @@ -227,10 +260,10 @@ ; CHECK-NEXT: constType: 0 ; CHECK-NEXT: isPointerToDataMember: 0 ; CHECK-NEXT: isPointerToMemberFunction: 1 -; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers ; CHECK-NEXT: RValueReference: 0 ; CHECK-NEXT: reference: 0 ; CHECK-NEXT: restrictedType: 0 +; CHECK-NEXT: isSingleInheritance: 1 ; CHECK-NEXT: unalignedType: 0 ; CHECK-NEXT: volatileType: 0 ; CHECK-NEXT: } @@ -243,7 +276,7 @@ ; CHECK-NEXT: RValueReference: 0 ; CHECK-NEXT: reference: 0 ; CHECK-NEXT: restrictedType: 0 -; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers +; CHECK-NEXT: isSingleInheritance: 1 ; CHECK-NEXT: unalignedType: 0 ; CHECK-NEXT: volatileType: 0 ; CHECK-NEXT: } @@ -256,7 +289,7 @@ ; CHECK-NEXT: RValueReference: 0 ; CHECK-NEXT: reference: 0 ; CHECK-NEXT: restrictedType: 0 -; FIXME: isSingleInheritance: 1 # DIA has this property for member pointers +; CHECK-NEXT: isSingleInheritance: 1 ; CHECK-NEXT: unalignedType: 0 ; CHECK-NEXT: volatileType: 0 ; CHECK-NEXT: } diff --git a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp index 9ffdcfd..093164b 100644 --- a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp +++ b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp @@ -22,6 +22,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "llvm/DebugInfo/PDB/UDTLayout.h" @@ -136,43 +137,72 @@ filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E, TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} -void TypeDumper::start(const PDBSymbolExe &Exe) { - if (opts::pretty::Enums) { - if (auto Enums = Exe.findAllChildren()) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums"; - Printer << ": (" << Enums->getChildCount() << " items)"; - Printer.Indent(); - while (auto Enum = Enums->getNext()) - Enum->dump(*this); - Printer.Unindent(); - } - } +template +static bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) { + return false; +} + +static bool isTypeExcluded(LinePrinter &Printer, + const PDBSymbolTypeEnum &Enum) { + if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength())) + return true; + // Dump member enums when dumping their class definition. + if (nullptr != Enum.getClassParent()) + return true; + return false; +} + +static bool isTypeExcluded(LinePrinter &Printer, + const PDBSymbolTypeTypedef &Typedef) { + return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength()); +} + +template +static void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe, + TypeDumper &TD, StringRef Label) { + if (auto Children = Exe.findAllChildren()) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << Label; + Printer << ": (" << Children->getChildCount() << " items)"; + Printer.Indent(); + while (auto Child = Children->getNext()) { + if (isTypeExcluded(Printer, *Child)) + continue; - if (opts::pretty::Funcsigs) { - if (auto Funcsigs = Exe.findAllChildren()) { Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() - << "Function Signatures"; - Printer << ": (" << Funcsigs->getChildCount() << " items)"; - Printer.Indent(); - while (auto FS = Funcsigs->getNext()) - FS->dump(*this); - Printer.Unindent(); + Child->dump(TD); } + Printer.Unindent(); } +} - if (opts::pretty::Typedefs) { - if (auto Typedefs = Exe.findAllChildren()) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs"; - Printer << ": (" << Typedefs->getChildCount() << " items)"; - Printer.Indent(); - while (auto Typedef = Typedefs->getNext()) - Typedef->dump(*this); - Printer.Unindent(); - } +static void printClassDecl(LinePrinter &Printer, + const PDBSymbolTypeUDT &Class) { + if (Class.getUnmodifiedTypeId() != 0) { + if (Class.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; + if (Class.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + if (Class.isUnalignedType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; } + WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; + WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); +} + +void TypeDumper::start(const PDBSymbolExe &Exe) { + if (opts::pretty::Enums) + dumpSymbolCategory(Printer, Exe, *this, "Enums"); + + if (opts::pretty::Funcsigs) + dumpSymbolCategory(Printer, Exe, *this, + "Function Signatures"); + + if (opts::pretty::Typedefs) + dumpSymbolCategory(Printer, Exe, *this, "Typedefs"); + + if (opts::pretty::Pointers) + dumpSymbolCategory(Printer, Exe, *this, "Pointers"); if (opts::pretty::Classes) { if (auto Classes = Exe.findAllChildren()) { @@ -214,17 +244,11 @@ void TypeDumper::start(const PDBSymbolExe &Exe) { if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) continue; + // No point duplicating a full class layout. Just print the modified + // declaration and continue. if (Class->getUnmodifiedTypeId() != 0) { Printer.NewLine(); - if (Class->isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; - if (Class->isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; - if (Class->isUnalignedType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; - WithColor(Printer, PDB_ColorItem::Keyword).get() - << Class->getUdtKind() << " "; - WithColor(Printer, PDB_ColorItem::Type).get() << Class->getName(); + printClassDecl(Printer, *Class); continue; } @@ -244,34 +268,59 @@ void TypeDumper::start(const PDBSymbolExe &Exe) { void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) { assert(opts::pretty::Enums); - if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) - return; - // Dump member enums when dumping their class definition. - if (nullptr != Symbol.getClassParent()) - return; - - Printer.NewLine(); EnumDumper Dumper(Printer); Dumper.start(Symbol); } +void TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { + BuiltinDumper BD(Printer); + BD.start(Symbol); +} + void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) { assert(opts::pretty::Typedefs); - if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) - return; - - Printer.NewLine(); TypedefDumper Dumper(Printer); Dumper.start(Symbol); } void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { - Printer.NewLine(); FunctionDumper Dumper(Printer); Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None); } +void TypeDumper::dump(const PDBSymbolTypePointer &Symbol) { + std::unique_ptr P = Symbol.getPointeeType(); + + if (auto *FS = dyn_cast(P.get())) { + FunctionDumper Dumper(Printer); + FunctionDumper::PointerType PT = + Symbol.isReference() ? FunctionDumper::PointerType::Reference + : FunctionDumper::PointerType::Pointer; + Dumper.start(*FS, nullptr, PT); + return; + } + + if (auto *UDT = dyn_cast(P.get())) { + printClassDecl(Printer, *UDT); + } else { + P->dump(*this); + } + + if (auto Parent = Symbol.getClassParent()) { + auto UDT = llvm::unique_dyn_cast(std::move(Parent)); + if (UDT) + Printer << " " << UDT->getName() << "::"; + } + + if (Symbol.isReference()) + Printer << "&"; + else if (Symbol.isRValueReference()) + Printer << "&&"; + else + Printer << "*"; +} + void TypeDumper::dumpClassLayout(const ClassLayout &Class) { assert(opts::pretty::Classes); diff --git a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.h b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.h index b94c4fe..cb6fcb1 100644 --- a/llvm/tools/llvm-pdbutil/PrettyTypeDumper.h +++ b/llvm/tools/llvm-pdbutil/PrettyTypeDumper.h @@ -26,6 +26,8 @@ public: void dump(const PDBSymbolTypeEnum &Symbol) override; void dump(const PDBSymbolTypeTypedef &Symbol) override; void dump(const PDBSymbolTypeFunctionSig &Symbol) override; + void dump(const PDBSymbolTypeBuiltin &Symbol) override; + void dump(const PDBSymbolTypePointer &Symbol) override; void dumpClassLayout(const ClassLayout &Class); diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index 5783661..c9162dd 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -243,6 +243,9 @@ cl::opt Typedefs("typedefs", cl::desc("Display typedef types"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); cl::opt Funcsigs("funcsigs", cl::desc("Display function signatures"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Pointers("pointers", cl::desc("Display pointer types"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); + cl::opt SymbolOrder( "symbol-order", cl::desc("symbol sort order"), cl::init(SymbolSortMode::None), @@ -1179,7 +1182,7 @@ static void dumpPretty(StringRef Path) { } if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs || - opts::pretty::Funcsigs) { + opts::pretty::Funcsigs || opts::pretty::Pointers) { Printer.NewLine(); WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---"; Printer.Indent(); @@ -1516,6 +1519,8 @@ int main(int Argc, const char **Argv) { opts::pretty::Classes = true; opts::pretty::Typedefs = true; opts::pretty::Enums = true; + opts::pretty::Pointers = true; + opts::pretty::Funcsigs = true; } // When adding filters for excluded compilands and types, we need to diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h index 234beb3..eaedb1a 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h @@ -84,6 +84,7 @@ extern llvm::cl::opt Classes; extern llvm::cl::opt Enums; extern llvm::cl::opt Funcsigs; extern llvm::cl::opt Typedefs; +extern llvm::cl::opt Pointers; extern llvm::cl::opt All; extern llvm::cl::opt ExcludeCompilerGenerated;