]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-pdbdump/PrettyTypeDumper.cpp
Merge llvm trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-pdbdump / 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 "PrettyTypedefDumper.h"
17 #include "llvm-pdbdump.h"
18
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"
28
29 using namespace llvm;
30 using namespace llvm::pdb;
31
32 using LayoutPtr = std::unique_ptr<ClassLayout>;
33
34 typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
35
36 static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
37   return S1->getUDTName() < S2->getUDTName();
38 }
39
40 static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
41   return S1->getClassSize() < S2->getClassSize();
42 }
43
44 static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
45   return S1->deepPaddingSize() < S2->deepPaddingSize();
46 }
47
48 static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
49   switch (Mode) {
50   case opts::pretty::ClassSortMode::Name:
51     return CompareNames;
52   case opts::pretty::ClassSortMode::Size:
53     return CompareSizes;
54   case opts::pretty::ClassSortMode::Padding:
55     return ComparePadding;
56   default:
57     return nullptr;
58   }
59 }
60
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;
66
67   Filtered.reserve(UnfilteredCount);
68   CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
69
70   uint32_t Examined = 0;
71   uint32_t Discarded = 0;
72   while (auto Class = E.getNext()) {
73     ++Examined;
74     if (Examined % 10000 == 0) {
75       outs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
76                         Examined, UnfilteredCount, Discarded);
77       outs().flush();
78     }
79
80     if (Class->getUnmodifiedTypeId() != 0) {
81       ++Discarded;
82       continue;
83     }
84
85     if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
86       ++Discarded;
87       continue;
88     }
89
90     auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
91     if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
92       ++Discarded;
93       continue;
94     }
95
96     Filtered.push_back(std::move(Layout));
97   }
98
99   if (Comp)
100     std::sort(Filtered.begin(), Filtered.end(), Comp);
101   return Filtered;
102 }
103
104 TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
105
106 void TypeDumper::start(const PDBSymbolExe &Exe) {
107   if (opts::pretty::Enums) {
108     auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
109     Printer.NewLine();
110     WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
111     Printer << ": (" << Enums->getChildCount() << " items)";
112     Printer.Indent();
113     while (auto Enum = Enums->getNext())
114       Enum->dump(*this);
115     Printer.Unindent();
116   }
117
118   if (opts::pretty::Typedefs) {
119     auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>();
120     Printer.NewLine();
121     WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
122     Printer << ": (" << Typedefs->getChildCount() << " items)";
123     Printer.Indent();
124     while (auto Typedef = Typedefs->getNext())
125       Typedef->dump(*this);
126     Printer.Unindent();
127   }
128
129   if (opts::pretty::Classes) {
130     auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
131     uint32_t All = Classes->getChildCount();
132
133     Printer.NewLine();
134     WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
135
136     bool Precompute = false;
137     Precompute =
138         (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
139
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;
147     if (Precompute) {
148       Filtered = filterAndSortClassDefs(Printer, *Classes, All);
149
150       Shown = Filtered.size();
151     }
152
153     Printer << ": (Showing " << Shown << " items";
154     if (Shown < All)
155       Printer << ", " << (All - Shown) << " filtered";
156     Printer << ")";
157     Printer.Indent();
158
159     // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
160     // the DIA enumerator and filter on the fly.
161     if (Precompute) {
162       for (auto &Class : Filtered)
163         dumpClassLayout(*Class);
164     } else {
165       while (auto Class = Classes->getNext()) {
166         if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
167           continue;
168
169         auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
170         if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
171           continue;
172
173         dumpClassLayout(*Layout);
174       }
175     }
176
177     Printer.Unindent();
178   }
179 }
180
181 void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
182   assert(opts::pretty::Enums);
183
184   if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
185     return;
186   // Dump member enums when dumping their class definition.
187   if (nullptr != Symbol.getClassParent())
188     return;
189
190   Printer.NewLine();
191   EnumDumper Dumper(Printer);
192   Dumper.start(Symbol);
193 }
194
195 void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
196   assert(opts::pretty::Typedefs);
197
198   if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
199     return;
200
201   Printer.NewLine();
202   TypedefDumper Dumper(Printer);
203   Dumper.start(Symbol);
204 }
205
206 void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
207   assert(opts::pretty::Classes);
208
209   if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
210     Printer.NewLine();
211     WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
212     WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getUDTName();
213   } else {
214     ClassDefinitionDumper Dumper(Printer);
215     Dumper.start(Class);
216   }
217 }