e65983034a6a89d7f21011af45b75d408161b3ad
[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 << ")";
167   if (Symbol.isConstType())
168     OS << " const";
169   if (Symbol.isVolatileType())
170     OS << " volatile";
171   if (Symbol.isPureVirtual())
172     OS << " = 0";
173 }
174
175 void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
176                           int Indent) {
177   uint32_t ElementTypeId = Symbol.getTypeId();
178   auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
179   if (!ElementType)
180     return;
181
182   ElementType->dump(OS, 0, *this);
183   OS << "[" << Symbol.getLength() << "]";
184 }
185
186 void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
187                           int Indent) {
188   PDB_BuiltinType Type = Symbol.getBuiltinType();
189   OS << Type;
190   if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
191     OS << (8 * Symbol.getLength()) << "_t";
192 }
193
194 void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
195                           int Indent) {
196   dumpClassParentWithScopeOperator(Symbol, OS, *this);
197   OS << Symbol.getName();
198 }
199
200 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol,
201                           raw_ostream &OS, int Indent) {
202   // PDBSymbolTypeFunctionArg is just a shim over the real argument.  Just drill
203   // through to the real thing and dump it.
204   Symbol.defaultDump(OS, Indent);
205   uint32_t TypeId = Symbol.getTypeId();
206   auto Type = Symbol.getSession().getSymbolById(TypeId);
207   if (!Type)
208     return;
209   Type->dump(OS, 0, *this);
210 }
211
212 void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
213                           int Indent) {
214   dumpClassParentWithScopeOperator(Symbol, OS, *this);
215   OS << Symbol.getName();
216 }
217
218 void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
219                           int Indent) {
220   uint32_t PointeeId = Symbol.getTypeId();
221   auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
222   if (!PointeeType)
223     return;
224
225   if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
226     FunctionDumper NestedDumper;
227     PointerType Pointer =
228         Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
229     NestedDumper.start(*FuncSig, Pointer, OS);
230   } else {
231     if (Symbol.isConstType())
232       OS << "const ";
233     if (Symbol.isVolatileType())
234       OS << "volatile ";
235     PointeeType->dump(OS, Indent, *this);
236     OS << (Symbol.isReference() ? "&" : "*");
237   }
238 }
239
240 void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
241                           int Indent) {
242   OS << Symbol.getName();
243 }