]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-pdbutil/PrettyTypeDumper.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-pdbutil / PrettyTypeDumper.cpp
1 //===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ 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 "PrettyTypeDumper.h"
11
12 #include "LinePrinter.h"
13 #include "PrettyBuiltinDumper.h"
14 #include "PrettyClassDefinitionDumper.h"
15 #include "PrettyEnumDumper.h"
16 #include "PrettyFunctionDumper.h"
17 #include "PrettyTypedefDumper.h"
18 #include "llvm-pdbutil.h"
19
20 #include "llvm/DebugInfo/PDB/IPDBSession.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
27 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
28 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
29 #include "llvm/DebugInfo/PDB/UDTLayout.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/FormatVariadic.h"
32
33 using namespace llvm;
34 using namespace llvm::pdb;
35
36 using LayoutPtr = std::unique_ptr<ClassLayout>;
37
38 typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
39
40 static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
41   return S1->getName() < S2->getName();
42 }
43
44 static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
45   return S1->getSize() < S2->getSize();
46 }
47
48 static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
49   return S1->deepPaddingSize() < S2->deepPaddingSize();
50 }
51
52 static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {
53   double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();
54   double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();
55   return Pct1 < Pct2;
56 }
57
58 static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {
59   return S1->immediatePadding() < S2->immediatePadding();
60 }
61
62 static bool ComparePaddingPctImmediate(const LayoutPtr &S1,
63                                        const LayoutPtr &S2) {
64   double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();
65   double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();
66   return Pct1 < Pct2;
67 }
68
69 static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
70   switch (Mode) {
71   case opts::pretty::ClassSortMode::Name:
72     return CompareNames;
73   case opts::pretty::ClassSortMode::Size:
74     return CompareSizes;
75   case opts::pretty::ClassSortMode::Padding:
76     return ComparePadding;
77   case opts::pretty::ClassSortMode::PaddingPct:
78     return ComparePaddingPct;
79   case opts::pretty::ClassSortMode::PaddingImmediate:
80     return ComparePaddingImmediate;
81   case opts::pretty::ClassSortMode::PaddingPctImmediate:
82     return ComparePaddingPctImmediate;
83   default:
84     return nullptr;
85   }
86 }
87
88 template <typename Enumerator>
89 static std::vector<std::unique_ptr<ClassLayout>>
90 filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
91                        uint32_t UnfilteredCount) {
92   std::vector<std::unique_ptr<ClassLayout>> Filtered;
93
94   Filtered.reserve(UnfilteredCount);
95   CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
96
97   if (UnfilteredCount > 10000) {
98     errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);
99     errs().flush();
100   }
101   uint32_t Examined = 0;
102   uint32_t Discarded = 0;
103   while (auto Class = E.getNext()) {
104     ++Examined;
105     if (Examined % 10000 == 0) {
106       errs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
107                         Examined, UnfilteredCount, Discarded);
108       errs().flush();
109     }
110
111     if (Class->getUnmodifiedTypeId() != 0) {
112       ++Discarded;
113       continue;
114     }
115
116     if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
117       ++Discarded;
118       continue;
119     }
120
121     auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
122     if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
123       ++Discarded;
124       continue;
125     }
126     if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {
127       ++Discarded;
128       continue;
129     }
130
131     Filtered.push_back(std::move(Layout));
132   }
133
134   if (Comp)
135     llvm::sort(Filtered, Comp);
136   return Filtered;
137 }
138
139 TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
140
141 template <typename T>
142 static bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) {
143   return false;
144 }
145
146 static bool isTypeExcluded(LinePrinter &Printer,
147                            const PDBSymbolTypeEnum &Enum) {
148   if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength()))
149     return true;
150   // Dump member enums when dumping their class definition.
151   if (nullptr != Enum.getClassParent())
152     return true;
153   return false;
154 }
155
156 static bool isTypeExcluded(LinePrinter &Printer,
157                            const PDBSymbolTypeTypedef &Typedef) {
158   return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength());
159 }
160
161 template <typename SymbolT>
162 static void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe,
163                                TypeDumper &TD, StringRef Label) {
164   if (auto Children = Exe.findAllChildren<SymbolT>()) {
165     Printer.NewLine();
166     WithColor(Printer, PDB_ColorItem::Identifier).get() << Label;
167     Printer << ": (" << Children->getChildCount() << " items)";
168     Printer.Indent();
169     while (auto Child = Children->getNext()) {
170       if (isTypeExcluded(Printer, *Child))
171         continue;
172
173       Printer.NewLine();
174       Child->dump(TD);
175     }
176     Printer.Unindent();
177   }
178 }
179
180 static void printClassDecl(LinePrinter &Printer,
181                            const PDBSymbolTypeUDT &Class) {
182   if (Class.getUnmodifiedTypeId() != 0) {
183     if (Class.isConstType())
184       WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
185     if (Class.isVolatileType())
186       WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
187     if (Class.isUnalignedType())
188       WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
189   }
190   WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
191   WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
192 }
193
194 void TypeDumper::start(const PDBSymbolExe &Exe) {
195   if (opts::pretty::Enums)
196     dumpSymbolCategory<PDBSymbolTypeEnum>(Printer, Exe, *this, "Enums");
197
198   if (opts::pretty::Funcsigs)
199     dumpSymbolCategory<PDBSymbolTypeFunctionSig>(Printer, Exe, *this,
200                                                  "Function Signatures");
201
202   if (opts::pretty::Typedefs)
203     dumpSymbolCategory<PDBSymbolTypeTypedef>(Printer, Exe, *this, "Typedefs");
204
205   if (opts::pretty::Arrays)
206     dumpSymbolCategory<PDBSymbolTypeArray>(Printer, Exe, *this, "Arrays");
207
208   if (opts::pretty::Pointers)
209     dumpSymbolCategory<PDBSymbolTypePointer>(Printer, Exe, *this, "Pointers");
210
211   if (opts::pretty::VTShapes)
212     dumpSymbolCategory<PDBSymbolTypeVTableShape>(Printer, Exe, *this,
213                                                  "VFTable Shapes");
214
215   if (opts::pretty::Classes) {
216     if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
217       uint32_t All = Classes->getChildCount();
218
219       Printer.NewLine();
220       WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
221
222       bool Precompute = false;
223       Precompute =
224           (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
225
226       // If we're using no sort mode, then we can start getting immediate output
227       // from the tool by just filtering as we go, rather than processing
228       // everything up front so that we can sort it.  This makes the tool more
229       // responsive.  So only precompute the filtered/sorted set of classes if
230       // necessary due to the specified options.
231       std::vector<LayoutPtr> Filtered;
232       uint32_t Shown = All;
233       if (Precompute) {
234         Filtered = filterAndSortClassDefs(Printer, *Classes, All);
235
236         Shown = Filtered.size();
237       }
238
239       Printer << ": (Showing " << Shown << " items";
240       if (Shown < All)
241         Printer << ", " << (All - Shown) << " filtered";
242       Printer << ")";
243       Printer.Indent();
244
245       // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
246       // the DIA enumerator and filter on the fly.
247       if (Precompute) {
248         for (auto &Class : Filtered)
249           dumpClassLayout(*Class);
250       } else {
251         while (auto Class = Classes->getNext()) {
252           if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
253             continue;
254
255           // No point duplicating a full class layout.  Just print the modified
256           // declaration and continue.
257           if (Class->getUnmodifiedTypeId() != 0) {
258             Printer.NewLine();
259             printClassDecl(Printer, *Class);
260             continue;
261           }
262
263           auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
264           if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
265             continue;
266
267           dumpClassLayout(*Layout);
268         }
269       }
270
271       Printer.Unindent();
272     }
273   }
274 }
275
276 void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
277   assert(opts::pretty::Enums);
278
279   EnumDumper Dumper(Printer);
280   Dumper.start(Symbol);
281 }
282
283 void TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
284   BuiltinDumper BD(Printer);
285   BD.start(Symbol);
286 }
287
288 void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
289   printClassDecl(Printer, Symbol);
290 }
291
292 void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
293   assert(opts::pretty::Typedefs);
294
295   TypedefDumper Dumper(Printer);
296   Dumper.start(Symbol);
297 }
298
299 void TypeDumper::dump(const PDBSymbolTypeArray &Symbol) {
300   auto ElementType = Symbol.getElementType();
301
302   ElementType->dump(*this);
303   Printer << "[";
304   WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getCount();
305   Printer << "]";
306 }
307
308 void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
309   FunctionDumper Dumper(Printer);
310   Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
311 }
312
313 void TypeDumper::dump(const PDBSymbolTypePointer &Symbol) {
314   std::unique_ptr<PDBSymbol> P = Symbol.getPointeeType();
315
316   if (auto *FS = dyn_cast<PDBSymbolTypeFunctionSig>(P.get())) {
317     FunctionDumper Dumper(Printer);
318     FunctionDumper::PointerType PT =
319         Symbol.isReference() ? FunctionDumper::PointerType::Reference
320                              : FunctionDumper::PointerType::Pointer;
321     Dumper.start(*FS, nullptr, PT);
322     return;
323   }
324
325   if (auto *UDT = dyn_cast<PDBSymbolTypeUDT>(P.get())) {
326     printClassDecl(Printer, *UDT);
327   } else if (P) {
328     P->dump(*this);
329   }
330
331   if (auto Parent = Symbol.getClassParent()) {
332     auto UDT = llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Parent));
333     if (UDT)
334       Printer << " " << UDT->getName() << "::";
335   }
336
337   if (Symbol.isReference())
338     Printer << "&";
339   else if (Symbol.isRValueReference())
340     Printer << "&&";
341   else
342     Printer << "*";
343 }
344
345 void TypeDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {
346   Printer.format("<vtshape ({0} methods)>", Symbol.getCount());
347 }
348
349 void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
350   assert(opts::pretty::Classes);
351
352   if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
353     WithColor(Printer, PDB_ColorItem::Keyword).get()
354         << Class.getClass().getUdtKind() << " ";
355     WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
356   } else {
357     ClassDefinitionDumper Dumper(Printer);
358     Dumper.start(Class);
359   }
360 }