1 //===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ 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 "PrettyTypeDumper.h"
12 #include "LinePrinter.h"
13 #include "PrettyBuiltinDumper.h"
14 #include "PrettyClassDefinitionDumper.h"
15 #include "PrettyEnumDumper.h"
16 #include "PrettyTypedefDumper.h"
17 #include "llvm-pdbdump.h"
19 #include "llvm/DebugInfo/PDB/IPDBSession.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
25 #include "llvm/DebugInfo/PDB/UDTLayout.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/FormatVariadic.h"
30 using namespace llvm::pdb;
32 using LayoutPtr = std::unique_ptr<ClassLayout>;
34 typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
36 static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
37 return S1->getUDTName() < S2->getUDTName();
40 static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
41 return S1->getClassSize() < S2->getClassSize();
44 static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
45 return S1->deepPaddingSize() < S2->deepPaddingSize();
48 static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
50 case opts::pretty::ClassSortMode::Name:
52 case opts::pretty::ClassSortMode::Size:
54 case opts::pretty::ClassSortMode::Padding:
55 return ComparePadding;
61 template <typename Enumerator>
62 static std::vector<std::unique_ptr<ClassLayout>>
63 filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
64 uint32_t UnfilteredCount) {
65 std::vector<std::unique_ptr<ClassLayout>> Filtered;
67 Filtered.reserve(UnfilteredCount);
68 CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
70 uint32_t Examined = 0;
71 uint32_t Discarded = 0;
72 while (auto Class = E.getNext()) {
74 if (Examined % 10000 == 0) {
75 outs() << formatv("Examined {0}/{1} items. {2} items discarded\n",
76 Examined, UnfilteredCount, Discarded);
80 if (Class->getUnmodifiedTypeId() != 0) {
85 if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
90 auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
91 if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
96 Filtered.push_back(std::move(Layout));
100 std::sort(Filtered.begin(), Filtered.end(), Comp);
104 TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
106 void TypeDumper::start(const PDBSymbolExe &Exe) {
107 if (opts::pretty::Enums) {
108 auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
110 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
111 Printer << ": (" << Enums->getChildCount() << " items)";
113 while (auto Enum = Enums->getNext())
118 if (opts::pretty::Typedefs) {
119 auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>();
121 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
122 Printer << ": (" << Typedefs->getChildCount() << " items)";
124 while (auto Typedef = Typedefs->getNext())
125 Typedef->dump(*this);
129 if (opts::pretty::Classes) {
130 auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
131 uint32_t All = Classes->getChildCount();
134 WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
136 bool Precompute = false;
138 (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
140 // If we're using no sort mode, then we can start getting immediate output
141 // from the tool by just filtering as we go, rather than processing
142 // everything up front so that we can sort it. This makes the tool more
143 // responsive. So only precompute the filtered/sorted set of classes if
144 // necessary due to the specified options.
145 std::vector<LayoutPtr> Filtered;
146 uint32_t Shown = All;
148 Filtered = filterAndSortClassDefs(Printer, *Classes, All);
150 Shown = Filtered.size();
153 Printer << ": (Showing " << Shown << " items";
155 Printer << ", " << (All - Shown) << " filtered";
159 // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
160 // the DIA enumerator and filter on the fly.
162 for (auto &Class : Filtered)
163 dumpClassLayout(*Class);
165 while (auto Class = Classes->getNext()) {
166 if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
169 auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
170 if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
173 dumpClassLayout(*Layout);
181 void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
182 assert(opts::pretty::Enums);
184 if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
186 // Dump member enums when dumping their class definition.
187 if (nullptr != Symbol.getClassParent())
191 EnumDumper Dumper(Printer);
192 Dumper.start(Symbol);
195 void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
196 assert(opts::pretty::Typedefs);
198 if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
202 TypedefDumper Dumper(Printer);
203 Dumper.start(Symbol);
206 void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
207 assert(opts::pretty::Classes);
209 if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
211 WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
212 WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getUDTName();
214 ClassDefinitionDumper Dumper(Printer);