1 //===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "PrettyFunctionDumper.h"
10 #include "PrettyBuiltinDumper.h"
12 #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
13 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
14 #include "llvm/DebugInfo/PDB/IPDBSession.h"
15 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
16 #include "llvm/DebugInfo/PDB/PDBExtras.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
27 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
28 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
29 #include "llvm/Support/Format.h"
30 #include "llvm/Support/FormatVariadic.h"
33 using namespace llvm::codeview
;
34 using namespace llvm::pdb
;
38 void dumpClassParentWithScopeOperator(const T
&Symbol
, LinePrinter
&Printer
,
39 FunctionDumper
&Dumper
) {
40 uint32_t ClassParentId
= Symbol
.getClassParentId();
42 Symbol
.getSession().template getConcreteSymbolById
<PDBSymbolTypeUDT
>(
47 WithColor(Printer
, PDB_ColorItem::Type
).get() << ClassParent
->getName();
52 FunctionDumper::FunctionDumper(LinePrinter
&P
)
53 : PDBSymDumper(true), Printer(P
) {}
55 void FunctionDumper::start(const PDBSymbolTypeFunctionSig
&Symbol
,
56 const char *Name
, PointerType Pointer
) {
57 auto ReturnType
= Symbol
.getReturnType();
59 Printer
<< "<unknown-type>";
61 ReturnType
->dump(*this);
63 uint32_t ClassParentId
= Symbol
.getClassParentId();
65 Symbol
.getSession().getConcreteSymbolById
<PDBSymbolTypeUDT
>(
68 PDB_CallingConv CC
= Symbol
.getCallingConvention();
69 bool ShouldDumpCallingConvention
= true;
70 if ((ClassParent
&& CC
== CallingConvention::ThisCall
) ||
71 (!ClassParent
&& CC
== CallingConvention::NearStdCall
)) {
72 ShouldDumpCallingConvention
= false;
75 if (Pointer
== PointerType::None
) {
76 if (ShouldDumpCallingConvention
)
77 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << CC
<< " ";
80 WithColor(Printer
, PDB_ColorItem::Identifier
).get()
81 << ClassParent
->getName();
86 if (ShouldDumpCallingConvention
)
87 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << CC
<< " ";
89 WithColor(Printer
, PDB_ColorItem::Identifier
).get()
90 << ClassParent
->getName();
93 if (Pointer
== PointerType::Reference
)
98 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Name
;
103 if (auto ChildEnum
= Symbol
.getArguments()) {
105 while (auto Arg
= ChildEnum
->getNext()) {
107 if (++Index
< ChildEnum
->getChildCount())
113 if (Symbol
.isConstType())
114 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " const";
115 if (Symbol
.isVolatileType())
116 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " volatile";
119 void FunctionDumper::start(const PDBSymbolFunc
&Symbol
, PointerType Pointer
) {
120 uint64_t FuncStart
= Symbol
.getVirtualAddress();
121 uint64_t FuncEnd
= FuncStart
+ Symbol
.getLength();
124 WithColor(Printer
, PDB_ColorItem::Address
).get() << format_hex(FuncStart
, 10);
125 if (auto DebugStart
= Symbol
.findOneChild
<PDBSymbolFuncDebugStart
>()) {
126 uint64_t Prologue
= DebugStart
->getVirtualAddress() - FuncStart
;
127 WithColor(Printer
, PDB_ColorItem::Offset
).get()
128 << formatv("+{0,2}", Prologue
);
131 WithColor(Printer
, PDB_ColorItem::Address
).get() << format_hex(FuncEnd
, 10);
132 if (auto DebugEnd
= Symbol
.findOneChild
<PDBSymbolFuncDebugEnd
>()) {
133 uint64_t Epilogue
= FuncEnd
- DebugEnd
->getVirtualAddress();
134 WithColor(Printer
, PDB_ColorItem::Offset
).get()
135 << formatv("-{0,2}", Epilogue
);
138 WithColor(Printer
, PDB_ColorItem::Comment
).get()
139 << formatv(" | sizeof={0,3}", Symbol
.getLength());
142 if (Symbol
.hasFramePointer()) {
143 WithColor(Printer
, PDB_ColorItem::Register
).get()
144 << CPURegister
{Symbol
.getRawSymbol().getPlatform(),
145 Symbol
.getLocalBasePointerRegisterId()};
147 WithColor(Printer
, PDB_ColorItem::Register
).get() << "FPO";
151 if (Symbol
.isVirtual() || Symbol
.isPureVirtual())
152 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "virtual ";
154 auto Signature
= Symbol
.getSignature();
156 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Symbol
.getName();
157 if (Pointer
== PointerType::Pointer
)
159 else if (Pointer
== FunctionDumper::PointerType::Reference
)
164 auto ReturnType
= Signature
->getReturnType();
165 ReturnType
->dump(*this);
168 auto ClassParent
= Symbol
.getClassParent();
169 CallingConvention CC
= Signature
->getCallingConvention();
170 if (Pointer
!= FunctionDumper::PointerType::None
)
173 if ((ClassParent
&& CC
!= CallingConvention::ThisCall
) ||
174 (!ClassParent
&& CC
!= CallingConvention::NearStdCall
)) {
175 WithColor(Printer
, PDB_ColorItem::Keyword
).get()
176 << Signature
->getCallingConvention() << " ";
178 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Symbol
.getName();
179 if (Pointer
!= FunctionDumper::PointerType::None
) {
180 if (Pointer
== PointerType::Pointer
)
182 else if (Pointer
== FunctionDumper::PointerType::Reference
)
188 if (auto Arguments
= Symbol
.getArguments()) {
190 while (auto Arg
= Arguments
->getNext()) {
191 auto ArgType
= Arg
->getType();
192 ArgType
->dump(*this);
193 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << " "
195 if (++Index
< Arguments
->getChildCount())
198 if (Signature
->isCVarArgs())
202 if (Symbol
.isConstType())
203 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " const";
204 if (Symbol
.isVolatileType())
205 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " volatile";
206 if (Symbol
.isPureVirtual())
210 void FunctionDumper::dump(const PDBSymbolTypeArray
&Symbol
) {
211 auto ElementType
= Symbol
.getElementType();
213 ElementType
->dump(*this);
215 WithColor(Printer
, PDB_ColorItem::LiteralValue
).get() << Symbol
.getLength();
219 void FunctionDumper::dump(const PDBSymbolTypeBuiltin
&Symbol
) {
220 BuiltinDumper
Dumper(Printer
);
221 Dumper
.start(Symbol
);
224 void FunctionDumper::dump(const PDBSymbolTypeEnum
&Symbol
) {
225 dumpClassParentWithScopeOperator(Symbol
, Printer
, *this);
226 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();
229 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg
&Symbol
) {
230 // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
231 // through to the real thing and dump it.
232 uint32_t TypeId
= Symbol
.getTypeId();
233 auto Type
= Symbol
.getSession().getSymbolById(TypeId
);
237 Printer
<< "<unknown-type>";
240 void FunctionDumper::dump(const PDBSymbolTypeTypedef
&Symbol
) {
241 dumpClassParentWithScopeOperator(Symbol
, Printer
, *this);
242 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();
245 void FunctionDumper::dump(const PDBSymbolTypePointer
&Symbol
) {
246 auto PointeeType
= Symbol
.getPointeeType();
250 if (auto FuncSig
= unique_dyn_cast
<PDBSymbolTypeFunctionSig
>(PointeeType
)) {
251 FunctionDumper
NestedDumper(Printer
);
252 PointerType Pointer
=
253 Symbol
.isReference() ? PointerType::Reference
: PointerType::Pointer
;
254 NestedDumper
.start(*FuncSig
, nullptr, Pointer
);
256 if (Symbol
.isConstType())
257 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "const ";
258 if (Symbol
.isVolatileType())
259 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "volatile ";
260 PointeeType
->dump(*this);
261 Printer
<< (Symbol
.isReference() ? "&" : "*");
263 if (Symbol
.getRawSymbol().isRestrictedType())
264 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " __restrict";
268 void FunctionDumper::dump(const PDBSymbolTypeUDT
&Symbol
) {
269 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();