[llvm] r300258 - [llvm-pdbdump] Recursively dump class layout.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 13 14:11:01 PDT 2017


Author: zturner
Date: Thu Apr 13 16:11:00 2017
New Revision: 300258

URL: http://llvm.org/viewvc/llvm-project?rev=300258&view=rev
Log:
[llvm-pdbdump] Recursively dump class layout.

Added:
    llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test
    llvm/trunk/test/tools/llvm-pdbdump/simple-padding-text.test
Removed:
    llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
    llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h
    llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
    llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp
    llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp
    llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb
    llvm/trunk/tools/llvm-pdbdump/LinePrinter.cpp
    llvm/trunk/tools/llvm-pdbdump/LinePrinter.h
    llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
    llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h
    llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.h
    llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h Thu Apr 13 16:11:00 2017
@@ -34,12 +34,11 @@ public:
 
   std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override {
     std::unique_ptr<PDBSymbol> Child = Enumerator->getChildAtIndex(Index);
-    return make_concrete_child(std::move(Child));
+    return unique_dyn_cast_or_null<ChildType>(Child);
   }
 
   std::unique_ptr<ChildType> getNext() override {
-    std::unique_ptr<PDBSymbol> Child = Enumerator->getNext();
-    return make_concrete_child(std::move(Child));
+    return unique_dyn_cast_or_null<ChildType>(Enumerator->getNext());
   }
 
   void reset() override { Enumerator->reset(); }
@@ -50,11 +49,6 @@ public:
   }
 
 private:
-  std::unique_ptr<ChildType>
-  make_concrete_child(std::unique_ptr<PDBSymbol> Child) const {
-    ChildType *ConcreteChild = dyn_cast_or_null<ChildType>(Child.release());
-    return std::unique_ptr<ChildType>(ConcreteChild);
-  }
 
   std::unique_ptr<IPDBEnumSymbols> Enumerator;
 };

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h Thu Apr 13 16:11:00 2017
@@ -27,6 +27,8 @@ public:
 
   void dump(PDBSymDumper &Dumper) const override;
 
+  bool isDestructor() const;
+
   std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const;
 
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h Thu Apr 13 16:11:00 2017
@@ -67,6 +67,8 @@ public:
   virtual uint32_t deepPaddingSize() const;
 
   const PDBSymbolData &getDataMember();
+  bool hasUDTLayout() const;
+  const ClassLayout &getUDTLayout() const;
 
 private:
   std::unique_ptr<PDBSymbolData> DataMember;
@@ -77,13 +79,24 @@ class VTableLayoutItem : public StorageI
 public:
   VTableLayoutItem(const UDTLayoutBase &Parent,
                    std::unique_ptr<PDBSymbolTypeVTable> VTable);
+  ArrayRef<PDBSymbolFunc *> funcs() const { return VTableFuncs; }
+
+  uint32_t getElementSize() const { return ElementSize; }
+
+  void setFunction(uint32_t Index, PDBSymbolFunc &Func) {
+    VTableFuncs[Index] = &Func;
+  }
 
 private:
+  uint32_t ElementSize = 0;
+  std::unique_ptr<PDBSymbolTypeVTableShape> Shape;
   std::unique_ptr<PDBSymbolTypeVTable> VTable;
-  std::vector<std::unique_ptr<PDBSymbolFunc>> VTableFuncs;
+  std::vector<PDBSymbolFunc *> VTableFuncs;
 };
 
 class UDTLayoutBase {
+  template <typename T> using UniquePtrVector = std::vector<std::unique_ptr<T>>;
+
 public:
   UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
                 uint32_t Size);
@@ -99,26 +112,37 @@ public:
     return ChildStorage;
   }
 
-  ArrayRef<BaseClassLayout *> base_classes() const { return BaseClasses; }
+  VTableLayoutItem *findVTableAtOffset(uint32_t RelativeOffset);
 
-  ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const {
-    return NonStorageItems;
+  StringRef getUDTName() const { return Name; }
+
+  ArrayRef<BaseClassLayout *> bases() const { return BaseClasses; }
+  ArrayRef<std::unique_ptr<PDBSymbolTypeBaseClass>> vbases() const {
+    return VirtualBases;
   }
 
+  ArrayRef<std::unique_ptr<PDBSymbolFunc>> funcs() const { return Funcs; }
+
+  ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const { return Other; }
+
   const PDBSymbol &getSymbolBase() const { return SymbolBase; }
 
 protected:
   void initializeChildren(const PDBSymbol &Sym);
 
   void addChildToLayout(std::unique_ptr<StorageItemBase> Child);
+  void addVirtualOverride(PDBSymbolFunc &Func);
+  void addVirtualIntro(PDBSymbolFunc &Func);
 
   const PDBSymbol &SymbolBase;
   std::string Name;
   uint32_t SizeOf = 0;
 
   BitVector UsedBytes;
-  std::vector<std::unique_ptr<PDBSymbol>> NonStorageItems;
-  std::vector<std::unique_ptr<StorageItemBase>> ChildStorage;
+  UniquePtrVector<PDBSymbol> Other;
+  UniquePtrVector<PDBSymbolFunc> Funcs;
+  UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBases;
+  UniquePtrVector<StorageItemBase> ChildStorage;
   std::vector<std::list<StorageItemBase *>> ChildrenPerByte;
   std::vector<BaseClassLayout *> BaseClasses;
   VTableLayoutItem *VTable = nullptr;
@@ -129,6 +153,8 @@ public:
   explicit ClassLayout(const PDBSymbolTypeUDT &UDT);
   explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT);
 
+  ClassLayout(ClassLayout &&Other) = default;
+
   const PDBSymbolTypeUDT &getClass() const { return UDT; }
 
 private:
@@ -142,6 +168,7 @@ public:
                   std::unique_ptr<PDBSymbolTypeBaseClass> Base);
 
   const PDBSymbolTypeBaseClass &getBase() const { return *Base; }
+  bool isVirtualBase() const { return IsVirtualBase; }
 
 private:
   std::unique_ptr<PDBSymbolTypeBaseClass> Base;

Modified: llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp Thu Apr 13 16:11:00 2017
@@ -159,6 +159,8 @@ PDBSymbol::findInlineFramesByRVA(uint32_
 std::unique_ptr<IPDBEnumSymbols>
 PDBSymbol::getChildStats(TagStats &Stats) const {
   std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
+  if (!Result)
+    return nullptr;
   Stats.clear();
   while (auto Child = Result->getNext()) {
     ++Stats[Child->getSymTag()];

Modified: llvm/trunk/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/PDBSymbolFunc.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/PDBSymbolFunc.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/PDBSymbolFunc.cpp Thu Apr 13 16:11:00 2017
@@ -95,3 +95,14 @@ PDBSymbolFunc::getArguments() const {
 }
 
 void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+bool PDBSymbolFunc::isDestructor() const {
+  std::string Name = getName();
+  if (Name.empty())
+    return false;
+  if (Name[0] == '~')
+    return true;
+  if (Name == "__vecDelDtor")
+    return true;
+  return false;
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp Thu Apr 13 16:11:00 2017
@@ -9,6 +9,7 @@
 
 #include "llvm/DebugInfo/PDB/UDTLayout.h"
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
@@ -70,6 +71,12 @@ const PDBSymbolData &DataMemberLayoutIte
   return *dyn_cast<PDBSymbolData>(&Symbol);
 }
 
+bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
+
+const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
+  return *UdtLayout;
+}
+
 uint32_t DataMemberLayoutItem::deepPaddingSize() const {
   uint32_t Result = StorageItemBase::deepPaddingSize();
   if (UdtLayout)
@@ -81,31 +88,13 @@ VTableLayoutItem::VTableLayoutItem(const
                                    std::unique_ptr<PDBSymbolTypeVTable> VTable)
     : StorageItemBase(Parent, *VTable, "<vtbl>", 0, getTypeLength(*VTable)),
       VTable(std::move(VTable)) {
-  // initialize vtbl methods.
   auto VTableType = cast<PDBSymbolTypePointer>(this->VTable->getType());
-  uint32_t PointerSize = VTableType->getLength();
+  ElementSize = VTableType->getLength();
 
-  if (auto Shape = unique_dyn_cast<PDBSymbolTypeVTableShape>(
-          VTableType->getPointeeType())) {
+  Shape =
+      unique_dyn_cast<PDBSymbolTypeVTableShape>(VTableType->getPointeeType());
+  if (Shape)
     VTableFuncs.resize(Shape->getCount());
-
-    auto ParentFunctions =
-        Parent.getSymbolBase().findAllChildren<PDBSymbolFunc>();
-    while (auto Func = ParentFunctions->getNext()) {
-      if (Func->isVirtual()) {
-        uint32_t Index = Func->getVirtualBaseOffset();
-        assert(Index % PointerSize == 0);
-        Index /= PointerSize;
-
-        // Don't allow a compiler generated function to overwrite a user
-        // function in the VTable.  Not sure why this happens, but a function
-        // named __vecDelDtor sometimes shows up on top of the destructor.
-        if (Func->isCompilerGenerated() && VTableFuncs[Index])
-          continue;
-        VTableFuncs[Index] = std::move(Func);
-      }
-    }
-  }
 }
 
 UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
@@ -145,44 +134,191 @@ uint32_t UDTLayoutBase::deepPaddingSize(
 }
 
 void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
+  // Handled bases first, followed by VTables, followed by data members,
+  // followed by functions, followed by other.  This ordering is necessary
+  // so that bases and vtables get initialized before any functions which
+  // may override them.
+
+  UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
+  UniquePtrVector<PDBSymbolTypeVTable> VTables;
+  UniquePtrVector<PDBSymbolData> Members;
   auto Children = Sym.findAllChildren();
   while (auto Child = Children->getNext()) {
-    if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
-      if (Data->getDataKind() == PDB_DataKind::Member) {
-        auto DM =
-            llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
-
-        addChildToLayout(std::move(DM));
-      } else {
-        NonStorageItems.push_back(std::move(Data));
-      }
-      continue;
+    if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
+      if (Base->isVirtualBaseClass())
+        VirtualBases.push_back(std::move(Base));
+      else
+        Bases.push_back(std::move(Base));
     }
 
-    if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
-      auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
-      BaseClasses.push_back(BL.get());
+    else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
+      if (Data->getDataKind() == PDB_DataKind::Member)
+        Members.push_back(std::move(Data));
+      else
+        Other.push_back(std::move(Child));
+    } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
+      VTables.push_back(std::move(VT));
+    else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
+      Funcs.push_back(std::move(Func));
+    else
+      Other.push_back(std::move(Child));
+  }
+
+  for (auto &Base : Bases) {
+    auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
+    BaseClasses.push_back(BL.get());
+
+    addChildToLayout(std::move(BL));
+  }
+
+  for (auto &VT : VTables) {
+    auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
+
+    VTable = VTLayout.get();
+
+    addChildToLayout(std::move(VTLayout));
+    continue;
+  }
+
+  for (auto &Data : Members) {
+    auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
+
+    addChildToLayout(std::move(DM));
+  }
 
-      addChildToLayout(std::move(BL));
+  for (auto &Func : Funcs) {
+    if (!Func->isVirtual())
       continue;
-    }
 
-    if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) {
-      auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
+    if (Func->isIntroVirtualFunction())
+      addVirtualIntro(*Func);
+    else
+      addVirtualOverride(*Func);
+  }
+}
+
+void UDTLayoutBase::addVirtualIntro(PDBSymbolFunc &Func) {
+  // Kind of a hack, but we prefer the more common destructor name that people
+  // are familiar with, e.g. ~ClassName.  It seems there are always both and
+  // the vector deleting destructor overwrites the nice destructor, so just
+  // ignore the vector deleting destructor.
+  if (Func.getName() == "__vecDelDtor")
+    return;
+
+  if (!VTable) {
+    // FIXME: Handle this.  What's most likely happening is we have an intro
+    // virtual in a derived class where the base also has an intro virtual.
+    // In this case the vtable lives in the base.  What we really need is
+    // for each UDTLayoutBase to contain a list of all its vtables, and
+    // then propagate this list up the hierarchy so that derived classes have
+    // direct access to their bases' vtables.
+    return;
+  }
+
+  uint32_t Stride = VTable->getElementSize();
+
+  uint32_t Index = Func.getVirtualBaseOffset();
+  assert(Index % Stride == 0);
+  Index /= Stride;
+
+  VTable->setFunction(Index, Func);
+}
+
+VTableLayoutItem *UDTLayoutBase::findVTableAtOffset(uint32_t RelativeOffset) {
+  if (VTable && VTable->getOffsetInParent() == RelativeOffset)
+    return VTable;
+  for (auto Base : BaseClasses) {
+    uint32_t Begin = Base->getOffsetInParent();
+    uint32_t End = Begin + Base->getSize();
+    if (RelativeOffset < Begin || RelativeOffset >= End)
+      continue;
+
+    return Base->findVTableAtOffset(RelativeOffset - Begin);
+  }
+
+  return nullptr;
+}
 
-      VTable = VTLayout.get();
+void UDTLayoutBase::addVirtualOverride(PDBSymbolFunc &Func) {
+  auto Signature = Func.getSignature();
+  auto ThisAdjust = Signature->getThisAdjust();
+  // ThisAdjust tells us which VTable we're looking for.  Specifically, it's
+  // the offset into the current class of the VTable we're looking for.  So
+  // look through the base hierarchy until we find one such that
+  // AbsoluteOffset(VT) == ThisAdjust
+  VTableLayoutItem *VT = findVTableAtOffset(ThisAdjust);
+  if (!VT) {
+    // FIXME: There really should be a vtable here.  If there's not it probably
+    // means that the vtable is in a virtual base, which we don't yet support.
+    assert(!VirtualBases.empty());
+    return;
+  }
+  int32_t OverrideIndex = -1;
+  // Now we've found the VTable.  Func will not have a virtual base offset set,
+  // so instead we need to compare names and signatures.  We iterate each item
+  // in the VTable.  All items should already have non null entries because they
+  // were initialized by the intro virtual, which was guaranteed to come before.
+  for (auto ItemAndIndex : enumerate(VT->funcs())) {
+    auto Item = ItemAndIndex.value();
+    assert(Item);
+    // If the name doesn't match, this isn't an override.  Note that it's ok
+    // for the return type to not match (e.g. co-variant return).
+    if (Item->getName() != Func.getName()) {
+      if (Item->isDestructor() && Func.isDestructor()) {
+        OverrideIndex = ItemAndIndex.index();
+        break;
+      }
+      continue;
+    }
+    // Now make sure it's the right overload.  Get the signature of the existing
+    // vtable method and make sure it has the same arglist and the same cv-ness.
+    auto ExistingSig = Item->getSignature();
+    if (ExistingSig->isConstType() != Signature->isConstType())
+      continue;
+    if (ExistingSig->isVolatileType() != Signature->isVolatileType())
+      continue;
 
-      addChildToLayout(std::move(VTLayout));
+    // Now compare arguments.  Using the raw bytes of the PDB this would be
+    // trivial
+    // because there is an ArgListId and they should be identical.  But DIA
+    // doesn't
+    // expose this, so the best we can do is iterate each argument and confirm
+    // that
+    // each one is identical.
+    if (ExistingSig->getCount() != Signature->getCount())
       continue;
+    bool IsMatch = true;
+    auto ExistingEnumerator = ExistingSig->getArguments();
+    auto NewEnumerator = Signature->getArguments();
+    for (uint32_t I = 0; I < ExistingEnumerator->getChildCount(); ++I) {
+      auto ExistingArg = ExistingEnumerator->getNext();
+      auto NewArg = NewEnumerator->getNext();
+      if (ExistingArg->getSymIndexId() != NewArg->getSymIndexId()) {
+        IsMatch = false;
+        break;
+      }
     }
+    if (!IsMatch)
+      continue;
 
-    NonStorageItems.push_back(std::move(Child));
+    // It's a match!  Stick the new function into the VTable.
+    OverrideIndex = ItemAndIndex.index();
+    break;
   }
+  if (OverrideIndex == -1) {
+    // FIXME: This is probably due to one of the other FIXMEs in this file.
+    return;
+  }
+  VT->setFunction(OverrideIndex, Func);
 }
 
 void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) {
   uint32_t Begin = Child->getOffsetInParent();
   uint32_t End = Begin + Child->getSize();
+  // Due to the empty base optimization, End might point outside the bounds of
+  // the parent class.  If that happens, just clamp the value.
+  End = std::min(End, getClassSize());
+
   UsedBytes.set(Begin, End);
   while (Begin != End) {
     ChildrenPerByte[Begin].push_back(Child.get());

Modified: llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp Thu Apr 13 16:11:00 2017
@@ -116,6 +116,51 @@ struct SimplePadAggregate {
   // the presence of X will cause 3 bytes of padding to be injected.
 } N;
 
+struct SimplePadVtable1 {
+  static void operator delete(void *ptr, size_t sz) {}
+  virtual ~SimplePadVtable1() {}
+  virtual void A1() {}
+  virtual void B1() {}
+} O;
+
+struct SimplePadVtable2 {
+  static void operator delete(void *ptr, size_t sz) {}
+  virtual ~SimplePadVtable2() {}
+  virtual void X2() {}
+  virtual void Y2() {}
+  virtual void Z2() {}
+} P;
+
+struct SimplePadVtable3 {
+  static void operator delete(void *ptr, size_t sz) {}
+  virtual ~SimplePadVtable3() {}
+  virtual void Foo3() {}
+  virtual void Bar3() {}
+  virtual void Baz3() {}
+  virtual void Buzz3() {}
+} Q;
+
+struct SimplePadMultiVTables
+    : public SimplePadVtable1,
+      public SimplePadVtable2,
+      public SimplePadVtable3 {
+
+  ~SimplePadMultiVTables() override {}
+  static void operator delete(void *ptr, size_t sz) {}
+
+  // SimplePadVtable1 overrides
+  void A1() override {}
+
+  // SimplePadVtable2 overrides
+  void Y2() override {}
+  void Z2() override {}
+
+  // SimplePadVtable3 overrides
+  void Bar3() override {}
+  void Baz3() override {}
+  void Buzz3() override {}
+} R;
+
 int main(int argc, char **argv) {
 
   return 0;

Modified: llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
Binary files - no diff available.

Added: llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test?rev=300258&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test (added)
+++ llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test Thu Apr 13 16:11:00 2017
@@ -0,0 +1,121 @@
+; RUN: llvm-pdbdump pretty -classes -class-definitions=graphical \
+; RUN:     -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
+
+; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
+; RUN: FileCheck -input-file=%t %s -check-prefix=UNION
+; RUN: FileCheck -input-file=%t %s -check-prefix=NESTED_UNION
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS1
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS2
+; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PAD_IN_BASE
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_IN_DERIVED
+; RUN: FileCheck -input-file=%t %s -check-prefix=EMPTY_BASE
+; RUN: FileCheck -input-file=%t %s -check-prefix=VFPTR
+; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT
+; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT2
+; RUN: FileCheck -input-file=%t %s -check-prefix=DEEP_INHERIT
+; RUN: FileCheck -input-file=%t %s -check-prefix=AGGREGATE
+
+; NO_PADDING:      struct SimplePadNoPadding [sizeof = 8] {
+; NO_PADDING-NEXT:   data +0x00 [sizeof=4] int X
+; NO_PADDING-NEXT:   data +0x04 [sizeof=4] int Y
+; NO_PADDING-NEXT: }
+
+; UNION:      struct SimplePadUnion [sizeof = 16] {
+; UNION-NEXT:   data +0x00 [sizeof=4] int X
+; UNION-NEXT:   data +0x00 [sizeof=8] __int64 Y
+; UNION-NEXT:   data +0x00 [sizeof=16] SimplePadUnion::
+; UNION-NEXT:     data +0x00 [sizeof=4] int X
+; UNION-NEXT:     <padding> (4 bytes)
+; UNION-NEXT:     data +0x08 [sizeof=8] __int64 Y
+; UNION-NEXT: }
+
+; NESTED_UNION:      struct {{SimplePadUnion::.*}} [sizeof = 16] {
+; NESTED_UNION-NEXT:   data +0x00 [sizeof=4] int X
+; NESTED_UNION-NEXT:   <padding> (4 bytes)
+; NESTED_UNION-NEXT:   data +0x08 [sizeof=8] __int64 Y
+; NESTED_UNION-NEXT: }
+
+; PAD_FROM_FIELDS1:      struct SimplePadFields1 [sizeof = 4] {
+; PAD_FROM_FIELDS1-NEXT:   data +0x00 [sizeof=1] char A
+; PAD_FROM_FIELDS1-NEXT:   data +0x01 [sizeof=1] char B
+; PAD_FROM_FIELDS1-NEXT:   data +0x02 [sizeof=1] char C
+; PAD_FROM_FIELDS1-NEXT:   <padding> (1 bytes)
+; PAD_FROM_FIELDS1-NEXT: }
+
+; PAD_FROM_FIELDS2:      struct SimplePadFields2 [sizeof = 8] {
+; PAD_FROM_FIELDS2-NEXT:   data +0x00 [sizeof=4] int Y
+; PAD_FROM_FIELDS2-NEXT:   data +0x04 [sizeof=1] char X
+; PAD_FROM_FIELDS2-NEXT:   <padding> (3 bytes)
+; PAD_FROM_FIELDS2-NEXT: }
+
+; NO_PAD_IN_BASE:      struct SimplePadBase [sizeof = 4] {
+; NO_PAD_IN_BASE-NEXT:   data +0x00 [sizeof=4] int X
+; NO_PAD_IN_BASE-NEXT: }
+
+; PAD_IN_DERIVED:      struct SimplePadDerived [sizeof = 16]
+; PAD_IN_DERIVED-NEXT:   : public SimplePadBase {
+; PAD_IN_DERIVED-NEXT:   base +0x00 [sizeof=4] SimplePadBase
+; PAD_IN_DERIVED-NEXT:     data +0x00 [sizeof=4] int X
+; PAD_IN_DERIVED-NEXT:   <padding> (4 bytes)
+; PAD_IN_DERIVED-NEXT:   data +0x08 [sizeof=8] __int64 Y
+; PAD_IN_DERIVED-NEXT: }
+
+; EMPTY_BASE:      struct SimplePadEmpty [sizeof = 8]
+; EMPTY_BASE-NEXT:   : public SimplePadEmptyBase1
+; EMPTY_BASE-NEXT:   , public SimplePadEmptyBase2 {
+; EMPTY_BASE-NEXT:   base +0x00 [sizeof=1] SimplePadEmptyBase1
+; EMPTY_BASE-NEXT:   base +0x01 [sizeof=1] SimplePadEmptyBase2
+; EMPTY_BASE-NEXT:   <padding> (2 bytes)
+; EMPTY_BASE-NEXT:   data +0x04 [sizeof=4] int X
+; EMPTY_BASE-NEXT: }
+
+; VFPTR:      struct SimplePadVfptr [sizeof = 8] {
+; VFPTR-NEXT:   vfptr +0x00 [sizeof=4]
+; VFPTR-NEXT:     [0] &SimplePadVfptr::~SimplePadVfptr
+; VFPTR-NEXT:   data +0x04 [sizeof=4] int X
+; VFPTR-NEXT: }
+
+; MULTIPLE_INHERIT:      struct SimplePadMultiInherit [sizeof = 8]
+; MULTIPLE_INHERIT-NEXT:   : public NonEmptyBase1
+; MULTIPLE_INHERIT-NEXT:   , public NonEmptyBase2 {
+; MULTIPLE_INHERIT-NEXT:   base +0x00 [sizeof=1] NonEmptyBase1
+; MULTIPLE_INHERIT-NEXT:     data +0x00 [sizeof=1] bool X
+; MULTIPLE_INHERIT-NEXT:   base +0x01 [sizeof=1] NonEmptyBase2
+; MULTIPLE_INHERIT-NEXT:     data +0x01 [sizeof=1] bool Y
+; MULTIPLE_INHERIT-NEXT:   <padding> (2 bytes)
+; MULTIPLE_INHERIT-NEXT:   data +0x04 [sizeof=4] int X
+; MULTIPLE_INHERIT-NEXT: }
+
+; MULTIPLE_INHERIT2:      SimplePadMultiInherit2 [sizeof = 16]
+; MULTIPLE_INHERIT2-NEXT:   : public SimplePadFields1
+; MULTIPLE_INHERIT2-NEXT:   , public SimplePadFields2 {
+; MULTIPLE_INHERIT2-NEXT:   base +0x00 [sizeof=4] SimplePadFields1
+; MULTIPLE_INHERIT2-NEXT:     data +0x00 [sizeof=1] char A
+; MULTIPLE_INHERIT2-NEXT:     data +0x01 [sizeof=1] char B
+; MULTIPLE_INHERIT2-NEXT:     data +0x02 [sizeof=1] char C
+; MULTIPLE_INHERIT2-NEXT:     <padding> (1 bytes)
+; MULTIPLE_INHERIT2-NEXT:   base +0x04 [sizeof=8] SimplePadFields2
+; MULTIPLE_INHERIT2-NEXT:     data +0x04 [sizeof=4] int Y
+; MULTIPLE_INHERIT2-NEXT:     data +0x08 [sizeof=1] char X
+; MULTIPLE_INHERIT2-NEXT:     <padding> (3 bytes)
+; MULTIPLE_INHERIT2-NEXT:   data +0x0c [sizeof=4] int X
+; MULTIPLE_INHERIT2-NEXT: }
+
+; DEEP_INHERIT:      struct SimplePadTwoLevelInherit [sizeof = 16]
+; DEEP_INHERIT-NEXT:   : public OneLevelInherit {
+; DEEP_INHERIT-NEXT:     base +0x00 [sizeof=4] OneLevelInherit
+; DEEP_INHERIT-NEXT:       base +0x00 [sizeof=1] NonEmptyBase1
+; DEEP_INHERIT-NEXT:         data +0x00 [sizeof=1] bool X
+; DEEP_INHERIT-NEXT:       <padding> (1 bytes)
+; DEEP_INHERIT-NEXT:       data +0x02 [sizeof=2] short Y
+; DEEP_INHERIT-NEXT:     <padding> (4 bytes)
+; DEEP_INHERIT-NEXT:     data +0x08 [sizeof=8] __int64 Z
+; DEEP_INHERIT-NEXT: }
+
+
+; AGGREGATE:      struct SimplePadAggregate [sizeof = 8] {
+; AGGREGATE-NEXT:   data +0x00 [sizeof=1] NonEmptyBase1 X
+; AGGREGATE-NEXT:     data +0x00 [sizeof=1] bool X
+; AGGREGATE-NEXT:   <padding> (3 bytes)
+; AGGREGATE-NEXT:   data +0x04 [sizeof=4] int Y
+; AGGREGATE-NEXT: }

Added: llvm/trunk/test/tools/llvm-pdbdump/simple-padding-text.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/simple-padding-text.test?rev=300258&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/simple-padding-text.test (added)
+++ llvm/trunk/test/tools/llvm-pdbdump/simple-padding-text.test Thu Apr 13 16:11:00 2017
@@ -0,0 +1,94 @@
+; RUN: llvm-pdbdump pretty -classes -class-definitions=layout-members \
+; RUN:     -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
+
+; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
+; RUN: FileCheck -input-file=%t %s -check-prefix=UNION
+; RUN: FileCheck -input-file=%t %s -check-prefix=NESTED_UNION
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS1
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS2
+; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PAD_IN_BASE
+; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_IN_DERIVED
+; RUN: FileCheck -input-file=%t %s -check-prefix=EMPTY_BASE
+; RUN: FileCheck -input-file=%t %s -check-prefix=VFPTR
+; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT
+; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT2
+; RUN: FileCheck -input-file=%t %s -check-prefix=DEEP_INHERIT
+; RUN: FileCheck -input-file=%t %s -check-prefix=AGGREGATE
+
+; NO_PADDING:      struct SimplePadNoPadding [sizeof = 8] {
+; NO_PADDING-NEXT:   data +0x00 [sizeof=4] int X
+; NO_PADDING-NEXT:   data +0x04 [sizeof=4] int Y
+; NO_PADDING-NEXT: }
+
+; UNION:      struct SimplePadUnion [sizeof = 16] {
+; UNION-NEXT:   data +0x00 [sizeof=4] int X
+; UNION-NEXT:   data +0x00 [sizeof=8] __int64 Y
+; UNION-NEXT:   data +0x00 [sizeof=16] SimplePadUnion::
+; UNION-NEXT: }
+
+; NESTED_UNION:      struct {{SimplePadUnion::.*}} [sizeof = 16] {
+; NESTED_UNION-NEXT:   data +0x00 [sizeof=4] int X
+; NESTED_UNION-NEXT:   <padding> (4 bytes)
+; NESTED_UNION-NEXT:   data +0x08 [sizeof=8] __int64 Y
+; NESTED_UNION-NEXT: }
+
+; PAD_FROM_FIELDS1:      struct SimplePadFields1 [sizeof = 4] {
+; PAD_FROM_FIELDS1-NEXT:   data +0x00 [sizeof=1] char A
+; PAD_FROM_FIELDS1-NEXT:   data +0x01 [sizeof=1] char B
+; PAD_FROM_FIELDS1-NEXT:   data +0x02 [sizeof=1] char C
+; PAD_FROM_FIELDS1-NEXT:   <padding> (1 bytes)
+; PAD_FROM_FIELDS1-NEXT: }
+
+; PAD_FROM_FIELDS2:      struct SimplePadFields2 [sizeof = 8] {
+; PAD_FROM_FIELDS2-NEXT:   data +0x00 [sizeof=4] int Y
+; PAD_FROM_FIELDS2-NEXT:   data +0x04 [sizeof=1] char X
+; PAD_FROM_FIELDS2-NEXT:   <padding> (3 bytes)
+; PAD_FROM_FIELDS2-NEXT: }
+
+; NO_PAD_IN_BASE:      struct SimplePadBase [sizeof = 4] {
+; NO_PAD_IN_BASE-NEXT:   data +0x00 [sizeof=4] int X
+; NO_PAD_IN_BASE-NEXT: }
+
+; PAD_IN_DERIVED:      struct SimplePadDerived [sizeof = 16]
+; PAD_IN_DERIVED-NEXT:   public SimplePadBase {
+; PAD_IN_DERIVED-NEXT:   <padding> (4 bytes)
+; PAD_IN_DERIVED-NEXT:   data +0x08 [sizeof=8] __int64 Y
+; PAD_IN_DERIVED-NEXT: }
+
+; EMPTY_BASE:      struct SimplePadEmpty [sizeof = 8]
+; EMPTY_BASE-NEXT:   : public SimplePadEmptyBase1
+; EMPTY_BASE-NEXT:   , public SimplePadEmptyBase2 {
+; EMPTY_BASE-NEXT:   <padding> (2 bytes)
+; EMPTY_BASE-NEXT:   data +0x04 [sizeof=4] int X
+; EMPTY_BASE-NEXT: }
+
+; VFPTR:      struct SimplePadVfptr [sizeof = 8] {
+; VFPTR-NEXT:   vfptr +0x00 [sizeof=4]
+; VFPTR-NEXT:   data +0x04 [sizeof=4] int X
+; VFPTR-NEXT: }
+
+; MULTIPLE_INHERIT:      struct SimplePadMultiInherit [sizeof = 8]
+; MULTIPLE_INHERIT-NEXT:   : public NonEmptyBase1
+; MULTIPLE_INHERIT-NEXT:   , public NonEmptyBase2 {
+; MULTIPLE_INHERIT-NEXT:   <padding> (2 bytes)
+; MULTIPLE_INHERIT-NEXT:   data +0x04 [sizeof=4] int X
+; MULTIPLE_INHERIT-NEXT: }
+
+; MULTIPLE_INHERIT2:      SimplePadMultiInherit2 [sizeof = 16]
+; MULTIPLE_INHERIT2-NEXT:   : public SimplePadFields1
+; MULTIPLE_INHERIT2-NEXT:   , public SimplePadFields2 {
+; MULTIPLE_INHERIT2-NEXT:   data +0x0c [sizeof=4] int X
+; MULTIPLE_INHERIT2-NEXT: }
+
+; DEEP_INHERIT:      struct SimplePadTwoLevelInherit [sizeof = 16]
+; DEEP_INHERIT-NEXT:   : public OneLevelInherit {
+; DEEP_INHERIT-NEXT:   <padding> (4 bytes)
+; DEEP_INHERIT-NEXT:   data +0x08 [sizeof=8] __int64 Z
+; DEEP_INHERIT-NEXT: }
+
+
+; AGGREGATE:      struct SimplePadAggregate [sizeof = 8] {
+; AGGREGATE-NEXT:   data +0x00 [sizeof=1] NonEmptyBase1 X
+; AGGREGATE-NEXT:   <padding> (3 bytes)
+; AGGREGATE-NEXT:   data +0x04 [sizeof=4] int Y
+; AGGREGATE-NEXT: }

Removed: llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test?rev=300257&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test (removed)
@@ -1,94 +0,0 @@
-; RUN: llvm-pdbdump pretty -classes -class-definitions=layout-members \
-; RUN:     -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
-
-; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
-; RUN: FileCheck -input-file=%t %s -check-prefix=UNION
-; RUN: FileCheck -input-file=%t %s -check-prefix=NESTED_UNION
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS1
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_FROM_FIELDS2
-; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PAD_IN_BASE
-; RUN: FileCheck -input-file=%t %s -check-prefix=PAD_IN_DERIVED
-; RUN: FileCheck -input-file=%t %s -check-prefix=EMPTY_BASE
-; RUN: FileCheck -input-file=%t %s -check-prefix=VFPTR
-; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT
-; RUN: FileCheck -input-file=%t %s -check-prefix=MULTIPLE_INHERIT2
-; RUN: FileCheck -input-file=%t %s -check-prefix=DEEP_INHERIT
-; RUN: FileCheck -input-file=%t %s -check-prefix=AGGREGATE
-
-; NO_PADDING:      struct SimplePadNoPadding [sizeof = 8] {
-; NO_PADDING-NEXT:   data +0x00 [sizeof=4] int X
-; NO_PADDING-NEXT:   data +0x04 [sizeof=4] int Y
-; NO_PADDING-NEXT: }
-
-; UNION:      struct SimplePadUnion [sizeof = 16] {
-; UNION-NEXT:   data +0x00 [sizeof=4] int X
-; UNION-NEXT:   data +0x00 [sizeof=8] __int64 Y
-; UNION-NEXT:   data +0x00 [sizeof=16] SimplePadUnion::
-; UNION-NEXT: }
-
-; NESTED_UNION:      struct {{SimplePadUnion::.*}} [sizeof = 16] {
-; NESTED_UNION-NEXT:   data +0x00 [sizeof=4] int X
-; NESTED_UNION-NEXT:   <padding> (4 bytes)
-; NESTED_UNION-NEXT:   data +0x08 [sizeof=8] __int64 Y
-; NESTED_UNION-NEXT: }
-
-; PAD_FROM_FIELDS1:      struct SimplePadFields1 [sizeof = 4] {
-; PAD_FROM_FIELDS1-NEXT:   data +0x00 [sizeof=1] char A
-; PAD_FROM_FIELDS1-NEXT:   data +0x01 [sizeof=1] char B
-; PAD_FROM_FIELDS1-NEXT:   data +0x02 [sizeof=1] char C
-; PAD_FROM_FIELDS1-NEXT:   <padding> (1 bytes)
-; PAD_FROM_FIELDS1-NEXT: }
-
-; PAD_FROM_FIELDS2:      struct SimplePadFields2 [sizeof = 8] {
-; PAD_FROM_FIELDS2-NEXT:   data +0x00 [sizeof=4] int Y
-; PAD_FROM_FIELDS2-NEXT:   data +0x04 [sizeof=1] char X
-; PAD_FROM_FIELDS2-NEXT:   <padding> (3 bytes)
-; PAD_FROM_FIELDS2-NEXT: }
-
-; NO_PAD_IN_BASE:      struct SimplePadBase [sizeof = 4] {
-; NO_PAD_IN_BASE-NEXT:   data +0x00 [sizeof=4] int X
-; NO_PAD_IN_BASE-NEXT: }
-
-; PAD_IN_DERIVED:      struct SimplePadDerived [sizeof = 16]
-; PAD_IN_DERIVED-NEXT:   public SimplePadBase {
-; PAD_IN_DERIVED-NEXT:   <padding> (4 bytes)
-; PAD_IN_DERIVED-NEXT:   data +0x08 [sizeof=8] __int64 Y
-; PAD_IN_DERIVED-NEXT: }
-
-; EMPTY_BASE:      struct SimplePadEmpty [sizeof = 8]
-; EMPTY_BASE-NEXT:   : public SimplePadEmptyBase1
-; EMPTY_BASE-NEXT:   , public SimplePadEmptyBase2 {
-; EMPTY_BASE-NEXT:   <padding> (2 bytes)
-; EMPTY_BASE-NEXT:   data +0x04 [sizeof=4] int X
-; EMPTY_BASE-NEXT: }
-
-; VFPTR:      struct SimplePadVfptr [sizeof = 8] {
-; VFPTR-NEXT:   data +0x00 [sizeof=4] __vfptr
-; VFPTR-NEXT:   data +0x04 [sizeof=4] int X
-; VFPTR-NEXT: }
-
-; MULTIPLE_INHERIT:      struct SimplePadMultiInherit [sizeof = 8]
-; MULTIPLE_INHERIT-NEXT:   : public NonEmptyBase1
-; MULTIPLE_INHERIT-NEXT:   , public NonEmptyBase2 {
-; MULTIPLE_INHERIT-NEXT:   <padding> (2 bytes)
-; MULTIPLE_INHERIT-NEXT:   data +0x04 [sizeof=4] int X
-; MULTIPLE_INHERIT-NEXT: }
-
-; MULTIPLE_INHERIT2:      SimplePadMultiInherit2 [sizeof = 16]
-; MULTIPLE_INHERIT2-NEXT:   : public SimplePadFields1
-; MULTIPLE_INHERIT2-NEXT:   , public SimplePadFields2 {
-; MULTIPLE_INHERIT2-NEXT:   data +0x0c [sizeof=4] int X
-; MULTIPLE_INHERIT2-NEXT: }
-
-; DEEP_INHERIT:      struct SimplePadTwoLevelInherit [sizeof = 16]
-; DEEP_INHERIT-NEXT:   : public OneLevelInherit {
-; DEEP_INHERIT-NEXT:   <padding> (4 bytes)
-; DEEP_INHERIT-NEXT:   data +0x08 [sizeof=8] __int64 Z
-; DEEP_INHERIT-NEXT: }
-
-
-; AGGREGATE:      struct SimplePadAggregate [sizeof = 8] {
-; AGGREGATE-NEXT:   data +0x00 [sizeof=1] NonEmptyBase1 X
-; AGGREGATE-NEXT:   <padding> (3 bytes)
-; AGGREGATE-NEXT:   data +0x04 [sizeof=4] int Y
-; AGGREGATE-NEXT: }

Modified: llvm/trunk/tools/llvm-pdbdump/LinePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LinePrinter.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LinePrinter.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LinePrinter.cpp Thu Apr 13 16:11:00 2017
@@ -12,6 +12,7 @@
 #include "llvm-pdbdump.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
 #include "llvm/Support/Regex.h"
 
 #include <algorithm>
@@ -70,8 +71,20 @@ void LinePrinter::NewLine() {
   OS.indent(CurrentIndent);
 }
 
-bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName) {
-  return IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters);
+bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
+  if (IsTypeExcluded(Class.getUDTName(), Class.getClassSize()))
+    return true;
+  if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold)
+    return true;
+  return false;
+}
+
+bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
+  if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
+    return true;
+  if (Size < opts::pretty::SizeThreshold)
+    return true;
+  return false;
 }
 
 bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {

Modified: llvm/trunk/tools/llvm-pdbdump/LinePrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LinePrinter.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LinePrinter.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/LinePrinter.h Thu Apr 13 16:11:00 2017
@@ -20,6 +20,8 @@
 namespace llvm {
 namespace pdb {
 
+class ClassLayout;
+
 class LinePrinter {
   friend class WithColor;
 
@@ -34,7 +36,8 @@ public:
   raw_ostream &getStream() { return OS; }
   int getIndentLevel() const { return CurrentIndent; }
 
-  bool IsTypeExcluded(llvm::StringRef TypeName);
+  bool IsClassExcluded(const ClassLayout &Class);
+  bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size);
   bool IsSymbolExcluded(llvm::StringRef SymbolName);
   bool IsCompilandExcluded(llvm::StringRef CompilandName);
 

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp Thu Apr 13 16:11:00 2017
@@ -33,15 +33,15 @@ void ClassDefinitionDumper::start(const
          opts::pretty::ClassDefinitionFormat::None);
 
   ClassLayout Layout(Class);
+  start(Layout);
+}
 
-  if (opts::pretty::OnlyPaddingClasses && (Layout.shallowPaddingSize() == 0))
-    return;
-
+void ClassDefinitionDumper::start(const ClassLayout &Layout) {
   prettyPrintClassIntro(Layout);
 
   switch (opts::pretty::ClassFormat) {
   case opts::pretty::ClassDefinitionFormat::Graphical: {
-    PrettyClassLayoutGraphicalDumper Dumper(Printer);
+    PrettyClassLayoutGraphicalDumper Dumper(Printer, 0);
     DumpedAnything = Dumper.start(Layout);
     break;
   }
@@ -58,6 +58,20 @@ void ClassDefinitionDumper::start(const
   prettyPrintClassOutro(Layout);
 }
 
+static void printBase(LinePrinter &Printer, const PDBSymbolTypeBaseClass &Base,
+                      uint32_t &CurIndex, uint32_t TotalBaseCount,
+                      bool IsVirtual) {
+  Printer << " ";
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess();
+  if (IsVirtual)
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
+  WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
+  if (++CurIndex < TotalBaseCount) {
+    Printer.NewLine();
+    Printer << ",";
+  }
+}
+
 void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) {
   DumpedAnything = false;
   Printer.NewLine();
@@ -69,24 +83,22 @@ void ClassDefinitionDumper::prettyPrintC
   WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
   WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
                                                    << "]";
-  uint32_t BaseCount = Layout.base_classes().size();
-  if (BaseCount > 0) {
+  uint32_t BaseCount = Layout.bases().size();
+  uint32_t VBaseCount = Layout.vbases().size();
+  uint32_t TotalBaseCount = BaseCount + VBaseCount;
+  if (TotalBaseCount > 0) {
     Printer.Indent();
     Printer.NewLine();
     Printer << ":";
     uint32_t BaseIndex = 0;
-    for (auto BC : Layout.base_classes()) {
+    for (auto BC : Layout.bases()) {
       const auto &Base = BC->getBase();
-      Printer << " ";
-      WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess();
-      if (Base.isVirtualBaseClass())
-        WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
-      WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
-      if (++BaseIndex < BaseCount) {
-        Printer.NewLine();
-        Printer << ",";
-      }
+      printBase(Printer, Base, BaseIndex, TotalBaseCount, false);
     }
+    for (auto &BC : Layout.vbases()) {
+      printBase(Printer, *BC, BaseIndex, TotalBaseCount, true);
+    }
+
     Printer.Unindent();
   }
 

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h Thu Apr 13 16:11:00 2017
@@ -32,7 +32,8 @@ class ClassDefinitionDumper : public PDB
 public:
   ClassDefinitionDumper(LinePrinter &P);
 
-  void start(const PDBSymbolTypeUDT &Exe);
+  void start(const PDBSymbolTypeUDT &Class);
+  void start(const ClassLayout &Class);
 
 private:
   void prettyPrintClassIntro(const ClassLayout &Class);

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp Thu Apr 13 16:11:00 2017
@@ -9,30 +9,143 @@
 
 #include "PrettyClassLayoutGraphicalDumper.h"
 
+#include "LinePrinter.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyVariableDumper.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Format.h"
+
 using namespace llvm;
 using namespace llvm::pdb;
 
 PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
-    LinePrinter &P)
-    : PDBSymDumper(true) {}
+    LinePrinter &P, uint32_t InitialOffset)
+    : PDBSymDumper(true), Printer(P), ClassOffsetZero(InitialOffset),
+      CurrentAbsoluteOffset(InitialOffset) {}
+
+bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
+  const BitVector &UseMap = Layout.usedBytes();
+  int NextPaddingByte = UseMap.find_first_unset();
+
+  for (auto &Item : Layout.layout_items()) {
+    // Calculate the absolute offset of the first byte of the next field.
+    uint32_t RelativeOffset = Item->getOffsetInParent();
+    CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
+
+    // Since there is storage there, it should be set!  However, this might
+    // be an empty base, in which case it could extend outside the bounds of
+    // the parent class.
+    if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
+      assert(UseMap.test(RelativeOffset));
+
+      // If there is any remaining padding in this class, and the offset of the
+      // new item is after the padding, then we must have just jumped over some
+      // padding.  Print a padding row and then look for where the next block
+      // of padding begins.
+      if ((NextPaddingByte >= 0) &&
+          (RelativeOffset > uint32_t(NextPaddingByte))) {
+        printPaddingRow(RelativeOffset - NextPaddingByte);
+        NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
+      }
+    }
+
+    CurrentItem = Item.get();
+    Item->getSymbol().dump(*this);
+  }
+
+  if (NextPaddingByte >= 0 && Layout.getClassSize() > 1) {
+    uint32_t Amount = Layout.getClassSize() - NextPaddingByte;
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
+                                                     << " bytes)";
+    DumpedAnything = true;
+  }
+
+  return DumpedAnything;
+}
 
-bool PrettyClassLayoutGraphicalDumper::start(const ClassLayout &Layout) {
-  return false;
+void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
+  if (Amount == 0)
+    return;
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
+                                                   << " bytes)";
+  DumpedAnything = true;
 }
 
 void PrettyClassLayoutGraphicalDumper::dump(
-    const PDBSymbolTypeBaseClass &Symbol) {}
+    const PDBSymbolTypeBaseClass &Symbol) {
+  assert(CurrentItem != nullptr);
 
-void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {}
+  Printer.NewLine();
+  BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
 
-void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {}
+  std::string Label = Layout.isVirtualBase() ? "vbase" : "base";
+  Printer << Label << " ";
 
-void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {}
+  WithColor(Printer, PDB_ColorItem::Offset).get()
+      << "+" << format_hex(CurrentAbsoluteOffset, 4)
+      << " [sizeof=" << Layout.getSize() << "] ";
 
-void PrettyClassLayoutGraphicalDumper::dump(
-    const PDBSymbolTypeTypedef &Symbol) {}
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
+
+  Printer.Indent();
+  uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+  PrettyClassLayoutGraphicalDumper BaseDumper(Printer, ChildOffsetZero);
+  BaseDumper.start(Layout);
+  Printer.Unindent();
+
+  DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
+  assert(CurrentItem != nullptr);
 
-void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
+  DataMemberLayoutItem &Layout =
+      static_cast<DataMemberLayoutItem &>(*CurrentItem);
+
+  VariableDumper VarDumper(Printer);
+  VarDumper.start(Symbol, ClassOffsetZero);
+
+  if (Layout.hasUDTLayout()) {
+    Printer.Indent();
+    PrettyClassLayoutGraphicalDumper TypeDumper(Printer, ClassOffsetZero);
+    TypeDumper.start(Layout.getUDTLayout());
+    Printer.Unindent();
+  }
+
+  DumpedAnything = true;
+}
 
 void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+  assert(CurrentItem != nullptr);
+
+  VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
+
+  VariableDumper VarDumper(Printer);
+  VarDumper.start(Symbol, ClassOffsetZero);
+
+  Printer.Indent();
+  uint32_t Index = 0;
+  for (auto &Func : Layout.funcs()) {
+    Printer.NewLine();
+    std::string Name = Func->getName();
+    auto ParentClass =
+        unique_dyn_cast<PDBSymbolTypeUDT>(Func->getClassParent());
+    assert(ParentClass);
+    WithColor(Printer, PDB_ColorItem::Address).get() << " [" << Index << "] ";
+    WithColor(Printer, PDB_ColorItem::Identifier).get()
+        << "&" << ParentClass->getName();
+    Printer << "::";
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+    ++Index;
+  }
+  Printer.Unindent();
+
+  DumpedAnything = true;
 }

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h Thu Apr 13 16:11:00 2017
@@ -18,22 +18,29 @@ namespace llvm {
 
 namespace pdb {
 
-class ClassLayout;
+class UDTLayoutBase;
+class StorageItemBase;
 class LinePrinter;
 
 class PrettyClassLayoutGraphicalDumper : public PDBSymDumper {
 public:
-  explicit PrettyClassLayoutGraphicalDumper(LinePrinter &P);
+  PrettyClassLayoutGraphicalDumper(LinePrinter &P, uint32_t InitialOffset);
 
-  bool start(const ClassLayout &Layout);
+  bool start(const UDTLayoutBase &Layout);
 
   void dump(const PDBSymbolTypeBaseClass &Symbol) override;
   void dump(const PDBSymbolData &Symbol) override;
-  void dump(const PDBSymbolTypeEnum &Symbol) override;
-  void dump(const PDBSymbolFunc &Symbol) override;
-  void dump(const PDBSymbolTypeTypedef &Symbol) override;
-  void dump(const PDBSymbolTypeUDT &Symbol) override;
   void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+private:
+  void printPaddingRow(uint32_t Amount);
+
+  LinePrinter &Printer;
+
+  StorageItemBase *CurrentItem = nullptr;
+  uint32_t ClassOffsetZero = 0;
+  uint32_t CurrentAbsoluteOffset = 0;
+  bool DumpedAnything = false;
 };
 }
 }

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassLayoutTextDumper.cpp Thu Apr 13 16:11:00 2017
@@ -38,6 +38,8 @@ bool PrettyClassLayoutTextDumper::start(
       opts::pretty::ClassDefinitionFormat::Standard) {
     for (auto &Other : Layout.other_items())
       Other->dump(*this);
+    for (auto &Func : Layout.funcs())
+      Func->dump(*this);
   }
 
   const BitVector &UseMap = Layout.usedBytes();
@@ -101,9 +103,6 @@ void PrettyClassLayoutTextDumper::dump(c
 }
 
 void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeEnum &Symbol) {
-  if (Printer.IsTypeExcluded(Symbol.getName()))
-    return;
-
   DumpedAnything = true;
   Printer.NewLine();
   EnumDumper Dumper(Printer);
@@ -111,9 +110,6 @@ void PrettyClassLayoutTextDumper::dump(c
 }
 
 void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
-  if (Printer.IsTypeExcluded(Symbol.getName()))
-    return;
-
   DumpedAnything = true;
   Printer.NewLine();
   TypedefDumper Dumper(Printer);

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp Thu Apr 13 16:11:00 2017
@@ -22,24 +22,82 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
 
 using namespace llvm;
 using namespace llvm::pdb;
 
+using LayoutPtr = std::unique_ptr<ClassLayout>;
+
+typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
+
+static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->getUDTName() < S2->getUDTName();
+}
+
+static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->getClassSize() < S2->getClassSize();
+}
+
+static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->deepPaddingSize() < S2->deepPaddingSize();
+}
+
+static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
+  switch (Mode) {
+  case opts::pretty::ClassSortMode::Name:
+    return CompareNames;
+  case opts::pretty::ClassSortMode::Size:
+    return CompareSizes;
+  case opts::pretty::ClassSortMode::Padding:
+    return ComparePadding;
+  default:
+    return nullptr;
+  }
+}
+
 template <typename Enumerator>
-static std::vector<std::unique_ptr<PDBSymbolTypeUDT>>
-filterClassDefs(LinePrinter &Printer, Enumerator &E) {
-  std::vector<std::unique_ptr<PDBSymbolTypeUDT>> Filtered;
+static std::vector<std::unique_ptr<ClassLayout>>
+filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
+                       uint32_t UnfilteredCount) {
+  std::vector<std::unique_ptr<ClassLayout>> Filtered;
+
+  Filtered.reserve(UnfilteredCount);
+  CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
+
+  uint32_t Examined = 0;
+  uint32_t Discarded = 0;
   while (auto Class = E.getNext()) {
-    if (Class->getUnmodifiedTypeId() != 0)
+    ++Examined;
+    if (Examined % 10000 == 0) {
+      outs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
+                        Examined, UnfilteredCount, Discarded);
+      outs().flush();
+    }
+
+    if (Class->getUnmodifiedTypeId() != 0) {
+      ++Discarded;
+      continue;
+    }
+
+    if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
+      ++Discarded;
       continue;
+    }
 
-    if (Printer.IsTypeExcluded(Class->getName()))
+    auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
+    if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
+      ++Discarded;
       continue;
+    }
 
-    Filtered.push_back(std::move(Class));
+    Filtered.push_back(std::move(Layout));
   }
 
+  if (Comp)
+    std::sort(Filtered.begin(), Filtered.end(), Comp);
   return Filtered;
 }
 
@@ -70,20 +128,52 @@ void TypeDumper::start(const PDBSymbolEx
 
   if (opts::pretty::Classes) {
     auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
-    auto Filtered = filterClassDefs(Printer, *Classes);
-
-    Printer.NewLine();
-    uint32_t Shown = Filtered.size();
     uint32_t All = Classes->getChildCount();
 
+    Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
+
+    bool Precompute = false;
+    Precompute =
+        (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
+
+    // If we're using no sort mode, then we can start getting immediate output
+    // from the tool by just filtering as we go, rather than processing
+    // everything up front so that we can sort it.  This makes the tool more
+    // responsive.  So only precompute the filtered/sorted set of classes if
+    // necessary due to the specified options.
+    std::vector<LayoutPtr> Filtered;
+    uint32_t Shown = All;
+    if (Precompute) {
+      Filtered = filterAndSortClassDefs(Printer, *Classes, All);
+
+      Shown = Filtered.size();
+    }
+
     Printer << ": (Showing " << Shown << " items";
     if (Shown < All)
       Printer << ", " << (All - Shown) << " filtered";
     Printer << ")";
     Printer.Indent();
-    for (auto &Class : Filtered)
-      Class->dump(*this);
+
+    // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
+    // the DIA enumerator and filter on the fly.
+    if (Precompute) {
+      for (auto &Class : Filtered)
+        dumpClassLayout(*Class);
+    } else {
+      while (auto Class = Classes->getNext()) {
+        if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
+          continue;
+
+        auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
+        if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
+          continue;
+
+        dumpClassLayout(*Layout);
+      }
+    }
+
     Printer.Unindent();
   }
 }
@@ -91,7 +181,7 @@ void TypeDumper::start(const PDBSymbolEx
 void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
   assert(opts::pretty::Enums);
 
-  if (Printer.IsTypeExcluded(Symbol.getName()))
+  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
     return;
   // Dump member enums when dumping their class definition.
   if (nullptr != Symbol.getClassParent())
@@ -105,7 +195,7 @@ void TypeDumper::dump(const PDBSymbolTyp
 void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
   assert(opts::pretty::Typedefs);
 
-  if (Printer.IsTypeExcluded(Symbol.getName()))
+  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
     return;
 
   Printer.NewLine();
@@ -113,15 +203,15 @@ void TypeDumper::dump(const PDBSymbolTyp
   Dumper.start(Symbol);
 }
 
-void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
   assert(opts::pretty::Classes);
 
   if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
     Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
-    WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getUDTName();
   } else {
     ClassDefinitionDumper Dumper(Printer);
-    Dumper.start(Symbol);
+    Dumper.start(Class);
   }
 }

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.h Thu Apr 13 16:11:00 2017
@@ -15,6 +15,7 @@
 namespace llvm {
 namespace pdb {
 class LinePrinter;
+class ClassLayout;
 
 class TypeDumper : public PDBSymDumper {
 public:
@@ -24,7 +25,8 @@ public:
 
   void dump(const PDBSymbolTypeEnum &Symbol) override;
   void dump(const PDBSymbolTypeTypedef &Symbol) override;
-  void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+  void dumpClassLayout(const ClassLayout &Class);
 
 private:
   LinePrinter &Printer;

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp Thu Apr 13 16:11:00 2017
@@ -35,7 +35,7 @@ using namespace llvm::pdb;
 VariableDumper::VariableDumper(LinePrinter &P)
     : PDBSymDumper(true), Printer(P) {}
 
-void VariableDumper::start(const PDBSymbolData &Var) {
+void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) {
   if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
     return;
   if (Printer.IsSymbolExcluded(Var.getName()))
@@ -68,16 +68,16 @@ void VariableDumper::start(const PDBSymb
     Printer.NewLine();
     Printer << "data ";
     WithColor(Printer, PDB_ColorItem::Offset).get()
-        << "+" << format_hex(Var.getOffset(), 4) << " [sizeof=" << Length
-        << "] ";
+        << "+" << format_hex(Offset + Var.getOffset(), 4)
+        << " [sizeof=" << Length << "] ";
     dumpSymbolTypeAndName(*VarType, Var.getName());
     break;
   case PDB_LocType::BitField:
     Printer.NewLine();
     Printer << "data ";
     WithColor(Printer, PDB_ColorItem::Offset).get()
-        << "+" << format_hex(Var.getOffset(), 4) << " [sizeof=" << Length
-        << "] ";
+        << "+" << format_hex(Offset + Var.getOffset(), 4)
+        << " [sizeof=" << Length << "] ";
     dumpSymbolTypeAndName(*VarType, Var.getName());
     Printer << " : ";
     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
@@ -91,17 +91,15 @@ void VariableDumper::start(const PDBSymb
   }
 }
 
-void VariableDumper::start(const PDBSymbolTypeVTable &Var) {
+void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) {
   Printer.NewLine();
-  Printer << "data ";
+  Printer << "vfptr ";
   auto VTableType = cast<PDBSymbolTypePointer>(Var.getType());
   uint32_t PointerSize = VTableType->getLength();
 
   WithColor(Printer, PDB_ColorItem::Offset).get()
-      << "+" << format_hex(Var.getOffset(), 4) << " [sizeof=" << PointerSize
-      << "] ";
-
-  WithColor(Printer, PDB_ColorItem::Identifier).get() << " __vfptr";
+      << "+" << format_hex(Offset + Var.getOffset(), 4)
+      << " [sizeof=" << PointerSize << "] ";
 }
 
 void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h Thu Apr 13 16:11:00 2017
@@ -24,8 +24,8 @@ class VariableDumper : public PDBSymDump
 public:
   VariableDumper(LinePrinter &P);
 
-  void start(const PDBSymbolData &Var);
-  void start(const PDBSymbolTypeVTable &Var);
+  void start(const PDBSymbolData &Var, uint32_t Offset = 0);
+  void start(const PDBSymbolTypeVTable &Var, uint32_t Offset = 0);
 
   void dump(const PDBSymbolTypeArray &Symbol) override;
   void dump(const PDBSymbolTypeBuiltin &Symbol) override;

Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Thu Apr 13 16:11:00 2017
@@ -122,15 +122,27 @@ cl::opt<bool> Enums("enums", cl::desc("D
                     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
 cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<ClassSortMode> ClassOrder(
+    "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
+    cl::values(clEnumValN(ClassSortMode::None, "none",
+                          "Undefined / no particular sort order"),
+               clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
+               clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
+               clEnumValN(ClassSortMode::Padding, "padding",
+                          "Sort classes by amount of padding")),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
 cl::opt<ClassDefinitionFormat> ClassFormat(
     "class-definitions", cl::desc("Class definition format"),
     cl::init(ClassDefinitionFormat::Standard),
     cl::values(
         clEnumValN(ClassDefinitionFormat::Standard, "all-members",
                    "Display all class members including data, constants, "
-                   "typedefs, etc"),
+                   "typedefs, functions, etc"),
         clEnumValN(ClassDefinitionFormat::Layout, "layout-members",
                    "Only display members that contribute to class size."),
+        clEnumValN(ClassDefinitionFormat::Graphical, "graphical",
+                   "Display graphical representation of each class's layout."),
         clEnumValN(ClassDefinitionFormat::None, "none",
                    "Don't display class definitions")),
     cl::cat(TypeCategory), cl::sub(PrettySubcommand));
@@ -173,10 +185,14 @@ cl::list<std::string> IncludeCompilands(
     "include-compilands",
     cl::desc("Include only compilands those which match a regular expression"),
     cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
-cl::opt<bool> OnlyPaddingClasses(
-    "only-padding-classes", cl::desc("When dumping classes, only display those "
-                                     "with non-zero amounts of padding bytes"),
-    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> SizeThreshold(
+    "min-type-size", cl::desc("Displays only those types which are greater "
+                              "than or equal to the specified size."),
+    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> PaddingThreshold(
+    "min-class-padding", cl::desc("Displays only those classes which have at "
+                                  "least the specified amount of padding."),
+    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
 
 cl::opt<bool> ExcludeCompilerGenerated(
     "no-compiler-generated",

Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h?rev=300258&r1=300257&r2=300258&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h Thu Apr 13 16:11:00 2017
@@ -19,6 +19,7 @@ namespace opts {
 namespace pretty {
 
 enum class ClassDefinitionFormat { None, Layout, Graphical, Standard };
+enum class ClassSortMode { None, Name, Size, Padding };
 
 extern llvm::cl::opt<bool> Compilands;
 extern llvm::cl::opt<bool> Symbols;
@@ -36,7 +37,9 @@ extern llvm::cl::list<std::string> Exclu
 extern llvm::cl::list<std::string> IncludeTypes;
 extern llvm::cl::list<std::string> IncludeSymbols;
 extern llvm::cl::list<std::string> IncludeCompilands;
-extern llvm::cl::opt<bool> OnlyPaddingClasses;
+extern llvm::cl::opt<ClassSortMode> ClassOrder;
+extern llvm::cl::opt<uint32_t> SizeThreshold;
+extern llvm::cl::opt<uint32_t> PaddingThreshold;
 extern llvm::cl::opt<ClassDefinitionFormat> ClassFormat;
 }
 




More information about the llvm-commits mailing list