blob: b48ed23c1c714e8cc281fa4c41f39495c6143db8 [file] [log] [blame]
Zachary Turnera9054dd2017-01-11 00:35:43 +00001//===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===//
Zachary Turner29c69102015-02-23 05:58:34 +00002//
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
Zachary Turnera9054dd2017-01-11 00:35:43 +000010#include "PrettyClassDefinitionDumper.h"
11
Zachary Turner2d11c202015-02-27 09:15:59 +000012#include "LinePrinter.h"
Zachary Turnera9054dd2017-01-11 00:35:43 +000013#include "PrettyEnumDumper.h"
14#include "PrettyFunctionDumper.h"
15#include "PrettyTypedefDumper.h"
16#include "PrettyVariableDumper.h"
Zachary Turner29c69102015-02-23 05:58:34 +000017#include "llvm-pdbdump.h"
Zachary Turner29c69102015-02-23 05:58:34 +000018
Zachary Turner0c990bbe2017-04-10 19:33:29 +000019#include "llvm/ADT/APFloat.h"
20#include "llvm/ADT/SmallString.h"
Zachary Turner29c69102015-02-23 05:58:34 +000021#include "llvm/DebugInfo/PDB/IPDBSession.h"
22#include "llvm/DebugInfo/PDB/PDBExtras.h"
23#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
24#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
25#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
26#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
27#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
28#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
29#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
30#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
Zachary Turner0c990bbe2017-04-10 19:33:29 +000031#include "llvm/Support/Compiler.h"
Zachary Turner29c69102015-02-23 05:58:34 +000032#include "llvm/Support/Format.h"
33
34using namespace llvm;
Zachary Turnerec28fc32016-05-04 20:32:13 +000035using namespace llvm::pdb;
Zachary Turner29c69102015-02-23 05:58:34 +000036
Zachary Turner2d11c202015-02-27 09:15:59 +000037ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
38 : PDBSymDumper(true), Printer(P) {}
Zachary Turner29c69102015-02-23 05:58:34 +000039
Zachary Turner0c990bbe2017-04-10 19:33:29 +000040static void analyzePadding(const PDBSymbolTypeUDT &Class, BitVector &Padding,
41 uint32_t &FirstFieldOffset) {
42 Padding.resize(Class.getLength(), true);
43 auto Children = Class.findAllChildren<PDBSymbolData>();
44 bool IsFirst = true;
45 FirstFieldOffset = Class.getLength();
46
47 while (auto Data = Children->getNext()) {
48 // Ignore data members which are not relative to this. Usually these are
49 // static data members or constexpr and occupy no space. We also need to
50 // handle BitFields since the PDB doesn't consider them ThisRel, but they
51 // still occupy space in the record layout.
52 auto LocType = Data->getLocationType();
53 if (LocType != PDB_LocType::ThisRel && LocType != PDB_LocType::BitField)
54 continue;
55
56 uint64_t Start = Data->getOffset();
57 if (IsFirst) {
58 FirstFieldOffset = Start;
59 IsFirst = false;
60 }
61
62 auto VarType = Data->getType();
63 uint64_t Size = VarType->getRawSymbol().getLength();
64 Padding.reset(Start, Start + Size);
65 }
66
67 // Unmark anything that comes before the first field so it doesn't get
68 // counted as padding. In reality this is going to be vptrs or base class
69 // members, but we don't correctly handle that yet.
70 // FIXME: Handle it.
71 Padding.reset(0, FirstFieldOffset);
72}
73
Zachary Turnerb52d08d2015-03-01 06:51:29 +000074void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
Zachary Turner10169b62017-04-06 23:43:39 +000075 assert(opts::pretty::ClassFormat !=
76 opts::pretty::ClassDefinitionFormat::None);
77
Zachary Turner0c990bbe2017-04-10 19:33:29 +000078 uint32_t Size = Class.getLength();
79 uint32_t FirstFieldOffset = 0;
80 BitVector Padding;
81 analyzePadding(Class, Padding, FirstFieldOffset);
82
83 if (opts::pretty::OnlyPaddingClasses && (Padding.count() == 0))
84 return;
85
86 Printer.NewLine();
87 WithColor(Printer, PDB_ColorItem::Comment).get() << "// sizeof = " << Size;
88 Printer.NewLine();
89
Zachary Turner7797c722015-03-02 04:39:56 +000090 WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
Zachary Turner2d11c202015-02-27 09:15:59 +000091 WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
Zachary Turner7797c722015-03-02 04:39:56 +000092
93 auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
94 if (Bases->getChildCount() > 0) {
95 Printer.Indent();
96 Printer.NewLine();
97 Printer << ":";
98 uint32_t BaseIndex = 0;
99 while (auto Base = Bases->getNext()) {
100 Printer << " ";
101 WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
102 if (Base->isVirtualBaseClass())
103 WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
104 WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
105 if (++BaseIndex < Bases->getChildCount()) {
106 Printer.NewLine();
107 Printer << ",";
108 }
109 }
110 Printer.Unindent();
111 }
112
Zachary Turner2d11c202015-02-27 09:15:59 +0000113 Printer << " {";
Zachary Turner29c69102015-02-23 05:58:34 +0000114 auto Children = Class.findAllChildren();
Zachary Turner10169b62017-04-06 23:43:39 +0000115 Printer.Indent();
116 int DumpedCount = 0;
Zachary Turner29c69102015-02-23 05:58:34 +0000117
Zachary Turner0c990bbe2017-04-10 19:33:29 +0000118 int NextPaddingByte = Padding.find_first();
119 while (auto Child = Children->getNext()) {
120 if (auto Data = llvm::dyn_cast<PDBSymbolData>(Child.get())) {
121 if (Data->getDataKind() == PDB_DataKind::Member && NextPaddingByte >= 0) {
122 // If there are padding bytes remaining, see if this field is the first
123 // to cross a padding boundary, and print a padding field indicator if
124 // so.
125 int Off = Data->getOffset();
126 if (Off > NextPaddingByte) {
127 uint32_t Amount = Off - NextPaddingByte;
128 Printer.NewLine();
129 WithColor(Printer, PDB_ColorItem::Padding).get()
130 << "<padding> (" << Amount << " bytes)";
131 assert(Padding.find_next_unset(NextPaddingByte) == Off);
132 NextPaddingByte = Padding.find_next(Off);
Zachary Turner10169b62017-04-06 23:43:39 +0000133 }
Zachary Turner10169b62017-04-06 23:43:39 +0000134 }
135 }
Zachary Turner29c69102015-02-23 05:58:34 +0000136
Zachary Turner1b1a70f2017-04-10 06:14:09 +0000137 if (auto Func = Child->cast<PDBSymbolFunc>()) {
Zachary Turnera30bd1a2016-06-30 17:42:48 +0000138 if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
Zachary Turner29c69102015-02-23 05:58:34 +0000139 continue;
Zachary Turner10169b62017-04-06 23:43:39 +0000140
Zachary Turner7797c722015-03-02 04:39:56 +0000141 if (Func->getLength() == 0 && !Func->isPureVirtual() &&
142 !Func->isIntroVirtualFunction())
Zachary Turner29c69102015-02-23 05:58:34 +0000143 continue;
Zachary Turner29c69102015-02-23 05:58:34 +0000144 }
Zachary Turner10169b62017-04-06 23:43:39 +0000145
146 ++DumpedCount;
147 Child->dump(*this);
Zachary Turner29c69102015-02-23 05:58:34 +0000148 }
149
Zachary Turner0c990bbe2017-04-10 19:33:29 +0000150 if (NextPaddingByte >= 0) {
151 uint32_t Amount = Size - NextPaddingByte;
152 Printer.NewLine();
153 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
154 << " bytes)";
155 }
Zachary Turner10169b62017-04-06 23:43:39 +0000156 Printer.Unindent();
157 if (DumpedCount > 0)
Zachary Turner2d11c202015-02-27 09:15:59 +0000158 Printer.NewLine();
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000159 Printer << "}";
Zachary Turner0c990bbe2017-04-10 19:33:29 +0000160 Printer.NewLine();
161 if (Padding.count() > 0) {
162 APFloat Pct(100.0 * (double)Padding.count() /
163 (double)(Size - FirstFieldOffset));
164 SmallString<8> PctStr;
165 Pct.toString(PctStr, 4);
166 WithColor(Printer, PDB_ColorItem::Padding).get()
167 << "Total padding " << Padding.count() << " bytes (" << PctStr
168 << "% of class size)";
169 Printer.NewLine();
170 }
Zachary Turner29c69102015-02-23 05:58:34 +0000171}
172
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000173void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {}
Zachary Turner29c69102015-02-23 05:58:34 +0000174
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000175void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) {
Zachary Turner2d11c202015-02-27 09:15:59 +0000176 VariableDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000177 Dumper.start(Symbol);
Zachary Turner29c69102015-02-23 05:58:34 +0000178}
179
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000180void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) {
Zachary Turnerf5abda22015-03-01 06:49:49 +0000181 if (Printer.IsSymbolExcluded(Symbol.getName()))
182 return;
183
Zachary Turner2d11c202015-02-27 09:15:59 +0000184 Printer.NewLine();
185 FunctionDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000186 Dumper.start(Symbol, FunctionDumper::PointerType::None);
Zachary Turner29c69102015-02-23 05:58:34 +0000187}
188
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000189void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {}
Zachary Turner29c69102015-02-23 05:58:34 +0000190
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000191void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
Zachary Turnerf5abda22015-03-01 06:49:49 +0000192 if (Printer.IsTypeExcluded(Symbol.getName()))
193 return;
194
Zachary Turner2d11c202015-02-27 09:15:59 +0000195 Printer.NewLine();
Zachary Turner65323652015-03-04 06:09:53 +0000196 EnumDumper Dumper(Printer);
197 Dumper.start(Symbol);
Zachary Turner29c69102015-02-23 05:58:34 +0000198}
199
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000200void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
Zachary Turnerf5abda22015-03-01 06:49:49 +0000201 if (Printer.IsTypeExcluded(Symbol.getName()))
202 return;
203
Zachary Turner2d11c202015-02-27 09:15:59 +0000204 Printer.NewLine();
205 TypedefDumper Dumper(Printer);
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000206 Dumper.start(Symbol);
Zachary Turner29c69102015-02-23 05:58:34 +0000207}
208
Zachary Turnerb52d08d2015-03-01 06:51:29 +0000209void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {}