blob: f0385f198e0de91a06e7bb361d03da724878a8fb [file] [log] [blame]
Zachary Turner9e7dda32017-04-12 23:18:51 +00001//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "PrettyClassLayoutGraphicalDumper.h"
11
Zachary Turner4dc4f012017-04-13 21:11:00 +000012#include "LinePrinter.h"
13#include "PrettyClassDefinitionDumper.h"
14#include "PrettyVariableDumper.h"
15
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"
21
Zachary Turner9e7dda32017-04-12 23:18:51 +000022using namespace llvm;
23using namespace llvm::pdb;
24
25PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
Zachary Turner4dc4f012017-04-13 21:11:00 +000026 LinePrinter &P, uint32_t InitialOffset)
27 : PDBSymDumper(true), Printer(P), ClassOffsetZero(InitialOffset),
28 CurrentAbsoluteOffset(InitialOffset) {}
Zachary Turner9e7dda32017-04-12 23:18:51 +000029
Zachary Turner4dc4f012017-04-13 21:11:00 +000030bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
31 const BitVector &UseMap = Layout.usedBytes();
32 int NextPaddingByte = UseMap.find_first_unset();
33
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;
38
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
41 // the parent class.
42 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
43 assert(UseMap.test(RelativeOffset));
44
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
48 // of padding begins.
49 if ((NextPaddingByte >= 0) &&
50 (RelativeOffset > uint32_t(NextPaddingByte))) {
51 printPaddingRow(RelativeOffset - NextPaddingByte);
52 NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
53 }
54 }
55
Zachary Turner16901642017-04-24 17:47:24 +000056 CurrentItem = Item;
57 if (Item->isVBPtr()) {
58 VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
59
60 VariableDumper VarDumper(Printer);
61 VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
62 } else {
63 if (auto Sym = Item->getSymbol())
64 Sym->dump(*this);
65 }
66
67 if (Item->getLayoutSize() > 0) {
68 uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
69 NextPaddingByte = UseMap.find_next_unset(Prev);
70 }
Zachary Turner4dc4f012017-04-13 21:11:00 +000071 }
72
Zachary Turner16901642017-04-24 17:47:24 +000073 auto TailPadding = Layout.tailPadding();
74 if (TailPadding > 0) {
Zachary Turner4dc4f012017-04-13 21:11:00 +000075 Printer.NewLine();
Zachary Turner16901642017-04-24 17:47:24 +000076 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> ("
77 << TailPadding << " bytes)";
Zachary Turner4dc4f012017-04-13 21:11:00 +000078 DumpedAnything = true;
79 }
80
81 return DumpedAnything;
82}
83
84void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
85 if (Amount == 0)
86 return;
87
88 Printer.NewLine();
89 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
90 << " bytes)";
91 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +000092}
93
94void PrettyClassLayoutGraphicalDumper::dump(
Zachary Turner4dc4f012017-04-13 21:11:00 +000095 const PDBSymbolTypeBaseClass &Symbol) {
96 assert(CurrentItem != nullptr);
Zachary Turner9e7dda32017-04-12 23:18:51 +000097
Zachary Turner4dc4f012017-04-13 21:11:00 +000098 Printer.NewLine();
99 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
Zachary Turner9e7dda32017-04-12 23:18:51 +0000100
Zachary Turner16901642017-04-24 17:47:24 +0000101 std::string Label = "base";
102 if (Layout.isVirtualBase()) {
103 Label.insert(Label.begin(), 'v');
104 if (Layout.getBase().isIndirectVirtualBaseClass())
105 Label.insert(Label.begin(), 'i');
106 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000107 Printer << Label << " ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000108
Zachary Turner16901642017-04-24 17:47:24 +0000109 uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
110
Zachary Turner4dc4f012017-04-13 21:11:00 +0000111 WithColor(Printer, PDB_ColorItem::Offset).get()
Zachary Turner16901642017-04-24 17:47:24 +0000112 << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
113 << "] ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000114
Zachary Turner4dc4f012017-04-13 21:11:00 +0000115 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
Zachary Turner9e7dda32017-04-12 23:18:51 +0000116
Zachary Turner4dc4f012017-04-13 21:11:00 +0000117 Printer.Indent();
118 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
119 PrettyClassLayoutGraphicalDumper BaseDumper(Printer, ChildOffsetZero);
120 BaseDumper.start(Layout);
121 Printer.Unindent();
122
123 DumpedAnything = true;
124}
125
126void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
127 assert(CurrentItem != nullptr);
128
129 DataMemberLayoutItem &Layout =
130 static_cast<DataMemberLayoutItem &>(*CurrentItem);
131
132 VariableDumper VarDumper(Printer);
133 VarDumper.start(Symbol, ClassOffsetZero);
134
135 if (Layout.hasUDTLayout()) {
136 Printer.Indent();
137 PrettyClassLayoutGraphicalDumper TypeDumper(Printer, ClassOffsetZero);
138 TypeDumper.start(Layout.getUDTLayout());
139 Printer.Unindent();
140 }
141
142 DumpedAnything = true;
143}
Zachary Turner9e7dda32017-04-12 23:18:51 +0000144
145void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000146 assert(CurrentItem != nullptr);
147
Zachary Turner4dc4f012017-04-13 21:11:00 +0000148 VariableDumper VarDumper(Printer);
149 VarDumper.start(Symbol, ClassOffsetZero);
150
Zachary Turner4dc4f012017-04-13 21:11:00 +0000151 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +0000152}