summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h1
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h2
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h5
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/IPDBSession.h12
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h1
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h2
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h18
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h2
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h3
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h8
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h1
-rw-r--r--llvm/include/llvm/DebugInfo/PDB/UDTLayout.h145
-rw-r--r--llvm/include/llvm/Support/Casting.h2
-rw-r--r--llvm/lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp15
-rw-r--r--llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp2
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp7
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp5
-rw-r--r--llvm/lib/DebugInfo/PDB/PDBSymbol.cpp9
-rw-r--r--llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp11
-rw-r--r--llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp8
-rw-r--r--llvm/lib/DebugInfo/PDB/UDTLayout.cpp194
-rw-r--r--llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test4
-rw-r--r--llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdbbin44032 -> 110592 bytes
-rw-r--r--llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp122
-rw-r--r--llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdbbin0 -> 110592 bytes
-rw-r--r--llvm/test/tools/llvm-pdbdump/class-layout.test23
-rw-r--r--llvm/test/tools/llvm-pdbdump/enum-layout.test2
-rw-r--r--llvm/test/tools/llvm-pdbdump/simple-padding.test94
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp131
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h6
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp2
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp34
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp2
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp23
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyVariableDumper.h1
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp21
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.h2
-rw-r--r--llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp3
39 files changed, 769 insertions, 155 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
index 1e40c46f8a2..c0633cbdfa5 100644
--- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 350442556be..3f5818631e7 100644
--- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -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>
diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index 49866b8bb2f..4c28e194bc7 100644
--- a/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
index 696736a907a..85d9fe12485 100644
--- a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -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>
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
index 655bed9ac17..cffb5d09d22 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index bbe207738e0..e6da266f796 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -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>
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
index 652f2136105..b114b7afb0b 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -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
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
index 5b3f50d153e..2c2d7466504 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
index 0924efb8aa9..d607a3d8117 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
index 47a4525a47b..e9e7fe8c986 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
@@ -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;
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
index 17612ff4606..e270c2b7eb9 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
@@ -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)
diff --git a/llvm/include/llvm/DebugInfo/PDB/UDTLayout.h b/llvm/include/llvm/DebugInfo/PDB/UDTLayout.h
new file mode 100644
index 00000000000..20b70340f33
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/UDTLayout.h
@@ -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
diff --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h
index 3a0c5536c01..89d2af052dc 100644
--- a/llvm/include/llvm/Support/Casting.h
+++ b/llvm/include/llvm/Support/Casting.h
@@ -384,7 +384,7 @@ LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &Val)
-> 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>
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 1295d2a19ce..f87a0b0a72e 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -101,6 +101,7 @@ add_llvm_library(LLVMDebugInfoPDB
PDBSymbolUnknown.cpp
PDBSymbolUsingNamespace.cpp
PDBSymDumper.cpp
+ UDTLayout.cpp
${PDB_IMPL_SOURCES}
ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 6182dab213c..5e8c0bdc171 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -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::getVirtualTableShapeId() const {
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);
diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
index 7077bda4a53..6ecf335812b 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -140,7 +140,7 @@ void DIASession::setLoadAddress(uint64_t Address) {
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;
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
index 4841ded7410..3aba35adb53 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -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::getVirtualTableShapeId() const {
return 0;
}
+std::unique_ptr<PDBSymbolTypeVTable>
+NativeRawSymbol::getVirtualBaseTableType() const {
+ return nullptr;
+}
+
PDB_DataKind NativeRawSymbol::getDataKind() const {
return PDB_DataKind::Unknown;
}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index 3a83a326cfe..7e6843bceb7 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -70,8 +70,9 @@ uint64_t NativeSession::getLoadAddress() const { return 0; }
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()));
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
index 2c8438f9c23..14eb6ba8ad8 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -54,6 +54,9 @@ PDBSymbol::PDBSymbol(const IPDBSession &PDBSession,
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 &PDBSession,
}
}
-#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);
}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
index b9fcac78c36..7417167b61a 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
@@ -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 IPDBSession &PDBSession,
}
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;
+}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
index 4a9a9ed5fda..15dc1535216 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
@@ -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>
diff --git a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp
new file mode 100644
index 00000000000..71443fe7587
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp
@@ -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
diff --git a/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test b/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
index 60a19534687..0bb3e001d3a 100644
--- a/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
+++ b/llvm/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
@@ -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
diff --git a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb
index 0e509f3a93c..9272f318258 100644
--- a/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb
+++ b/llvm/test/DebugInfo/PDB/Inputs/symbolformat.pdb
Binary files differ
diff --git a/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp b/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp
new file mode 100644
index 00000000000..b10839beea2
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.cpp
@@ -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;
+}
diff --git a/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb b/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb
new file mode 100644
index 00000000000..44207d60193
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/Inputs/SimplePaddingTest.pdb
Binary files differ
diff --git a/llvm/test/tools/llvm-pdbdump/class-layout.test b/llvm/test/tools/llvm-pdbdump/class-layout.test
index e2921d298fc..c0083d176ea 100644
--- a/llvm/test/tools/llvm-pdbdump/class-layout.test
+++ b/llvm/test/tools/llvm-pdbdump/class-layout.test
@@ -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
diff --git a/llvm/test/tools/llvm-pdbdump/enum-layout.test b/llvm/test/tools/llvm-pdbdump/enum-layout.test
index 21e1867175f..df447c65bba 100644
--- a/llvm/test/tools/llvm-pdbdump/enum-layout.test
+++ b/llvm/test/tools/llvm-pdbdump/enum-layout.test
@@ -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
diff --git a/llvm/test/tools/llvm-pdbdump/simple-padding.test b/llvm/test/tools/llvm-pdbdump/simple-padding.test
new file mode 100644
index 00000000000..4096d287a56
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbdump/simple-padding.test
@@ -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: }
diff --git a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
index b48ed23c1c7..2e1e54e4db1 100644
--- a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
@@ -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 PDBSymbolTypeUDT &Class) {
}
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);
- }
- }
- }
- if (auto Func = Child->cast<PDBSymbolFunc>()) {
- if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
- continue;
+ // 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 (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 PDBSymbolTypeBaseClass &Symbol) {}
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 PDBSymbolTypeTypedef &Symbol) {
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
+ DumpedAnything = true;
Printer.NewLine();
TypedefDumper Dumper(Printer);
Dumper.start(Symbol);
diff --git a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
index 8f0c35cba81..94ae07d345d 100644
--- a/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
+++ b/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h
@@ -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;
};
}
diff --git a/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp
index 0e0da026e56..b0be33c157c 100644
--- a/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/PrettyFunctionDumper.cpp
@@ -233,7 +233,7 @@ void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
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;
diff --git a/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp
index 12a47d24f79..2857b07078c 100644
--- a/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp
@@ -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 PDBSymbolExe &Exe) {
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 PDBSymbolTypeTypedef &Symbol) {
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 ";
diff --git a/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp
index 861f7e28b38..2d8e915d760 100644
--- a/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/PrettyTypedefDumper.cpp
@@ -54,7 +54,7 @@ void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
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;
diff --git a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp
index 65f0139dfbc..ef9a9b51bd0 100644
--- a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.cpp
@@ -91,6 +91,19 @@ void VariableDumper::start(const PDBSymbolData &Var) {
}
}
+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 PDBSymbolTypePointer &Symbol) {
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 PDBSymbolTypePointer &Symbol) {
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);
diff --git a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h
index eec389b1707..ba9fdb17655 100644
--- a/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h
+++ b/llvm/tools/llvm-pdbdump/PrettyVariableDumper.h
@@ -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;
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 8a749bab98e..a486c8a0730 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -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("Display enum types"),
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));
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
index a335d30c4cf..c572176f76d 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
@@ -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;
diff --git a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
index ba09a8e2842..6afe83cd90d 100644
--- a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
+++ b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
@@ -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)
OpenPOWER on IntegriCloud