diff options
Diffstat (limited to 'llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp')
| -rw-r--r-- | llvm/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp | 131 |
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); |

