blob: 16cec82f718a84030f958701193e7b445669ef35 [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"
Zachary Turnerda949c12017-04-24 17:47:52 +000014#include "PrettyEnumDumper.h"
15#include "PrettyFunctionDumper.h"
16#include "PrettyTypedefDumper.h"
Zachary Turner4dc4f012017-04-13 21:11:00 +000017#include "PrettyVariableDumper.h"
Zachary Turnerda949c12017-04-24 17:47:52 +000018#include "PrettyVariableDumper.h"
19#include "llvm-pdbdump.h"
Zachary Turner4dc4f012017-04-13 21:11:00 +000020
21#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
22#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
23#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
24#include "llvm/DebugInfo/PDB/UDTLayout.h"
25#include "llvm/Support/Format.h"
26
Zachary Turner9e7dda32017-04-12 23:18:51 +000027using namespace llvm;
28using namespace llvm::pdb;
29
30PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
Zachary Turnerda949c12017-04-24 17:47:52 +000031 LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
32 : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
33 ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
Zachary Turner9e7dda32017-04-12 23:18:51 +000034
Zachary Turner4dc4f012017-04-13 21:11:00 +000035bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
Zachary Turnerda949c12017-04-24 17:47:52 +000036
37 if (RecursionLevel == 1 &&
38 opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
39 for (auto &Other : Layout.other_items())
40 Other->dump(*this);
41 for (auto &Func : Layout.funcs())
42 Func->dump(*this);
43 }
44
Zachary Turner4dc4f012017-04-13 21:11:00 +000045 const BitVector &UseMap = Layout.usedBytes();
46 int NextPaddingByte = UseMap.find_first_unset();
47
48 for (auto &Item : Layout.layout_items()) {
49 // Calculate the absolute offset of the first byte of the next field.
50 uint32_t RelativeOffset = Item->getOffsetInParent();
51 CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
52
53 // Since there is storage there, it should be set! However, this might
54 // be an empty base, in which case it could extend outside the bounds of
55 // the parent class.
56 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
57 assert(UseMap.test(RelativeOffset));
58
59 // If there is any remaining padding in this class, and the offset of the
60 // new item is after the padding, then we must have just jumped over some
61 // padding. Print a padding row and then look for where the next block
62 // of padding begins.
63 if ((NextPaddingByte >= 0) &&
64 (RelativeOffset > uint32_t(NextPaddingByte))) {
65 printPaddingRow(RelativeOffset - NextPaddingByte);
66 NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
67 }
68 }
69
Zachary Turner16901642017-04-24 17:47:24 +000070 CurrentItem = Item;
71 if (Item->isVBPtr()) {
72 VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
73
74 VariableDumper VarDumper(Printer);
75 VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
76 } else {
77 if (auto Sym = Item->getSymbol())
78 Sym->dump(*this);
79 }
80
81 if (Item->getLayoutSize() > 0) {
82 uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
83 NextPaddingByte = UseMap.find_next_unset(Prev);
84 }
Zachary Turner4dc4f012017-04-13 21:11:00 +000085 }
86
Zachary Turner16901642017-04-24 17:47:24 +000087 auto TailPadding = Layout.tailPadding();
88 if (TailPadding > 0) {
Zachary Turnerda949c12017-04-24 17:47:52 +000089 if (TailPadding != 1 || Layout.getSize() != 1) {
90 Printer.NewLine();
91 WithColor(Printer, PDB_ColorItem::Padding).get()
92 << "<padding> (" << TailPadding << " bytes)";
93 DumpedAnything = true;
94 }
Zachary Turner4dc4f012017-04-13 21:11:00 +000095 }
96
97 return DumpedAnything;
98}
99
100void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
101 if (Amount == 0)
102 return;
103
104 Printer.NewLine();
105 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
106 << " bytes)";
107 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +0000108}
109
110void PrettyClassLayoutGraphicalDumper::dump(
Zachary Turner4dc4f012017-04-13 21:11:00 +0000111 const PDBSymbolTypeBaseClass &Symbol) {
112 assert(CurrentItem != nullptr);
Zachary Turner9e7dda32017-04-12 23:18:51 +0000113
Zachary Turner4dc4f012017-04-13 21:11:00 +0000114 Printer.NewLine();
115 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
Zachary Turner9e7dda32017-04-12 23:18:51 +0000116
Zachary Turner16901642017-04-24 17:47:24 +0000117 std::string Label = "base";
118 if (Layout.isVirtualBase()) {
119 Label.insert(Label.begin(), 'v');
120 if (Layout.getBase().isIndirectVirtualBaseClass())
121 Label.insert(Label.begin(), 'i');
122 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000123 Printer << Label << " ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000124
Zachary Turner16901642017-04-24 17:47:24 +0000125 uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
126
Zachary Turner4dc4f012017-04-13 21:11:00 +0000127 WithColor(Printer, PDB_ColorItem::Offset).get()
Zachary Turner16901642017-04-24 17:47:24 +0000128 << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
129 << "] ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000130
Zachary Turner4dc4f012017-04-13 21:11:00 +0000131 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
Zachary Turner9e7dda32017-04-12 23:18:51 +0000132
Zachary Turnerda949c12017-04-24 17:47:52 +0000133 if (shouldRecurse()) {
134 Printer.Indent();
135 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
136 PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
137 ChildOffsetZero);
138 DumpedAnything |= BaseDumper.start(Layout);
139 Printer.Unindent();
140 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000141
142 DumpedAnything = true;
143}
144
Zachary Turnerda949c12017-04-24 17:47:52 +0000145bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
146 uint32_t Limit = opts::pretty::ClassRecursionDepth;
147 if (Limit == 0)
148 return true;
149 return RecursionLevel < Limit;
150}
151
Zachary Turner4dc4f012017-04-13 21:11:00 +0000152void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
153 assert(CurrentItem != nullptr);
154
155 DataMemberLayoutItem &Layout =
156 static_cast<DataMemberLayoutItem &>(*CurrentItem);
157
158 VariableDumper VarDumper(Printer);
159 VarDumper.start(Symbol, ClassOffsetZero);
160
Zachary Turnerda949c12017-04-24 17:47:52 +0000161 if (Layout.hasUDTLayout() && shouldRecurse()) {
162 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
Zachary Turner4dc4f012017-04-13 21:11:00 +0000163 Printer.Indent();
Zachary Turnerda949c12017-04-24 17:47:52 +0000164 PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
165 ChildOffsetZero);
Zachary Turner4dc4f012017-04-13 21:11:00 +0000166 TypeDumper.start(Layout.getUDTLayout());
167 Printer.Unindent();
168 }
169
170 DumpedAnything = true;
171}
Zachary Turner9e7dda32017-04-12 23:18:51 +0000172
173void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000174 assert(CurrentItem != nullptr);
175
Zachary Turner4dc4f012017-04-13 21:11:00 +0000176 VariableDumper VarDumper(Printer);
177 VarDumper.start(Symbol, ClassOffsetZero);
178
Zachary Turner4dc4f012017-04-13 21:11:00 +0000179 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +0000180}
Zachary Turnerda949c12017-04-24 17:47:52 +0000181
182void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
183 DumpedAnything = true;
184 Printer.NewLine();
185 EnumDumper Dumper(Printer);
186 Dumper.start(Symbol);
187}
188
189void PrettyClassLayoutGraphicalDumper::dump(
190 const PDBSymbolTypeTypedef &Symbol) {
191 DumpedAnything = true;
192 Printer.NewLine();
193 TypedefDumper Dumper(Printer);
194 Dumper.start(Symbol);
195}
196
197void PrettyClassLayoutGraphicalDumper::dump(
198 const PDBSymbolTypeBuiltin &Symbol) {}
199
200void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
201
202void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
203 if (Printer.IsSymbolExcluded(Symbol.getName()))
204 return;
205 if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
206 return;
207 if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
208 !Symbol.isIntroVirtualFunction())
209 return;
210
211 DumpedAnything = true;
212 Printer.NewLine();
213 FunctionDumper Dumper(Printer);
214 Dumper.start(Symbol, FunctionDumper::PointerType::None);
215}