1 //===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "PrettyClassLayoutGraphicalDumper.h"
12 #include "LinePrinter.h"
13 #include "PrettyClassDefinitionDumper.h"
14 #include "PrettyVariableDumper.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
19 #include "llvm/DebugInfo/PDB/UDTLayout.h"
20 #include "llvm/Support/Format.h"
23 using namespace llvm::pdb;
25 PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
26 LinePrinter &P, uint32_t InitialOffset)
27 : PDBSymDumper(true), Printer(P), ClassOffsetZero(InitialOffset),
28 CurrentAbsoluteOffset(InitialOffset) {}
30 bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
31 const BitVector &UseMap = Layout.usedBytes();
32 int NextPaddingByte = UseMap.find_first_unset();
34 for (auto &Item : Layout.layout_items()) {
35 // Calculate the absolute offset of the first byte of the next field.
36 uint32_t RelativeOffset = Item->getOffsetInParent();
37 CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
39 // Since there is storage there, it should be set! However, this might
40 // be an empty base, in which case it could extend outside the bounds of
42 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
43 assert(UseMap.test(RelativeOffset));
45 // If there is any remaining padding in this class, and the offset of the
46 // new item is after the padding, then we must have just jumped over some
47 // padding. Print a padding row and then look for where the next block
49 if ((NextPaddingByte >= 0) &&
50 (RelativeOffset > uint32_t(NextPaddingByte))) {
51 printPaddingRow(RelativeOffset - NextPaddingByte);
52 NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
56 CurrentItem = Item.get();
57 Item->getSymbol().dump(*this);
60 if (NextPaddingByte >= 0 && Layout.getClassSize() > 1) {
61 uint32_t Amount = Layout.getClassSize() - NextPaddingByte;
63 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
65 DumpedAnything = true;
68 return DumpedAnything;
71 void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
76 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
78 DumpedAnything = true;
81 void PrettyClassLayoutGraphicalDumper::dump(
82 const PDBSymbolTypeBaseClass &Symbol) {
83 assert(CurrentItem != nullptr);
86 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
88 std::string Label = Layout.isVirtualBase() ? "vbase" : "base";
89 Printer << Label << " ";
91 WithColor(Printer, PDB_ColorItem::Offset).get()
92 << "+" << format_hex(CurrentAbsoluteOffset, 4)
93 << " [sizeof=" << Layout.getSize() << "] ";
95 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
98 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
99 PrettyClassLayoutGraphicalDumper BaseDumper(Printer, ChildOffsetZero);
100 BaseDumper.start(Layout);
103 DumpedAnything = true;
106 void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
107 assert(CurrentItem != nullptr);
109 DataMemberLayoutItem &Layout =
110 static_cast<DataMemberLayoutItem &>(*CurrentItem);
112 VariableDumper VarDumper(Printer);
113 VarDumper.start(Symbol, ClassOffsetZero);
115 if (Layout.hasUDTLayout()) {
117 PrettyClassLayoutGraphicalDumper TypeDumper(Printer, ClassOffsetZero);
118 TypeDumper.start(Layout.getUDTLayout());
122 DumpedAnything = true;
125 void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
126 assert(CurrentItem != nullptr);
128 VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
130 VariableDumper VarDumper(Printer);
131 VarDumper.start(Symbol, ClassOffsetZero);
135 for (auto &Func : Layout.funcs()) {
137 std::string Name = Func->getName();
139 unique_dyn_cast<PDBSymbolTypeUDT>(Func->getClassParent());
141 WithColor(Printer, PDB_ColorItem::Address).get() << " [" << Index << "] ";
142 WithColor(Printer, PDB_ColorItem::Identifier).get()
143 << "&" << ParentClass->getName();
145 WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
150 DumpedAnything = true;