[llvm] r300133 - [llvm-pdbdump] More advanced class definition dumping.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 12 16:18:23 PDT 2017


Author: zturner
Date: Wed Apr 12 18:18:21 2017
New Revision: 300133

URL: http://llvm.org/viewvc/llvm-project?rev=300133&view=rev
Log:
[llvm-pdbdump] More advanced class definition dumping.

Previously the dumping of class definitions was very primitive,
and it made it hard to do more than the most trivial of output
formats when dumping.  As such, we would only dump one line for
each field, and then dump non-layout items like nested types
and enums.

With this patch, we do a complete analysis of the object
hierarchy including aggregate types, bases, virtual bases,
vftable analysis, etc.  The only immediately visible effects
of this are that a) we can now dump a line for the vfptr where
before we would treat that as padding, and b) we now don't
treat virtual bases that come at the end of a class as padding
since we have a more detailed analysis of the class's storage
usage.

In subsequent patches, we should be able to use this analysis
to display a complete graphical view of a class's layout including
recursing arbitrarily deep into an object's base class / aggregate
member hierarchy.

Added:
    llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h
    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   (with props)
    llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
    llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIASession.h
    llvm/trunk/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
    llvm/trunk/include/llvm/DebugInfo/PDB/IPDBSession.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeSession.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbol.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
    llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
    llvm/trunk/include/llvm/Support/Casting.h
    llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp
    llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/PDBSymbolExe.cpp
    llvm/trunk/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
    llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
    llvm/trunk/test/DebugInfo/PDB/Inputs/symbolformat.pdb
    llvm/trunk/test/tools/llvm-pdbdump/class-layout.test
    llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test
    llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
    llvm/trunk/tools/llvm-pdbdump/PrettyFunctionDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/PrettyTypedefDumper.cpp
    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
    llvm/trunk/unittests/DebugInfo/PDB/PDBApiTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h Wed Apr 12 18:18:21 2017
@@ -102,6 +102,7 @@ public:
   uint32_t getVirtualBaseDispIndex() const override;
   uint32_t getVirtualBaseOffset() const override;
   uint32_t getVirtualTableShapeId() const override;
+  std::unique_ptr<PDBSymbolTypeVTable> getVirtualBaseTableType() const override;
   PDB_DataKind getDataKind() const override;
   PDB_SymType getSymTag() const override;
   PDB_UniqueId getGuid() const override;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIASession.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIASession.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIASession.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIASession.h Wed Apr 12 18:18:21 2017
@@ -31,7 +31,7 @@ public:
 
   uint64_t getLoadAddress() const override;
   void setLoadAddress(uint64_t Address) override;
-  std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
+  std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
   std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
 
   std::unique_ptr<PDBSymbol>

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h Wed Apr 12 18:18:21 2017
@@ -21,6 +21,9 @@ class raw_ostream;
 
 namespace pdb {
 
+class PDBSymbolTypeVTable;
+class PDBSymbolTypeVTableShape;
+
 /// IPDBRawSymbol defines an interface used to represent an arbitrary symbol.
 /// It exposes a monolithic interface consisting of accessors for the union of
 /// all properties that are valid for any symbol type.  This interface is then
@@ -110,6 +113,8 @@ public:
   virtual Variant getValue() const = 0;
   virtual uint32_t getVirtualBaseDispIndex() const = 0;
   virtual uint32_t getVirtualBaseOffset() const = 0;
+  virtual std::unique_ptr<PDBSymbolTypeVTable>
+  getVirtualBaseTableType() const = 0;
   virtual uint32_t getVirtualTableShapeId() const = 0;
   virtual PDB_DataKind getDataKind() const = 0;
   virtual PDB_SymType getSymTag() const = 0;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/IPDBSession.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/IPDBSession.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/IPDBSession.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/IPDBSession.h Wed Apr 12 18:18:21 2017
@@ -29,20 +29,12 @@ public:
 
   virtual uint64_t getLoadAddress() const = 0;
   virtual void setLoadAddress(uint64_t Address) = 0;
-  virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() = 0;
+  virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() const = 0;
   virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0;
 
   template <typename T>
   std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const {
-    auto Symbol(getSymbolById(SymbolId));
-    if (!Symbol)
-      return nullptr;
-
-    T *ConcreteSymbol = dyn_cast<T>(Symbol.get());
-    if (!ConcreteSymbol)
-      return nullptr;
-    (void)Symbol.release();
-    return std::unique_ptr<T>(ConcreteSymbol);
+    return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
   }
 
   virtual std::unique_ptr<PDBSymbol>

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h Wed Apr 12 18:18:21 2017
@@ -101,6 +101,7 @@ public:
   uint32_t getVirtualBaseDispIndex() const override;
   uint32_t getVirtualBaseOffset() const override;
   uint32_t getVirtualTableShapeId() const override;
+  std::unique_ptr<PDBSymbolTypeVTable> getVirtualBaseTableType() const override;
   PDB_DataKind getDataKind() const override;
   PDB_SymType getSymTag() const override;
   PDB_UniqueId getGuid() const override;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeSession.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeSession.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeSession.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeSession.h Wed Apr 12 18:18:21 2017
@@ -32,7 +32,7 @@ public:
 
   uint64_t getLoadAddress() const override;
   void setLoadAddress(uint64_t Address) override;
-  std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
+  std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
   std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
 
   std::unique_ptr<PDBSymbol>

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbol.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbol.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbol.h Wed Apr 12 18:18:21 2017
@@ -62,6 +62,7 @@ class PDBSymbol {
 protected:
   PDBSymbol(const IPDBSession &PDBSession,
             std::unique_ptr<IPDBRawSymbol> Symbol);
+  PDBSymbol(PDBSymbol &Symbol);
 
 public:
   static std::unique_ptr<PDBSymbol>
@@ -91,12 +92,6 @@ public:
     return Enumerator->getNext();
   }
 
-  template <typename T> T *cast() { return llvm::dyn_cast<T>(this); }
-
-  template <typename T> const T *cast() const {
-    return llvm::dyn_cast<T>(this);
-  }
-
   std::unique_ptr<PDBSymbol> clone() const;
 
   template <typename T>
@@ -128,18 +123,11 @@ protected:
 
   template <typename ConcreteType>
   std::unique_ptr<ConcreteType> getConcreteSymbolByIdHelper(uint32_t Id) const {
-    auto Sym = getSymbolByIdHelper(Id);
-    if (!Sym)
-      return nullptr;
-    ConcreteType *Result = Sym->cast<ConcreteType>();
-    if (!Result)
-      return nullptr;
-    Sym.release();
-    return std::unique_ptr<ConcreteType>(Result);
+    return unique_dyn_cast_or_null<ConcreteType>(getSymbolByIdHelper(Id));
   }
 
   const IPDBSession &Session;
-  const std::unique_ptr<IPDBRawSymbol> RawSymbol;
+  std::unique_ptr<IPDBRawSymbol> RawSymbol;
 };
 
 } // namespace llvm

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolExe.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolExe.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolExe.h Wed Apr 12 18:18:21 2017
@@ -37,6 +37,8 @@ public:
   FORWARD_SYMBOL_METHOD(getSignature)
   FORWARD_SYMBOL_METHOD(getSymbolsFileName)
 
+  uint32_t getPointerByteSize() const;
+
 private:
   void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType,
                     int Indent) const;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h Wed Apr 12 18:18:21 2017
@@ -13,6 +13,9 @@
 #include "PDBSymbol.h"
 #include "PDBTypes.h"
 
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+
 namespace llvm {
 
 class raw_ostream;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h Wed Apr 12 18:18:21 2017
@@ -10,7 +10,9 @@
 #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
 #define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
 
+#include "IPDBSession.h"
 #include "PDBSymbol.h"
+#include "PDBSymbolTypeBaseClass.h"
 #include "PDBTypes.h"
 
 namespace llvm {
@@ -18,11 +20,17 @@ namespace llvm {
 class raw_ostream;
 
 namespace pdb {
+
 class PDBSymbolTypeUDT : public PDBSymbol {
 public:
   PDBSymbolTypeUDT(const IPDBSession &PDBSession,
                    std::unique_ptr<IPDBRawSymbol> UDTSymbol);
 
+  std::unique_ptr<PDBSymbolTypeUDT> clone() const {
+    return getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+        getSymIndexId());
+  }
+
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT)
 
   void dump(PDBSymDumper &Dumper) const override;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h Wed Apr 12 18:18:21 2017
@@ -28,6 +28,7 @@ public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getClassParent)
+  FORWARD_SYMBOL_METHOD(getOffset)
   FORWARD_SYMBOL_METHOD(isConstType)
   FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
   FORWARD_SYMBOL_ID_METHOD(getType)

Added: llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h?rev=300133&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/UDTLayout.h Wed Apr 12 18:18:21 2017
@@ -0,0 +1,145 @@
+//===- UDTLayout.h - UDT layout info ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
+#define LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+
+#include <list>
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace pdb {
+
+class PDBSymTypeBaseClass;
+class PDBSymbolData;
+class PDBSymbolTypeUDT;
+class PDBSymbolTypeVTable;
+
+class ClassLayout;
+class BaseClassLayout;
+class StorageItemBase;
+class UDTLayoutBase;
+
+class StorageItemBase {
+public:
+  StorageItemBase(const UDTLayoutBase &Parent, const PDBSymbol &Symbol,
+                  const std::string &Name, uint32_t OffsetInParent,
+                  uint32_t Size);
+  virtual ~StorageItemBase() {}
+
+  virtual uint32_t deepPaddingSize() const;
+
+  const UDTLayoutBase &getParent() const { return Parent; }
+  StringRef getName() const { return Name; }
+  uint32_t getOffsetInParent() const { return OffsetInParent; }
+  uint32_t getSize() const { return SizeOf; }
+  const PDBSymbol &getSymbol() const { return Symbol; }
+
+protected:
+  const UDTLayoutBase &Parent;
+  const PDBSymbol &Symbol;
+  BitVector UsedBytes;
+  std::string Name;
+  uint32_t OffsetInParent = 0;
+  uint32_t SizeOf = 0;
+};
+
+class DataMemberLayoutItem : public StorageItemBase {
+public:
+  DataMemberLayoutItem(const UDTLayoutBase &Parent,
+                       std::unique_ptr<PDBSymbolData> DataMember);
+
+  virtual uint32_t deepPaddingSize() const;
+
+  const PDBSymbolData &getDataMember();
+
+private:
+  std::unique_ptr<PDBSymbolData> DataMember;
+  std::unique_ptr<ClassLayout> UdtLayout;
+};
+
+class VTableLayoutItem : public StorageItemBase {
+public:
+  VTableLayoutItem(const UDTLayoutBase &Parent,
+                   std::unique_ptr<PDBSymbolTypeVTable> VTable);
+
+private:
+  std::unique_ptr<PDBSymbolTypeVTable> VTable;
+  std::vector<std::unique_ptr<PDBSymbolFunc>> VTableFuncs;
+};
+
+class UDTLayoutBase {
+public:
+  UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
+                uint32_t Size);
+
+  uint32_t shallowPaddingSize() const;
+  uint32_t deepPaddingSize() const;
+
+  const BitVector &usedBytes() const { return UsedBytes; }
+
+  uint32_t getClassSize() const { return SizeOf; }
+
+  const PDBSymbol &getSymbol() const { return Symbol; }
+
+  ArrayRef<std::unique_ptr<StorageItemBase>> layout_items() const {
+    return ChildStorage;
+  }
+
+  ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const {
+    return NonStorageItems;
+  }
+
+protected:
+  void initializeChildren(const PDBSymbol &Sym);
+
+  void addChildToLayout(std::unique_ptr<StorageItemBase> Child);
+
+  uint32_t SizeOf = 0;
+  std::string Name;
+
+  const PDBSymbol &Symbol;
+  BitVector UsedBytes;
+  std::vector<std::unique_ptr<PDBSymbol>> NonStorageItems;
+  std::vector<std::unique_ptr<StorageItemBase>> ChildStorage;
+  std::vector<std::list<StorageItemBase *>> ChildrenPerByte;
+  std::vector<BaseClassLayout *> BaseClasses;
+  VTableLayoutItem *VTable = nullptr;
+};
+
+class ClassLayout : public UDTLayoutBase {
+public:
+  explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT);
+
+private:
+  std::unique_ptr<PDBSymbolTypeUDT> Type;
+};
+
+class BaseClassLayout : public UDTLayoutBase, public StorageItemBase {
+public:
+  BaseClassLayout(const UDTLayoutBase &Parent,
+                  std::unique_ptr<PDBSymbolTypeBaseClass> Base);
+
+private:
+  std::unique_ptr<PDBSymbolTypeBaseClass> Base;
+  bool IsVirtualBase;
+};
+}
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_UDTLAYOUT_H

Modified: llvm/trunk/include/llvm/Support/Casting.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Casting.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Casting.h (original)
+++ llvm/trunk/include/llvm/Support/Casting.h Wed Apr 12 18:18:21 2017
@@ -384,7 +384,7 @@ LLVM_NODISCARD inline auto unique_dyn_ca
     -> decltype(cast<X>(Val)) {
   if (!Val)
     return nullptr;
-  return unique_dyn_cast(Val);
+  return unique_dyn_cast<X, Y>(Val);
 }
 
 template <class X, class Y>

Modified: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt Wed Apr 12 18:18:21 2017
@@ -101,6 +101,7 @@ add_llvm_library(LLVMDebugInfoPDB
   PDBSymbolUnknown.cpp
   PDBSymbolUsingNamespace.cpp
   PDBSymDumper.cpp
+  UDTLayout.cpp
   ${PDB_IMPL_SOURCES}
 
   ADDITIONAL_HEADER_DIRS

Modified: llvm/trunk/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp Wed Apr 12 18:18:21 2017
@@ -14,6 +14,9 @@
 #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
 #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
 #include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -717,6 +720,18 @@ uint32_t DIARawSymbol::getVirtualTableSh
   return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId);
 }
 
+std::unique_ptr<PDBSymbolTypeVTable>
+DIARawSymbol::getVirtualBaseTableType() const {
+  CComPtr<IDiaSymbol> TableType;
+  if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType)
+    return nullptr;
+
+  auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType);
+  auto Pointer =
+      llvm::make_unique<PDBSymbolTypePointer>(Session, std::move(RawVT));
+  return unique_dyn_cast<PDBSymbolTypeVTable>(Pointer->getPointeeType());
+}
+
 PDB_DataKind DIARawSymbol::getDataKind() const {
   return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol,
                                                  &IDiaSymbol::get_dataKind);

Modified: llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp Wed Apr 12 18:18:21 2017
@@ -140,7 +140,7 @@ void DIASession::setLoadAddress(uint64_t
   Session->put_loadAddress(Address);
 }
 
-std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
+std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
   CComPtr<IDiaSymbol> GlobalScope;
   if (S_OK != Session->get_globalScope(&GlobalScope))
     return nullptr;

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp Wed Apr 12 18:18:21 2017
@@ -13,6 +13,8 @@
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -318,6 +320,11 @@ uint32_t NativeRawSymbol::getVirtualTabl
   return 0;
 }
 
+std::unique_ptr<PDBSymbolTypeVTable>
+NativeRawSymbol::getVirtualBaseTableType() const {
+  return nullptr;
+}
+
 PDB_DataKind NativeRawSymbol::getDataKind() const {
   return PDB_DataKind::Unknown;
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp Wed Apr 12 18:18:21 2017
@@ -70,8 +70,9 @@ uint64_t NativeSession::getLoadAddress()
 
 void NativeSession::setLoadAddress(uint64_t Address) {}
 
-std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
-  auto RawSymbol = llvm::make_unique<NativeExeSymbol>(*this);
+std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() const {
+  auto RawSymbol =
+      llvm::make_unique<NativeExeSymbol>(const_cast<NativeSession &>(*this));
   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
   std::unique_ptr<PDBSymbolExe> ExeSymbol(
     static_cast<PDBSymbolExe *>(PdbSymbol.release()));

Modified: llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/PDBSymbol.cpp Wed Apr 12 18:18:21 2017
@@ -54,6 +54,9 @@ PDBSymbol::PDBSymbol(const IPDBSession &
                      std::unique_ptr<IPDBRawSymbol> Symbol)
     : Session(PDBSession), RawSymbol(std::move(Symbol)) {}
 
+PDBSymbol::PDBSymbol(PDBSymbol &Symbol)
+    : Session(Symbol.Session), RawSymbol(std::move(Symbol.RawSymbol)) {}
+
 PDBSymbol::~PDBSymbol() = default;
 
 #define FACTORY_SYMTAG_CASE(Tag, Type)                                         \
@@ -100,12 +103,6 @@ PDBSymbol::create(const IPDBSession &PDB
   }
 }
 
-#define TRY_DUMP_TYPE(Type)                                                    \
-  if (const Type *DerivedThis = this->cast<Type>())                            \
-    Dumper.dump(OS, Indent, *DerivedThis);
-
-#define ELSE_TRY_DUMP_TYPE(Type, Dumper) else TRY_DUMP_TYPE(Type, Dumper)
-
 void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const {
   RawSymbol->dump(OS, Indent);
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/PDBSymbolExe.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/PDBSymbolExe.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/PDBSymbolExe.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/PDBSymbolExe.cpp Wed Apr 12 18:18:21 2017
@@ -10,6 +10,7 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
 
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
 
 #include <utility>
 
@@ -23,3 +24,13 @@ PDBSymbolExe::PDBSymbolExe(const IPDBSes
 }
 
 void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+uint32_t PDBSymbolExe::getPointerByteSize() const {
+  auto Pointer = findOneChild<PDBSymbolTypePointer>();
+  if (Pointer)
+    return Pointer->getLength();
+
+  if (getMachineType() == PDB_Machine::x86)
+    return 4;
+  return 8;
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp Wed Apr 12 18:18:21 2017
@@ -9,7 +9,15 @@
 
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
 
 #include <utility>
 

Added: llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp?rev=300133&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp (added)
+++ llvm/trunk/lib/DebugInfo/PDB/UDTLayout.cpp Wed Apr 12 18:18:21 2017
@@ -0,0 +1,194 @@
+//===- UDTLayout.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
+  const IPDBSession &Session = Symbol.getSession();
+  const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
+  uint32_t TypeId = RawSymbol.getTypeId();
+  return Session.getSymbolById(TypeId);
+}
+
+static uint32_t getTypeLength(const PDBSymbol &Symbol) {
+  auto SymbolType = getSymbolType(Symbol);
+  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
+
+  return RawType.getLength();
+}
+
+StorageItemBase::StorageItemBase(const UDTLayoutBase &Parent,
+                                 const PDBSymbol &Symbol,
+                                 const std::string &Name,
+                                 uint32_t OffsetInParent, uint32_t Size)
+    : Parent(Parent), Symbol(Symbol), Name(Name), SizeOf(Size),
+      OffsetInParent(OffsetInParent) {
+  UsedBytes.resize(SizeOf, true);
+}
+
+uint32_t StorageItemBase::deepPaddingSize() const {
+  // sizeof(Field) - sizeof(typeof(Field)) is trailing padding.
+  return SizeOf - getTypeLength(Symbol);
+}
+
+DataMemberLayoutItem::DataMemberLayoutItem(
+    const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> DataMember)
+    : StorageItemBase(Parent, *DataMember, DataMember->getName(),
+                      DataMember->getOffset(), getTypeLength(*DataMember)),
+      DataMember(std::move(DataMember)) {
+  auto Type = this->DataMember->getType();
+  if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
+    // UDT data members might have padding in between fields, but otherwise
+    // a member should occupy its entire storage.
+    UsedBytes.resize(SizeOf, false);
+    UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
+  }
+}
+
+const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
+  return *dyn_cast<PDBSymbolData>(&Symbol);
+}
+
+uint32_t DataMemberLayoutItem::deepPaddingSize() const {
+  uint32_t Result = StorageItemBase::deepPaddingSize();
+  if (UdtLayout)
+    Result += UdtLayout->deepPaddingSize();
+  return Result;
+}
+
+VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
+                                   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();
+
+  if (auto Shape = unique_dyn_cast<PDBSymbolTypeVTableShape>(
+          VTableType->getPointeeType())) {
+    VTableFuncs.resize(Shape->getCount());
+
+    auto ParentFunctions = Parent.getSymbol().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,
+                             uint32_t Size)
+    : Symbol(Symbol), Name(Name), SizeOf(Size) {
+  UsedBytes.resize(Size);
+  ChildrenPerByte.resize(Size);
+  initializeChildren(Symbol);
+}
+
+ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
+    : UDTLayoutBase(*UDT, UDT->getName(), UDT->getLength()),
+      Type(std::move(UDT)) {}
+
+BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
+                                 std::unique_ptr<PDBSymbolTypeBaseClass> Base)
+    : UDTLayoutBase(*Base, Base->getName(), Base->getLength()),
+      StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(),
+                      Base->getLength()),
+      Base(std::move(Base)) {
+  IsVirtualBase = this->Base->isVirtualBaseClass();
+}
+
+uint32_t UDTLayoutBase::shallowPaddingSize() const {
+  return UsedBytes.size() - UsedBytes.count();
+}
+
+uint32_t UDTLayoutBase::deepPaddingSize() const {
+  uint32_t Result = shallowPaddingSize();
+  for (auto &Child : ChildStorage)
+    Result += Child->deepPaddingSize();
+  return Result;
+}
+
+void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
+  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)) {
+      auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base));
+      BaseClasses.push_back(BL.get());
+
+      addChildToLayout(std::move(BL));
+      continue;
+    }
+
+    if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) {
+      auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT));
+
+      VTable = VTLayout.get();
+
+      addChildToLayout(std::move(VTLayout));
+      continue;
+    }
+
+    NonStorageItems.push_back(std::move(Child));
+  }
+}
+
+void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) {
+  uint32_t Begin = Child->getOffsetInParent();
+  uint32_t End = Begin + Child->getSize();
+  UsedBytes.set(Begin, End);
+  while (Begin != End) {
+    ChildrenPerByte[Begin].push_back(Child.get());
+    ++Begin;
+  }
+
+  auto Loc = std::upper_bound(
+      ChildStorage.begin(), ChildStorage.end(), Begin,
+      [](uint32_t Off, const std::unique_ptr<StorageItemBase> &Item) {
+        return Off < Item->getOffsetInParent();
+      });
+
+  ChildStorage.insert(Loc, std::move(Child));
+}
\ No newline at end of file

Modified: llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test Wed Apr 12 18:18:21 2017
@@ -32,14 +32,14 @@
 ; TYPES_FORMAT-DAG: typedef class A ClassAType
 
 ; TYPES_1: Classes
-; TYPES_1: struct A {
+; TYPES_1: struct A [sizeof = 4] {
 ; TYPES_1: virtual void PureFunc() = 0
 ; TYPES_1: virtual void VirtualFunc()
 ; TYPES_1: void RegularFunc()
 ; TYPES_1: }
 
 ; TYPES_2: Classes
-; TYPES_2: struct MemberTest {
+; TYPES_2: struct MemberTest [sizeof = 96] {
 ; TYPES_2: data +0x00 [sizeof=4] MemberTest::NestedEnum m_nested_enum
 ; TYPES_2: data +0x04 [sizeof=4] int m_typedef
 ; TYPES_2: data +0x08 [sizeof=1] bool m_bool

Modified: llvm/trunk/test/DebugInfo/PDB/Inputs/symbolformat.pdb
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/symbolformat.pdb?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
Binary files llvm/trunk/test/DebugInfo/PDB/Inputs/symbolformat.pdb (original) and llvm/trunk/test/DebugInfo/PDB/Inputs/symbolformat.pdb Wed Apr 12 18:18:21 2017 differ

Added: 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=300133&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp (added)
+++ llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp Wed Apr 12 18:18:21 2017
@@ -0,0 +1,122 @@
+// Compile with "cl /c /Zi /GR- SimplePaddingTest.cpp"
+// Link with "link SimplePaddingTest.obj /debug /nodefaultlib /entry:main"
+
+#include <stdint.h>
+
+extern "C" using at_exit_handler = void();
+
+int atexit(at_exit_handler handler) { return 0; }
+
+struct SimplePadNoPadding {
+  int32_t X;
+  int32_t Y;
+  // No padding anywhere, sizeof(T) = 8
+} A;
+
+struct SimplePadUnion {
+  union {
+    int32_t X;
+    int64_t Y;
+    struct {
+      int32_t X;
+      // 4 bytes of padding here
+      int64_t Y;
+    } Z;
+  };
+  // Since the padding occurs at a location that is occupied by other storage
+  // (namely the Y member), the storage will still be considered used, and so
+  // there will be no unused bytes in the larger class.  But in the debug
+  // info for the nested struct, we should see padding.
+  // sizeof(SimplePadUnion) == sizeof(Z) == 16
+} B;
+
+struct SimplePadNoPadding2 {
+  bool A;
+  bool B;
+  bool C;
+  bool D;
+  // No padding anywhere, sizeof(T) = 4
+} C;
+
+struct alignas(4) SimplePadFields1 {
+  char A;
+  char B;
+  char C;
+  // 1 byte of padding here, sizeof(T) = 4
+} E;
+
+struct SimplePadFields2 {
+  int32_t Y;
+  char X;
+} F;
+
+struct SimplePadBase {
+  // Make sure this class is 4 bytes, and the derived class requires 8 byte
+  // alignment, so that padding is inserted between base and derived.
+  int32_t X;
+  // No padding here
+} G;
+
+struct SimplePadDerived : public SimplePadBase {
+  // 4 bytes of padding here due to Y requiring 8 byte alignment.
+  // Thus, sizeof(T) = 16
+  int64_t Y;
+} H;
+
+struct SimplePadEmptyBase1 {};
+struct SimplePadEmptyBase2 {};
+
+struct SimplePadEmpty : public SimplePadEmptyBase1, SimplePadEmptyBase2 {
+  // Bases have to occupy at least 1 byte of storage, so this requires
+  // 2 bytes of padding, plus 1 byte for each base, yielding sizeof(T) = 8
+  int32_t X;
+} I;
+
+struct SimplePadVfptr {
+  virtual ~SimplePadVfptr() {}
+  static void operator delete(void *ptr, size_t sz) {}
+  int32_t X;
+} J;
+
+struct NonEmptyBase1 {
+  bool X;
+};
+
+struct NonEmptyBase2 {
+  bool Y;
+};
+
+struct SimplePadMultiInherit : public NonEmptyBase1, public NonEmptyBase2 {
+  // X and Y from the 2 bases will get squished together, leaving 2 bytes
+  // of padding necessary for proper alignment of an int32.
+  // Therefore, sizeof(T) = 2 + 2 + 4 = 8
+  int32_t X;
+} K;
+
+struct SimplePadMultiInherit2 : public SimplePadFields1, SimplePadFields2 {
+  // There should be 1 byte of padding after the first class, and
+  // 3 bytes of padding after the second class.
+  int32_t X;
+} L;
+
+struct OneLevelInherit : public NonEmptyBase1 {
+  short Y;
+};
+
+struct SimplePadTwoLevelInherit : public OneLevelInherit {
+  // OneLevelInherit has nested padding because of its base,
+  // and then padding again because of this class.  So each
+  // class should be 4 bytes, yielding sizeof(T) = 12.
+  int64_t Z;
+} M;
+
+struct SimplePadAggregate {
+  NonEmptyBase1 X;
+  int32_t Y;
+  // the presence of X will cause 3 bytes of padding to be injected.
+} N;
+
+int main(int argc, char **argv) {
+
+  return 0;
+}

Added: 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=300133&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: llvm/trunk/test/tools/llvm-pdbdump/class-layout.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/class-layout.test?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/class-layout.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/class-layout.test Wed Apr 12 18:18:21 2017
@@ -14,38 +14,39 @@
 ; GLOBALS_TEST-DAG: GlobalsTest::Enum GlobalsTest::EnumVar
 
 ; MEMBERS_TEST: ---TYPES---
-; MEMBERS_TEST: class MembersTest::A {
+; MEMBERS_TEST: class MembersTest::A [sizeof = 16] {
 ; MEMBERS_TEST-DAG: typedef int NestedTypedef
 ; MEMBERS_TEST-DAG: enum NestedEnum
 ; MEMBERS_TEST: void MemberFunc()
-; MEMBERS_TEST-DAG: int IntMemberVar
-; MEMBERS_TEST-DAG: double DoubleMemberVar
+; MEMBERS_TEST-DAG: data +0x00 [sizeof=4] int IntMemberVar
+; MEMBERS_TEST-NEXT: <padding> (4 bytes)
+; MEMBERS_TEST-NEXT: data +0x08 [sizeof=8] double DoubleMemberVar
 ; MEMBERS_TEST: }
 
 ; BASE_CLASS_A: ---TYPES---
-; BASE_CLASS_A: class BaseClassTest::A {}
+; BASE_CLASS_A: class BaseClassTest::A [sizeof = 1] {}
 
 ; BASE_CLASS_B: ---TYPES---
-; BASE_CLASS_B: class BaseClassTest::B
+; BASE_CLASS_B: class BaseClassTest::B [sizeof = 4]
 ; BASE_CLASS_B-NEXT: : public virtual BaseClassTest::A {
 
 ; BASE_CLASS_C: ---TYPES---
-; BASE_CLASS_C: class BaseClassTest::C
+; BASE_CLASS_C: class BaseClassTest::C [sizeof = 4]
 ; BASE_CLASS_C-NEXT: : public virtual BaseClassTest::A {
 
 ; BASE_CLASS_D: ---TYPES---
-; BASE_CLASS_D: class BaseClassTest::D
+; BASE_CLASS_D: class BaseClassTest::D [sizeof = 8]
 ; BASE_CLASS_D-DAG: protected BaseClassTest::B
 ; BASE_CLASS_D-DAG: private BaseClassTest::C
 ; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A
 
 ; UDT_KIND_TEST: ---TYPES---
-; UDT_KIND_TEST-DAG: union UdtKindTest::C {}
-; UDT_KIND_TEST-DAG: class UdtKindTest::B {}
-; UDT_KIND_TEST-DAG: struct UdtKindTest::A {}
+; UDT_KIND_TEST-DAG: union UdtKindTest::C [sizeof = 1] {}
+; UDT_KIND_TEST-DAG: class UdtKindTest::B [sizeof = 1] {}
+; UDT_KIND_TEST-DAG: struct UdtKindTest::A [sizeof = 1] {}
 
 ; BITFIELD_TEST: ---TYPES---
-; BITFIELD_TEST: struct BitFieldTest::A {
+; BITFIELD_TEST: struct BitFieldTest::A [sizeof = 8] {
 ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits1 : 1
 ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits2 : 2
 ; BITFIELD_TEST-NEXT: +0x00 [sizeof=4] int Bits3 : 3

Modified: llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test Wed Apr 12 18:18:21 2017
@@ -10,7 +10,7 @@
 
 ; MEMBER_ENUM: ---TYPES---
 ; MEMBER_ENUM: Classes:
-; MEMBER_ENUM: struct __vc_attributes::threadingAttribute {
+; MEMBER_ENUM: struct __vc_attributes::threadingAttribute [sizeof = 4] {
 ; MEMBER_ENUM-NEXT: enum threading_e {
 ; MEMBER_ENUM-NEXT: apartment = 1
 ; MEMBER_ENUM-NEXT: single = 2

Added: 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=300133&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test (added)
+++ llvm/trunk/test/tools/llvm-pdbdump/simple-padding.test Wed Apr 12 18:18:21 2017
@@ -0,0 +1,94 @@
+; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
+; 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/PrettyClassDefinitionDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp Wed Apr 12 18:18:21 2017
@@ -28,7 +28,8 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+
 #include "llvm/Support/Format.h"
 
 using namespace llvm;
@@ -37,58 +38,23 @@ using namespace llvm::pdb;
 ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
     : PDBSymDumper(true), Printer(P) {}
 
-static void analyzePadding(const PDBSymbolTypeUDT &Class, BitVector &Padding,
-                           uint32_t &FirstFieldOffset) {
-  Padding.resize(Class.getLength(), true);
-  auto Children = Class.findAllChildren<PDBSymbolData>();
-  bool IsFirst = true;
-  FirstFieldOffset = Class.getLength();
-
-  while (auto Data = Children->getNext()) {
-    // Ignore data members which are not relative to this.  Usually these are
-    // static data members or constexpr and occupy no space.  We also need to
-    // handle BitFields since the PDB doesn't consider them ThisRel, but they
-    // still occupy space in the record layout.
-    auto LocType = Data->getLocationType();
-    if (LocType != PDB_LocType::ThisRel && LocType != PDB_LocType::BitField)
-      continue;
-
-    uint64_t Start = Data->getOffset();
-    if (IsFirst) {
-      FirstFieldOffset = Start;
-      IsFirst = false;
-    }
-
-    auto VarType = Data->getType();
-    uint64_t Size = VarType->getRawSymbol().getLength();
-    Padding.reset(Start, Start + Size);
-  }
-
-  // Unmark anything that comes before the first field so it doesn't get
-  // counted as padding.  In reality this is going to be vptrs or base class
-  // members, but we don't correctly handle that yet.
-  // FIXME: Handle it.
-  Padding.reset(0, FirstFieldOffset);
-}
-
 void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
   assert(opts::pretty::ClassFormat !=
          opts::pretty::ClassDefinitionFormat::None);
 
   uint32_t Size = Class.getLength();
-  uint32_t FirstFieldOffset = 0;
-  BitVector Padding;
-  analyzePadding(Class, Padding, FirstFieldOffset);
 
-  if (opts::pretty::OnlyPaddingClasses && (Padding.count() == 0))
+  ClassLayout Layout(Class.clone());
+
+  if (opts::pretty::OnlyPaddingClasses && (Layout.shallowPaddingSize() == 0))
     return;
 
   Printer.NewLine();
-  WithColor(Printer, PDB_ColorItem::Comment).get() << "// sizeof = " << Size;
-  Printer.NewLine();
 
   WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
   WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+  WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
+                                                   << "]";
 
   auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
   if (Bases->getChildCount() > 0) {
@@ -111,60 +77,54 @@ void ClassDefinitionDumper::start(const
   }
 
   Printer << " {";
-  auto Children = Class.findAllChildren();
   Printer.Indent();
-  int DumpedCount = 0;
 
-  int NextPaddingByte = Padding.find_first();
-  while (auto Child = Children->getNext()) {
-    if (auto Data = llvm::dyn_cast<PDBSymbolData>(Child.get())) {
-      if (Data->getDataKind() == PDB_DataKind::Member && NextPaddingByte >= 0) {
-        // If there are padding bytes remaining, see if this field is the first
-        // to cross a padding boundary, and print a padding field indicator if
-        // so.
-        int Off = Data->getOffset();
-        if (Off > NextPaddingByte) {
-          uint32_t Amount = Off - NextPaddingByte;
-          Printer.NewLine();
-          WithColor(Printer, PDB_ColorItem::Padding).get()
-              << "<padding> (" << Amount << " bytes)";
-          assert(Padding.find_next_unset(NextPaddingByte) == Off);
-          NextPaddingByte = Padding.find_next(Off);
-        }
-      }
-    }
+  // Dump non-layout items first, but only if we're not in layout-only mode.
+  if (opts::pretty::ClassFormat !=
+      opts::pretty::ClassDefinitionFormat::Layout) {
+    for (auto &Other : Layout.other_items())
+      Other->dump(*this);
+  }
 
-    if (auto Func = Child->cast<PDBSymbolFunc>()) {
-      if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
-        continue;
-
-      if (Func->getLength() == 0 && !Func->isPureVirtual() &&
-          !Func->isIntroVirtualFunction())
-        continue;
+  const BitVector &UseMap = Layout.usedBytes();
+  int NextUnusedByte = Layout.usedBytes().find_first_unset();
+  // Next dump items which affect class layout.
+  for (auto &LayoutItem : Layout.layout_items()) {
+    if (NextUnusedByte >= 0) {
+      // If there are padding bytes remaining, see if this field is the first to
+      // cross a padding boundary, and print a padding field indicator if so.
+      int Off = LayoutItem->getOffsetInParent();
+      if (Off > NextUnusedByte) {
+        uint32_t Amount = Off - NextUnusedByte;
+        Printer.NewLine();
+        WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> ("
+                                                         << Amount << " bytes)";
+        assert(UseMap.find_next(NextUnusedByte) == Off);
+        NextUnusedByte = UseMap.find_next_unset(Off);
+      }
     }
-
-    ++DumpedCount;
-    Child->dump(*this);
+    LayoutItem->getSymbol().dump(*this);
   }
 
-  if (NextPaddingByte >= 0) {
-    uint32_t Amount = Size - NextPaddingByte;
+  if (NextUnusedByte >= 0 && Layout.getClassSize() > 1) {
+    uint32_t Amount = Layout.getClassSize() - NextUnusedByte;
     Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
                                                      << " bytes)";
+    DumpedAnything = true;
   }
+
   Printer.Unindent();
-  if (DumpedCount > 0)
+  if (DumpedAnything)
     Printer.NewLine();
   Printer << "}";
   Printer.NewLine();
-  if (Padding.count() > 0) {
-    APFloat Pct(100.0 * (double)Padding.count() /
-                (double)(Size - FirstFieldOffset));
+  if (Layout.deepPaddingSize() > 0) {
+    APFloat Pct(100.0 * (double)Layout.deepPaddingSize() / (double)Size);
     SmallString<8> PctStr;
     Pct.toString(PctStr, 4);
     WithColor(Printer, PDB_ColorItem::Padding).get()
-        << "Total padding " << Padding.count() << " bytes (" << PctStr
+        << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr
         << "% of class size)";
     Printer.NewLine();
   }
@@ -175,23 +135,35 @@ void ClassDefinitionDumper::dump(const P
 void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) {
   VariableDumper Dumper(Printer);
   Dumper.start(Symbol);
+  DumpedAnything = true;
 }
 
 void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) {
   if (Printer.IsSymbolExcluded(Symbol.getName()))
     return;
+  if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+    return;
+  if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
+      !Symbol.isIntroVirtualFunction())
+    return;
 
+  DumpedAnything = true;
   Printer.NewLine();
   FunctionDumper Dumper(Printer);
   Dumper.start(Symbol, FunctionDumper::PointerType::None);
 }
 
-void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {}
+void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+  VariableDumper Dumper(Printer);
+  Dumper.start(Symbol);
+  DumpedAnything = true;
+}
 
 void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
   if (Printer.IsTypeExcluded(Symbol.getName()))
     return;
 
+  DumpedAnything = true;
   Printer.NewLine();
   EnumDumper Dumper(Printer);
   Dumper.start(Symbol);
@@ -201,6 +173,7 @@ void ClassDefinitionDumper::dump(const P
   if (Printer.IsTypeExcluded(Symbol.getName()))
     return;
 
+  DumpedAnything = true;
   Printer.NewLine();
   TypedefDumper Dumper(Printer);
   Dumper.start(Symbol);

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h Wed Apr 12 18:18:21 2017
@@ -21,6 +21,8 @@
 #include <unordered_map>
 
 namespace llvm {
+class BitVector;
+
 namespace pdb {
 
 class LinePrinter;
@@ -40,6 +42,10 @@ public:
   void dump(const PDBSymbolTypeVTable &Symbol) override;
 
 private:
+  bool maybeDumpSymbol(std::unique_ptr<PDBSymbolData> Data,
+                       const BitVector &Padding, int &NextUnusedByte);
+  bool maybeDumpSymbol(std::unique_ptr<PDBSymbolFunc> Data);
+  bool DumpedAnything = false;
   LinePrinter &Printer;
 };
 }

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyFunctionDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyFunctionDumper.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyFunctionDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyFunctionDumper.cpp Wed Apr 12 18:18:21 2017
@@ -233,7 +233,7 @@ void FunctionDumper::dump(const PDBSymbo
   if (!PointeeType)
     return;
 
-  if (auto FuncSig = PointeeType->cast<PDBSymbolTypeFunctionSig>()) {
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
     FunctionDumper NestedDumper(Printer);
     PointerType Pointer =
         Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyTypeDumper.cpp Wed Apr 12 18:18:21 2017
@@ -26,6 +26,23 @@
 using namespace llvm;
 using namespace llvm::pdb;
 
+template <typename Enumerator>
+static std::vector<std::unique_ptr<PDBSymbolTypeUDT>>
+filterClassDefs(LinePrinter &Printer, Enumerator &E) {
+  std::vector<std::unique_ptr<PDBSymbolTypeUDT>> Filtered;
+  while (auto Class = E.getNext()) {
+    if (Class->getUnmodifiedTypeId() != 0)
+      continue;
+
+    if (Printer.IsTypeExcluded(Class->getName()))
+      continue;
+
+    Filtered.push_back(std::move(Class));
+  }
+
+  return Filtered;
+}
+
 TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
 
 void TypeDumper::start(const PDBSymbolExe &Exe) {
@@ -53,11 +70,19 @@ 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();
+
     WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
-    Printer << ": (" << Classes->getChildCount() << " items)";
+    Printer << ": (Showing " << Shown << " items";
+    if (Shown < All)
+      Printer << ", " << (All - Shown) << " filtered";
+    Printer << ")";
     Printer.Indent();
-    while (auto Class = Classes->getNext())
+    for (auto &Class : Filtered)
       Class->dump(*this);
     Printer.Unindent();
   }
@@ -91,11 +116,6 @@ void TypeDumper::dump(const PDBSymbolTyp
 void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
   assert(opts::pretty::Classes);
 
-  if (Symbol.getUnmodifiedTypeId() != 0)
-    return;
-  if (Printer.IsTypeExcluded(Symbol.getName()))
-    return;
-
   if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
     Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyTypedefDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyTypedefDumper.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyTypedefDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyTypedefDumper.cpp Wed Apr 12 18:18:21 2017
@@ -54,7 +54,7 @@ void TypedefDumper::dump(const PDBSymbol
   if (Symbol.isVolatileType())
     WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
   auto PointeeType = Symbol.getPointeeType();
-  if (auto FuncSig = PointeeType->cast<PDBSymbolTypeFunctionSig>()) {
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
     FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
     if (Symbol.isReference())
       Pointer = FunctionDumper::PointerType::Reference;

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.cpp Wed Apr 12 18:18:21 2017
@@ -91,6 +91,19 @@ void VariableDumper::start(const PDBSymb
   }
 }
 
+void VariableDumper::start(const PDBSymbolTypeVTable &Var) {
+  Printer.NewLine();
+  Printer << "data ";
+  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";
+}
+
 void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {
   auto ElementType = Symbol.getElementType();
   assert(ElementType);
@@ -157,12 +170,12 @@ void VariableDumper::dump(const PDBSymbo
   if (!PointeeType)
     return;
   PointeeType->dump(*this);
-  if (auto Func = PointeeType->cast<PDBSymbolTypeFunctionSig>()) {
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
     // A hack to get the calling convention in the right spot.
     Printer << " (";
-    PDB_CallingConv CC = Func->getCallingConvention();
+    PDB_CallingConv CC = FuncSig->getCallingConvention();
     WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
-  } else if (isa<PDBSymbolTypeArray>(PointeeType.get())) {
+  } else if (isa<PDBSymbolTypeArray>(PointeeType)) {
     Printer << " (";
   }
   Printer << (Symbol.isReference() ? "&" : "*");
@@ -177,8 +190,8 @@ void VariableDumper::dumpRight(const PDB
   assert(PointeeType);
   if (!PointeeType)
     return;
-  if (isa<PDBSymbolTypeFunctionSig>(PointeeType.get()) ||
-      isa<PDBSymbolTypeArray>(PointeeType.get())) {
+  if (isa<PDBSymbolTypeFunctionSig>(PointeeType) ||
+      isa<PDBSymbolTypeArray>(PointeeType)) {
     Printer << ")";
   }
   PointeeType->dumpRight(*this);

Modified: llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/PrettyVariableDumper.h Wed Apr 12 18:18:21 2017
@@ -25,6 +25,7 @@ public:
   VariableDumper(LinePrinter &P);
 
   void start(const PDBSymbolData &Var);
+  void start(const PDBSymbolTypeVTable &Var);
 
   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=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Wed Apr 12 18:18:21 2017
@@ -96,7 +96,7 @@ cl::SubCommand
                       "Analyze various aspects of a PDB's structure");
 
 cl::OptionCategory TypeCategory("Symbol Type Options");
-cl::OptionCategory FilterCategory("Filtering Options");
+cl::OptionCategory FilterCategory("Filtering and Sorting Options");
 cl::OptionCategory OtherOptions("Other Options");
 
 namespace pretty {
@@ -122,14 +122,17 @@ 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<ClassDefinitionFormat>
-    ClassFormat("class-definitions", cl::desc("Class definition format"),
-                cl::init(ClassDefinitionFormat::Standard),
-                cl::values(clEnumValN(ClassDefinitionFormat::Standard, "full",
-                                      "Display complete class definition"),
-                           clEnumValN(ClassDefinitionFormat::None, "none",
-                                      "Don't display class definitions")),
-                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, "full",
+                   "Display complete class definition"),
+        clEnumValN(ClassDefinitionFormat::Layout, "layout",
+                   "Only display members that contribute to class size."),
+        clEnumValN(ClassDefinitionFormat::None, "none",
+                   "Don't display class definitions")),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
 
 cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
                     cl::sub(PrettySubcommand));

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=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.h Wed Apr 12 18:18:21 2017
@@ -18,7 +18,7 @@ namespace opts {
 
 namespace pretty {
 
-enum class ClassDefinitionFormat { None, Standard };
+enum class ClassDefinitionFormat { None, Layout, Standard };
 
 extern llvm::cl::opt<bool> Compilands;
 extern llvm::cl::opt<bool> Symbols;

Modified: llvm/trunk/unittests/DebugInfo/PDB/PDBApiTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/PDB/PDBApiTest.cpp?rev=300133&r1=300132&r2=300133&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/PDB/PDBApiTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/PDB/PDBApiTest.cpp Wed Apr 12 18:18:21 2017
@@ -63,7 +63,7 @@ namespace {
 class MockSession : public IPDBSession {
   uint64_t getLoadAddress() const override { return 0; }
   void setLoadAddress(uint64_t Address) override {}
-  std::unique_ptr<PDBSymbolExe> getGlobalScope() override {
+  std::unique_ptr<PDBSymbolExe> getGlobalScope() const override {
     return nullptr;
   }
   std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override {
@@ -226,6 +226,7 @@ public:
   MOCK_SYMBOL_ACCESSOR(getMachineType)
   MOCK_SYMBOL_ACCESSOR(getThunkOrdinal)
   MOCK_SYMBOL_ACCESSOR(getLength)
+  MOCK_SYMBOL_ACCESSOR(getVirtualBaseTableType)
   MOCK_SYMBOL_ACCESSOR(getLiveRangeLength)
   MOCK_SYMBOL_ACCESSOR(getVirtualAddress)
   MOCK_SYMBOL_ACCESSOR(getUdtKind)




More information about the llvm-commits mailing list