blob: a572522c8cd704b1857f44250e8944fb93b69889 [file] [log] [blame]
Zachary Turner67dcd802017-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 Turner10683342017-04-13 21:11:00 +000012#include "LinePrinter.h"
13#include "PrettyClassDefinitionDumper.h"
Zachary Turner41374872017-04-24 17:47:52 +000014#include "PrettyEnumDumper.h"
15#include "PrettyFunctionDumper.h"
16#include "PrettyTypedefDumper.h"
Zachary Turner10683342017-04-13 21:11:00 +000017#include "PrettyVariableDumper.h"
Zachary Turner41374872017-04-24 17:47:52 +000018#include "PrettyVariableDumper.h"
Zachary Turnercfb13562017-06-09 20:46:17 +000019#include "llvm-pdbutil.h"
Zachary Turner10683342017-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 Turner67dcd802017-04-12 23:18:51 +000027using namespace llvm;
28using namespace llvm::pdb;
29
30PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
Zachary Turner41374872017-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 Turner67dcd802017-04-12 23:18:51 +000034
Zachary Turner10683342017-04-13 21:11:00 +000035bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
Zachary Turner41374872017-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 Turner10683342017-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
Adrian McCarthya14fac42018-04-16 17:01:18 +000053 // This might be an empty base, in which case it could extend outside the
54 // bounds of the parent class.
Zachary Turner10683342017-04-13 21:11:00 +000055 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
Zachary Turner10683342017-04-13 21:11:00 +000056 // If there is any remaining padding in this class, and the offset of the
57 // new item is after the padding, then we must have just jumped over some
58 // padding. Print a padding row and then look for where the next block
59 // of padding begins.
60 if ((NextPaddingByte >= 0) &&
61 (RelativeOffset > uint32_t(NextPaddingByte))) {
62 printPaddingRow(RelativeOffset - NextPaddingByte);
63 NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
64 }
65 }
66
Zachary Turner0e8b7072017-04-24 17:47:24 +000067 CurrentItem = Item;
68 if (Item->isVBPtr()) {
69 VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
70
71 VariableDumper VarDumper(Printer);
72 VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
73 } else {
74 if (auto Sym = Item->getSymbol())
75 Sym->dump(*this);
76 }
77
78 if (Item->getLayoutSize() > 0) {
79 uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
Zachary Turner03783212017-05-26 00:15:15 +000080 if (Prev < UseMap.size())
81 NextPaddingByte = UseMap.find_next_unset(Prev);
Zachary Turner0e8b7072017-04-24 17:47:24 +000082 }
Zachary Turner10683342017-04-13 21:11:00 +000083 }
84
Zachary Turner0e8b7072017-04-24 17:47:24 +000085 auto TailPadding = Layout.tailPadding();
86 if (TailPadding > 0) {
Zachary Turner41374872017-04-24 17:47:52 +000087 if (TailPadding != 1 || Layout.getSize() != 1) {
88 Printer.NewLine();
89 WithColor(Printer, PDB_ColorItem::Padding).get()
90 << "<padding> (" << TailPadding << " bytes)";
91 DumpedAnything = true;
92 }
Zachary Turner10683342017-04-13 21:11:00 +000093 }
94
95 return DumpedAnything;
96}
97
98void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
99 if (Amount == 0)
100 return;
101
102 Printer.NewLine();
103 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
104 << " bytes)";
105 DumpedAnything = true;
Zachary Turner67dcd802017-04-12 23:18:51 +0000106}
107
108void PrettyClassLayoutGraphicalDumper::dump(
Zachary Turner10683342017-04-13 21:11:00 +0000109 const PDBSymbolTypeBaseClass &Symbol) {
110 assert(CurrentItem != nullptr);
Zachary Turner67dcd802017-04-12 23:18:51 +0000111
Zachary Turner10683342017-04-13 21:11:00 +0000112 Printer.NewLine();
113 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
Zachary Turner67dcd802017-04-12 23:18:51 +0000114
Zachary Turner0e8b7072017-04-24 17:47:24 +0000115 std::string Label = "base";
116 if (Layout.isVirtualBase()) {
117 Label.insert(Label.begin(), 'v');
118 if (Layout.getBase().isIndirectVirtualBaseClass())
119 Label.insert(Label.begin(), 'i');
120 }
Zachary Turner10683342017-04-13 21:11:00 +0000121 Printer << Label << " ";
Zachary Turner67dcd802017-04-12 23:18:51 +0000122
Zachary Turner0e8b7072017-04-24 17:47:24 +0000123 uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
124
Zachary Turner10683342017-04-13 21:11:00 +0000125 WithColor(Printer, PDB_ColorItem::Offset).get()
Zachary Turner0e8b7072017-04-24 17:47:24 +0000126 << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
127 << "] ";
Zachary Turner67dcd802017-04-12 23:18:51 +0000128
Zachary Turner10683342017-04-13 21:11:00 +0000129 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
Zachary Turner67dcd802017-04-12 23:18:51 +0000130
Zachary Turner41374872017-04-24 17:47:52 +0000131 if (shouldRecurse()) {
132 Printer.Indent();
133 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
134 PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
135 ChildOffsetZero);
136 DumpedAnything |= BaseDumper.start(Layout);
137 Printer.Unindent();
138 }
Zachary Turner10683342017-04-13 21:11:00 +0000139
140 DumpedAnything = true;
141}
142
Zachary Turner41374872017-04-24 17:47:52 +0000143bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
144 uint32_t Limit = opts::pretty::ClassRecursionDepth;
145 if (Limit == 0)
146 return true;
147 return RecursionLevel < Limit;
148}
149
Zachary Turner10683342017-04-13 21:11:00 +0000150void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
Zachary Turner10683342017-04-13 21:11:00 +0000151 VariableDumper VarDumper(Printer);
152 VarDumper.start(Symbol, ClassOffsetZero);
153
Zachary Turnerbd6d1e92017-06-12 20:46:35 +0000154 if (CurrentItem != nullptr) {
155 DataMemberLayoutItem &Layout =
156 static_cast<DataMemberLayoutItem &>(*CurrentItem);
157
158 if (Layout.hasUDTLayout() && shouldRecurse()) {
159 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
160 Printer.Indent();
161 PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
162 ChildOffsetZero);
163 TypeDumper.start(Layout.getUDTLayout());
164 Printer.Unindent();
165 }
Zachary Turner10683342017-04-13 21:11:00 +0000166 }
167
168 DumpedAnything = true;
169}
Zachary Turner67dcd802017-04-12 23:18:51 +0000170
171void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
Zachary Turner10683342017-04-13 21:11:00 +0000172 assert(CurrentItem != nullptr);
173
Zachary Turner10683342017-04-13 21:11:00 +0000174 VariableDumper VarDumper(Printer);
175 VarDumper.start(Symbol, ClassOffsetZero);
176
Zachary Turner10683342017-04-13 21:11:00 +0000177 DumpedAnything = true;
Zachary Turner67dcd802017-04-12 23:18:51 +0000178}
Zachary Turner41374872017-04-24 17:47:52 +0000179
180void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
181 DumpedAnything = true;
182 Printer.NewLine();
183 EnumDumper Dumper(Printer);
184 Dumper.start(Symbol);
185}
186
187void PrettyClassLayoutGraphicalDumper::dump(
188 const PDBSymbolTypeTypedef &Symbol) {
189 DumpedAnything = true;
190 Printer.NewLine();
191 TypedefDumper Dumper(Printer);
192 Dumper.start(Symbol);
193}
194
195void PrettyClassLayoutGraphicalDumper::dump(
196 const PDBSymbolTypeBuiltin &Symbol) {}
197
198void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
199
200void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
201 if (Printer.IsSymbolExcluded(Symbol.getName()))
202 return;
203 if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
204 return;
205 if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
206 !Symbol.isIntroVirtualFunction())
207 return;
208
209 DumpedAnything = true;
210 Printer.NewLine();
211 FunctionDumper Dumper(Printer);
212 Dumper.start(Symbol, FunctionDumper::PointerType::None);
213}