[llvm-pdbdump] Add an option to dump full class definitions.
[oota-llvm.git] / tools / llvm-pdbdump / FunctionDumper.cpp
1 //===- FunctionDumper.cpp ------------------------------------ *- 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 "FunctionDumper.h"
11 #include "llvm-pdbdump.h"
12
13 #include "llvm/DebugInfo/PDB/IPDBSession.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
26 #include "llvm/Support/Format.h"
27
28 using namespace llvm;
29
30 namespace {
31 template <class T>
32 void dumpClassParentWithScopeOperator(const T &Symbol, llvm::raw_ostream &OS,
33                                       llvm::FunctionDumper &Dumper) {
34   uint32_t ClassParentId = Symbol.getClassParentId();
35   auto ClassParent =
36       Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
37           ClassParentId);
38   if (!ClassParent)
39     return;
40
41   OS << ClassParent->getName() << "::";
42 }
43 }
44
45 FunctionDumper::FunctionDumper() : PDBSymDumper(true) {}
46
47 void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
48                            PointerType Pointer, raw_ostream &OS) {
49   auto ReturnType = Symbol.getReturnType();
50   ReturnType->dump(OS, 0, *this);
51   OS << " ";
52   uint32_t ClassParentId = Symbol.getClassParentId();
53   auto ClassParent =
54       Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
55           ClassParentId);
56
57   PDB_CallingConv CC = Symbol.getCallingConvention();
58   bool ShouldDumpCallingConvention = true;
59   if ((ClassParent && CC == PDB_CallingConv::Thiscall) ||
60       (!ClassParent && CC == PDB_CallingConv::NearStdcall)) {
61     ShouldDumpCallingConvention = false;
62   }
63
64   if (Pointer == PointerType::None) {
65     if (ShouldDumpCallingConvention)
66       OS << CC << " ";
67     if (ClassParent)
68       OS << "(" << ClassParent->getName() << "::)";
69   } else {
70     OS << "(";
71     if (ShouldDumpCallingConvention)
72       OS << CC << " ";
73     OS << Symbol.getCallingConvention() << " ";
74     if (ClassParent)
75       OS << ClassParent->getName() << "::";
76     if (Pointer == PointerType::Reference)
77       OS << "&";
78     else
79       OS << "*";
80     OS << ")";
81   }
82
83   OS << "(";
84   if (auto ChildEnum = Symbol.getArguments()) {
85     uint32_t Index = 0;
86     while (auto Arg = ChildEnum->getNext()) {
87       Arg->dump(OS, 0, *this);
88       if (++Index < ChildEnum->getChildCount())
89         OS << ", ";
90     }
91   }
92   OS << ")";
93
94   if (Symbol.isConstType())
95     OS << " const";
96   if (Symbol.isVolatileType())
97     OS << " volatile";
98 }
99
100 void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer,
101                            raw_ostream &OS, int Indent) {
102   uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
103   uint32_t FuncEnd = FuncStart + Symbol.getLength();
104
105   OS << newline(Indent);
106
107   OS << "func [" << format_hex(FuncStart, 8);
108   if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>())
109     OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart;
110   OS << " - " << format_hex(FuncEnd, 8);
111   if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>())
112     OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress();
113   OS << "] ";
114
115   if (Symbol.hasFramePointer())
116     OS << "(" << Symbol.getLocalBasePointerRegisterId() << ")";
117   else
118     OS << "(FPO)";
119
120   OS << " ";
121   if (Symbol.isVirtual() || Symbol.isPureVirtual())
122     OS << "virtual ";
123
124   auto Signature = Symbol.getSignature();
125   if (!Signature) {
126     OS << Symbol.getName();
127     if (Pointer == PointerType::Pointer)
128       OS << "*";
129     else if (Pointer == FunctionDumper::PointerType::Reference)
130       OS << "&";
131     return;
132   }
133
134   auto ReturnType = Signature->getReturnType();
135   ReturnType->dump(OS, 0, *this);
136   OS << " ";
137
138   auto ClassParent = Symbol.getClassParent();
139   PDB_CallingConv CC = Signature->getCallingConvention();
140   if (Pointer != FunctionDumper::PointerType::None)
141     OS << "(";
142
143   if ((ClassParent && CC != PDB_CallingConv::Thiscall) ||
144       (!ClassParent && CC != PDB_CallingConv::NearStdcall))
145     OS << Signature->getCallingConvention() << " ";
146   OS << Symbol.getName();
147   if (Pointer != FunctionDumper::PointerType::None) {
148     if (Pointer == PointerType::Pointer)
149       OS << "*";
150     else if (Pointer == FunctionDumper::PointerType::Reference)
151       OS << "&";
152     OS << ")";
153   }
154
155   OS << "(";
156   if (auto Arguments = Symbol.getArguments()) {
157     uint32_t Index = 0;
158     while (auto Arg = Arguments->getNext()) {
159       auto ArgType = Arg->getType();
160       ArgType->dump(OS, 0, *this);
161       OS << " " << Arg->getName();
162       if (++Index < Arguments->getChildCount())
163         OS << ", ";
164     }
165   }
166   OS.flush();
167   OS << ")";
168   if (Symbol.isConstType())
169     OS << " const";
170   if (Symbol.isVolatileType())
171     OS << " volatile";
172   if (Symbol.isPureVirtual())
173     OS << " = 0";
174 }
175
176 void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
177                           int Indent) {
178   uint32_t ElementTypeId = Symbol.getTypeId();
179   auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
180   if (!ElementType)
181     return;
182
183   ElementType->dump(OS, 0, *this);
184   OS << "[" << Symbol.getLength() << "]";
185 }
186
187 void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
188                           int Indent) {
189   PDB_BuiltinType Type = Symbol.getBuiltinType();
190   OS << Type;
191   if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
192     OS << (8 * Symbol.getLength()) << "_t";
193 }
194
195 void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
196                           int Indent) {
197   dumpClassParentWithScopeOperator(Symbol, OS, *this);
198   OS << Symbol.getName();
199 }
200
201 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol,
202                           raw_ostream &OS, int Indent) {
203   // PDBSymbolTypeFunctionArg is just a shim over the real argument.  Just drill
204   // through to the real thing and dump it.
205   Symbol.defaultDump(OS, Indent, PDB_DumpLevel::Detailed);
206   OS.flush();
207   uint32_t TypeId = Symbol.getTypeId();
208   auto Type = Symbol.getSession().getSymbolById(TypeId);
209   if (!Type)
210     return;
211   Type->dump(OS, 0, *this);
212 }
213
214 void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
215                           int Indent) {
216   dumpClassParentWithScopeOperator(Symbol, OS, *this);
217   OS << Symbol.getName();
218 }
219
220 void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
221                           int Indent) {
222   uint32_t PointeeId = Symbol.getTypeId();
223   auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
224   if (!PointeeType)
225     return;
226
227   if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
228     FunctionDumper NestedDumper;
229     PointerType Pointer =
230         Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
231     NestedDumper.start(*FuncSig, Pointer, OS);
232   } else {
233     if (Symbol.isConstType())
234       OS << "const ";
235     if (Symbol.isVolatileType())
236       OS << "volatile ";
237     PointeeType->dump(OS, Indent, *this);
238     OS << (Symbol.isReference() ? "&" : "*");
239   }
240 }
241
242 void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
243                           int Indent) {
244   OS << Symbol.getName();
245 }