summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp')
-rw-r--r--llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp131
1 files changed, 52 insertions, 79 deletions
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);
OpenPOWER on IntegriCloud