10b57cec5SDimitry Andric //===- PrettyVariableDumper.cpp ---------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PrettyVariableDumper.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "PrettyBuiltinDumper.h"
120b57cec5SDimitry Andric #include "PrettyFunctionDumper.h"
130b57cec5SDimitry Andric #include "llvm-pdbutil.h"
140b57cec5SDimitry Andric 
1581ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
2081ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
210b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
220b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
230b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
2681ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
2781ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
280b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #include "llvm/Support/Format.h"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric using namespace llvm::codeview;
340b57cec5SDimitry Andric using namespace llvm::pdb;
350b57cec5SDimitry Andric 
VariableDumper(LinePrinter & P)360b57cec5SDimitry Andric VariableDumper::VariableDumper(LinePrinter &P)
370b57cec5SDimitry Andric     : PDBSymDumper(true), Printer(P) {}
380b57cec5SDimitry Andric 
start(const PDBSymbolData & Var,uint32_t Offset)390b57cec5SDimitry Andric void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) {
400b57cec5SDimitry Andric   if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
410b57cec5SDimitry Andric     return;
420b57cec5SDimitry Andric   if (Printer.IsSymbolExcluded(Var.getName()))
430b57cec5SDimitry Andric     return;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   auto VarType = Var.getType();
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   uint64_t Length = VarType->getRawSymbol().getLength();
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   switch (auto LocType = Var.getLocationType()) {
500b57cec5SDimitry Andric   case PDB_LocType::Static:
510b57cec5SDimitry Andric     Printer.NewLine();
520b57cec5SDimitry Andric     Printer << "data [";
530b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Address).get()
540b57cec5SDimitry Andric         << format_hex(Var.getVirtualAddress(), 10);
550b57cec5SDimitry Andric     Printer << ", sizeof=" << Length << "] ";
560b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
570b57cec5SDimitry Andric     dumpSymbolTypeAndName(*VarType, Var.getName());
580b57cec5SDimitry Andric     break;
590b57cec5SDimitry Andric   case PDB_LocType::Constant:
600b57cec5SDimitry Andric     if (isa<PDBSymbolTypeEnum>(*VarType))
610b57cec5SDimitry Andric       break;
620b57cec5SDimitry Andric     Printer.NewLine();
630b57cec5SDimitry Andric     Printer << "data [sizeof=" << Length << "] ";
640b57cec5SDimitry Andric     dumpSymbolTypeAndName(*VarType, Var.getName());
650b57cec5SDimitry Andric     Printer << " = ";
660b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
670b57cec5SDimitry Andric     break;
680b57cec5SDimitry Andric   case PDB_LocType::ThisRel:
690b57cec5SDimitry Andric     Printer.NewLine();
700b57cec5SDimitry Andric     Printer << "data ";
710b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Offset).get()
720b57cec5SDimitry Andric         << "+" << format_hex(Offset + Var.getOffset(), 4)
730b57cec5SDimitry Andric         << " [sizeof=" << Length << "] ";
740b57cec5SDimitry Andric     dumpSymbolTypeAndName(*VarType, Var.getName());
750b57cec5SDimitry Andric     break;
760b57cec5SDimitry Andric   case PDB_LocType::BitField:
770b57cec5SDimitry Andric     Printer.NewLine();
780b57cec5SDimitry Andric     Printer << "data ";
790b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Offset).get()
800b57cec5SDimitry Andric         << "+" << format_hex(Offset + Var.getOffset(), 4)
810b57cec5SDimitry Andric         << " [sizeof=" << Length << "] ";
820b57cec5SDimitry Andric     dumpSymbolTypeAndName(*VarType, Var.getName());
830b57cec5SDimitry Andric     Printer << " : ";
840b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
850b57cec5SDimitry Andric     break;
860b57cec5SDimitry Andric   default:
870b57cec5SDimitry Andric     Printer.NewLine();
880b57cec5SDimitry Andric     Printer << "data [sizeof=" << Length << "] ";
890b57cec5SDimitry Andric     Printer << "unknown(" << LocType << ") ";
900b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
startVbptr(uint32_t Offset,uint32_t Size)950b57cec5SDimitry Andric void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) {
960b57cec5SDimitry Andric   Printer.NewLine();
970b57cec5SDimitry Andric   Printer << "vbptr ";
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Offset).get()
1000b57cec5SDimitry Andric       << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] ";
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
start(const PDBSymbolTypeVTable & Var,uint32_t Offset)1030b57cec5SDimitry Andric void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) {
1040b57cec5SDimitry Andric   Printer.NewLine();
1050b57cec5SDimitry Andric   Printer << "vfptr ";
1060b57cec5SDimitry Andric   auto VTableType = cast<PDBSymbolTypePointer>(Var.getType());
1070b57cec5SDimitry Andric   uint32_t PointerSize = VTableType->getLength();
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Offset).get()
1100b57cec5SDimitry Andric       << "+" << format_hex(Offset + Var.getOffset(), 4)
1110b57cec5SDimitry Andric       << " [sizeof=" << PointerSize << "] ";
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
dump(const PDBSymbolTypeArray & Symbol)1140b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {
1150b57cec5SDimitry Andric   auto ElementType = Symbol.getElementType();
1160b57cec5SDimitry Andric   assert(ElementType);
1170b57cec5SDimitry Andric   if (!ElementType)
1180b57cec5SDimitry Andric     return;
1190b57cec5SDimitry Andric   ElementType->dump(*this);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
dumpRight(const PDBSymbolTypeArray & Symbol)1220b57cec5SDimitry Andric void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) {
1230b57cec5SDimitry Andric   auto ElementType = Symbol.getElementType();
1240b57cec5SDimitry Andric   assert(ElementType);
1250b57cec5SDimitry Andric   if (!ElementType)
1260b57cec5SDimitry Andric     return;
1270b57cec5SDimitry Andric   Printer << '[' << Symbol.getCount() << ']';
1280b57cec5SDimitry Andric   ElementType->dumpRight(*this);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
dump(const PDBSymbolTypeBuiltin & Symbol)1310b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
1320b57cec5SDimitry Andric   BuiltinDumper Dumper(Printer);
1330b57cec5SDimitry Andric   Dumper.start(Symbol);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
dump(const PDBSymbolTypeEnum & Symbol)1360b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
1370b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
dump(const PDBSymbolTypeFunctionSig & Symbol)1400b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
1410b57cec5SDimitry Andric   auto ReturnType = Symbol.getReturnType();
1420b57cec5SDimitry Andric   ReturnType->dump(*this);
1430b57cec5SDimitry Andric   Printer << " ";
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   uint32_t ClassParentId = Symbol.getClassParentId();
1460b57cec5SDimitry Andric   auto ClassParent =
1470b57cec5SDimitry Andric       Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
1480b57cec5SDimitry Andric           ClassParentId);
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   if (ClassParent) {
1510b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Identifier).get()
1520b57cec5SDimitry Andric       << ClassParent->getName();
1530b57cec5SDimitry Andric     Printer << "::";
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
dumpRight(const PDBSymbolTypeFunctionSig & Symbol)1570b57cec5SDimitry Andric void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {
1580b57cec5SDimitry Andric   Printer << "(";
1590b57cec5SDimitry Andric   if (auto Arguments = Symbol.getArguments()) {
1600b57cec5SDimitry Andric     uint32_t Index = 0;
1610b57cec5SDimitry Andric     while (auto Arg = Arguments->getNext()) {
1620b57cec5SDimitry Andric       Arg->dump(*this);
1630b57cec5SDimitry Andric       if (++Index < Arguments->getChildCount())
1640b57cec5SDimitry Andric         Printer << ", ";
1650b57cec5SDimitry Andric     }
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric   Printer << ")";
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   if (Symbol.isConstType())
1700b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
1710b57cec5SDimitry Andric   if (Symbol.isVolatileType())
1720b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   if (Symbol.getRawSymbol().isRestrictedType())
1750b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
dump(const PDBSymbolTypePointer & Symbol)1780b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
1790b57cec5SDimitry Andric   auto PointeeType = Symbol.getPointeeType();
1800b57cec5SDimitry Andric   if (!PointeeType)
1810b57cec5SDimitry Andric     return;
1820b57cec5SDimitry Andric   PointeeType->dump(*this);
1830b57cec5SDimitry Andric   if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
1840b57cec5SDimitry Andric     // A hack to get the calling convention in the right spot.
1850b57cec5SDimitry Andric     Printer << " (";
1860b57cec5SDimitry Andric     PDB_CallingConv CC = FuncSig->getCallingConvention();
1870b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
1880b57cec5SDimitry Andric   } else if (isa<PDBSymbolTypeArray>(PointeeType)) {
1890b57cec5SDimitry Andric     Printer << " (";
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric   Printer << (Symbol.isReference() ? "&" : "*");
1920b57cec5SDimitry Andric   if (Symbol.isConstType())
1930b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const ";
1940b57cec5SDimitry Andric   if (Symbol.isVolatileType())
1950b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile ";
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   if (Symbol.getRawSymbol().isRestrictedType())
1980b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict ";
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
dumpRight(const PDBSymbolTypePointer & Symbol)2010b57cec5SDimitry Andric void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) {
2020b57cec5SDimitry Andric   auto PointeeType = Symbol.getPointeeType();
2030b57cec5SDimitry Andric   assert(PointeeType);
2040b57cec5SDimitry Andric   if (!PointeeType)
2050b57cec5SDimitry Andric     return;
2060b57cec5SDimitry Andric   if (isa<PDBSymbolTypeFunctionSig>(PointeeType) ||
2070b57cec5SDimitry Andric       isa<PDBSymbolTypeArray>(PointeeType)) {
2080b57cec5SDimitry Andric     Printer << ")";
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric   PointeeType->dumpRight(*this);
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
dump(const PDBSymbolTypeTypedef & Symbol)2130b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
2140b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
2150b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
dump(const PDBSymbolTypeUDT & Symbol)2180b57cec5SDimitry Andric void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
2190b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
dumpSymbolTypeAndName(const PDBSymbol & Type,StringRef Name)2220b57cec5SDimitry Andric void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
2230b57cec5SDimitry Andric                                            StringRef Name) {
2240b57cec5SDimitry Andric   Type.dump(*this);
2250b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
2260b57cec5SDimitry Andric   Type.dumpRight(*this);
2270b57cec5SDimitry Andric }
228