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 "LinePrinter.h"
11 #include "PrettyBuiltinDumper.h"
13 #include "llvm/DebugInfo/PDB/IPDBSession.h"
14 #include "llvm/DebugInfo/PDB/PDBExtras.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.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 #include "llvm/Support/FormatVariadic.h"
30 using namespace llvm::codeview
;
31 using namespace llvm::pdb
;
35 void dumpClassParentWithScopeOperator(const T
&Symbol
, LinePrinter
&Printer
,
36 FunctionDumper
&Dumper
) {
37 uint32_t ClassParentId
= Symbol
.getClassParentId();
39 Symbol
.getSession().template getConcreteSymbolById
<PDBSymbolTypeUDT
>(
44 WithColor(Printer
, PDB_ColorItem::Type
).get() << ClassParent
->getName();
49 FunctionDumper::FunctionDumper(LinePrinter
&P
)
50 : PDBSymDumper(true), Printer(P
) {}
52 void FunctionDumper::start(const PDBSymbolTypeFunctionSig
&Symbol
,
53 const char *Name
, PointerType Pointer
) {
54 auto ReturnType
= Symbol
.getReturnType();
56 Printer
<< "<unknown-type>";
58 ReturnType
->dump(*this);
60 uint32_t ClassParentId
= Symbol
.getClassParentId();
62 Symbol
.getSession().getConcreteSymbolById
<PDBSymbolTypeUDT
>(
65 PDB_CallingConv CC
= Symbol
.getCallingConvention();
66 bool ShouldDumpCallingConvention
= true;
67 if ((ClassParent
&& CC
== CallingConvention::ThisCall
) ||
68 (!ClassParent
&& CC
== CallingConvention::NearStdCall
)) {
69 ShouldDumpCallingConvention
= false;
72 if (Pointer
== PointerType::None
) {
73 if (ShouldDumpCallingConvention
)
74 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << CC
<< " ";
77 WithColor(Printer
, PDB_ColorItem::Identifier
).get()
78 << ClassParent
->getName();
83 if (ShouldDumpCallingConvention
)
84 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << CC
<< " ";
86 WithColor(Printer
, PDB_ColorItem::Identifier
).get()
87 << ClassParent
->getName();
90 if (Pointer
== PointerType::Reference
)
95 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Name
;
100 if (auto ChildEnum
= Symbol
.getArguments()) {
102 while (auto Arg
= ChildEnum
->getNext()) {
104 if (++Index
< ChildEnum
->getChildCount())
110 if (Symbol
.isConstType())
111 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " const";
112 if (Symbol
.isVolatileType())
113 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " volatile";
116 void FunctionDumper::start(const PDBSymbolFunc
&Symbol
, PointerType Pointer
) {
117 uint64_t FuncStart
= Symbol
.getVirtualAddress();
118 uint64_t FuncEnd
= FuncStart
+ Symbol
.getLength();
121 WithColor(Printer
, PDB_ColorItem::Address
).get() << format_hex(FuncStart
, 10);
122 if (auto DebugStart
= Symbol
.findOneChild
<PDBSymbolFuncDebugStart
>()) {
123 uint64_t Prologue
= DebugStart
->getVirtualAddress() - FuncStart
;
124 WithColor(Printer
, PDB_ColorItem::Offset
).get()
125 << formatv("+{0,2}", Prologue
);
128 WithColor(Printer
, PDB_ColorItem::Address
).get() << format_hex(FuncEnd
, 10);
129 if (auto DebugEnd
= Symbol
.findOneChild
<PDBSymbolFuncDebugEnd
>()) {
130 uint64_t Epilogue
= FuncEnd
- DebugEnd
->getVirtualAddress();
131 WithColor(Printer
, PDB_ColorItem::Offset
).get()
132 << formatv("-{0,2}", Epilogue
);
135 WithColor(Printer
, PDB_ColorItem::Comment
).get()
136 << formatv(" | sizeof={0,3}", Symbol
.getLength());
139 if (Symbol
.hasFramePointer()) {
140 WithColor(Printer
, PDB_ColorItem::Register
).get()
141 << Symbol
.getLocalBasePointerRegisterId();
143 WithColor(Printer
, PDB_ColorItem::Register
).get() << "FPO";
147 if (Symbol
.isVirtual() || Symbol
.isPureVirtual())
148 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "virtual ";
150 auto Signature
= Symbol
.getSignature();
152 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Symbol
.getName();
153 if (Pointer
== PointerType::Pointer
)
155 else if (Pointer
== FunctionDumper::PointerType::Reference
)
160 auto ReturnType
= Signature
->getReturnType();
161 ReturnType
->dump(*this);
164 auto ClassParent
= Symbol
.getClassParent();
165 CallingConvention CC
= Signature
->getCallingConvention();
166 if (Pointer
!= FunctionDumper::PointerType::None
)
169 if ((ClassParent
&& CC
!= CallingConvention::ThisCall
) ||
170 (!ClassParent
&& CC
!= CallingConvention::NearStdCall
)) {
171 WithColor(Printer
, PDB_ColorItem::Keyword
).get()
172 << Signature
->getCallingConvention() << " ";
174 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << Symbol
.getName();
175 if (Pointer
!= FunctionDumper::PointerType::None
) {
176 if (Pointer
== PointerType::Pointer
)
178 else if (Pointer
== FunctionDumper::PointerType::Reference
)
184 if (auto Arguments
= Symbol
.getArguments()) {
186 while (auto Arg
= Arguments
->getNext()) {
187 auto ArgType
= Arg
->getType();
188 ArgType
->dump(*this);
189 WithColor(Printer
, PDB_ColorItem::Identifier
).get() << " "
191 if (++Index
< Arguments
->getChildCount())
194 if (Signature
->isCVarArgs())
198 if (Symbol
.isConstType())
199 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " const";
200 if (Symbol
.isVolatileType())
201 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " volatile";
202 if (Symbol
.isPureVirtual())
206 void FunctionDumper::dump(const PDBSymbolTypeArray
&Symbol
) {
207 auto ElementType
= Symbol
.getElementType();
209 ElementType
->dump(*this);
211 WithColor(Printer
, PDB_ColorItem::LiteralValue
).get() << Symbol
.getLength();
215 void FunctionDumper::dump(const PDBSymbolTypeBuiltin
&Symbol
) {
216 BuiltinDumper
Dumper(Printer
);
217 Dumper
.start(Symbol
);
220 void FunctionDumper::dump(const PDBSymbolTypeEnum
&Symbol
) {
221 dumpClassParentWithScopeOperator(Symbol
, Printer
, *this);
222 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();
225 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg
&Symbol
) {
226 // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
227 // through to the real thing and dump it.
228 uint32_t TypeId
= Symbol
.getTypeId();
229 auto Type
= Symbol
.getSession().getSymbolById(TypeId
);
233 Printer
<< "<unknown-type>";
236 void FunctionDumper::dump(const PDBSymbolTypeTypedef
&Symbol
) {
237 dumpClassParentWithScopeOperator(Symbol
, Printer
, *this);
238 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();
241 void FunctionDumper::dump(const PDBSymbolTypePointer
&Symbol
) {
242 auto PointeeType
= Symbol
.getPointeeType();
246 if (auto FuncSig
= unique_dyn_cast
<PDBSymbolTypeFunctionSig
>(PointeeType
)) {
247 FunctionDumper
NestedDumper(Printer
);
248 PointerType Pointer
=
249 Symbol
.isReference() ? PointerType::Reference
: PointerType::Pointer
;
250 NestedDumper
.start(*FuncSig
, nullptr, Pointer
);
252 if (Symbol
.isConstType())
253 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "const ";
254 if (Symbol
.isVolatileType())
255 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << "volatile ";
256 PointeeType
->dump(*this);
257 Printer
<< (Symbol
.isReference() ? "&" : "*");
259 if (Symbol
.getRawSymbol().isRestrictedType())
260 WithColor(Printer
, PDB_ColorItem::Keyword
).get() << " __restrict";
264 void FunctionDumper::dump(const PDBSymbolTypeUDT
&Symbol
) {
265 WithColor(Printer
, PDB_ColorItem::Type
).get() << Symbol
.getName();