1159097Smaxim//===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===// 2281464Sngie// 3281464Sngie// The LLVM Compiler Infrastructure 4281464Sngie// 5281464Sngie// This file is distributed under the University of Illinois Open Source 6281464Sngie// License. See LICENSE.TXT for details. 7281464Sngie// 8281464Sngie//===----------------------------------------------------------------------===// 9281464Sngie 10281464Sngie#include "ClassDefinitionDumper.h" 11159097Smaxim#include "EnumDumper.h" 12281464Sngie#include "FunctionDumper.h" 13281464Sngie#include "LinePrinter.h" 14281464Sngie#include "llvm-pdbdump.h" 15281464Sngie#include "TypedefDumper.h" 16281464Sngie#include "VariableDumper.h" 17281464Sngie 18281464Sngie#include "llvm/DebugInfo/PDB/IPDBSession.h" 19281464Sngie#include "llvm/DebugInfo/PDB/PDBExtras.h" 20281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolData.h" 21159097Smaxim#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 22281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" 23281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 24281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 25281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 26281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 27281464Sngie#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" 28281464Sngie#include "llvm/Support/Format.h" 29281464Sngie 30281464Sngieusing namespace llvm; 31159097Smaxim 32281464SngieClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P) 33281464Sngie : PDBSymDumper(true), Printer(P) {} 34281464Sngie 35281464Sngievoid ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { 36281464Sngie std::string Name = Class.getName(); 37281464Sngie WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; 38281464Sngie WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); 39281464Sngie 40281464Sngie auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>(); 41159097Smaxim if (Bases->getChildCount() > 0) { 42281464Sngie Printer.Indent(); 43281464Sngie Printer.NewLine(); 44281464Sngie Printer << ":"; 45281464Sngie uint32_t BaseIndex = 0; 46281464Sngie while (auto Base = Bases->getNext()) { 47281464Sngie Printer << " "; 48281464Sngie WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess(); 49281464Sngie if (Base->isVirtualBaseClass()) 50281464Sngie WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual"; 51159097Smaxim WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName(); 52281464Sngie if (++BaseIndex < Bases->getChildCount()) { 53281464Sngie Printer.NewLine(); 54281464Sngie Printer << ","; 55281464Sngie } 56281464Sngie } 57281464Sngie Printer.Unindent(); 58281464Sngie } 59281464Sngie 60281464Sngie Printer << " {"; 61281464Sngie auto Children = Class.findAllChildren(); 62281464Sngie if (Children->getChildCount() == 0) { 63281464Sngie Printer << "}"; 64281464Sngie return; 65281464Sngie } 66281464Sngie 67281464Sngie // Try to dump symbols organized by member access level. Public members 68281464Sngie // first, then protected, then private. This might be slow, so it's worth 69281464Sngie // reconsidering the value of this if performance of large PDBs is a problem. 70281464Sngie // NOTE: Access level of nested types is not recorded in the PDB, so we have 71281464Sngie // a special case for them. 72281464Sngie SymbolGroupByAccess Groups; 73281464Sngie Groups.insert(std::make_pair(0, SymbolGroup())); 74281464Sngie Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup())); 75281464Sngie Groups.insert( 76281464Sngie std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup())); 77281464Sngie Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup())); 78281464Sngie 79281464Sngie while (auto Child = Children->getNext()) { 80281464Sngie PDB_MemberAccess Access = Child->getRawSymbol().getAccess(); 81281464Sngie if (isa<PDBSymbolTypeBaseClass>(*Child)) 82281464Sngie continue; 83281464Sngie 84281464Sngie auto &AccessGroup = Groups.find((int)Access)->second; 85281464Sngie 86281464Sngie if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) { 87281464Sngie if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated) 88281464Sngie continue; 89281464Sngie if (Func->getLength() == 0 && !Func->isPureVirtual() && 90281464Sngie !Func->isIntroVirtualFunction()) 91281464Sngie continue; 92281464Sngie Child.release(); 93281464Sngie AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func)); 94281464Sngie } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) { 95281464Sngie Child.release(); 96281464Sngie AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data)); 97281464Sngie } else { 98281464Sngie AccessGroup.Unknown.push_back(std::move(Child)); 99281464Sngie } 100281464Sngie } 101281464Sngie 102281464Sngie int Count = 0; 103281464Sngie Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0]); 104281464Sngie Count += dumpAccessGroup(PDB_MemberAccess::Public, 105281464Sngie Groups[(int)PDB_MemberAccess::Public]); 106281464Sngie Count += dumpAccessGroup(PDB_MemberAccess::Protected, 107281464Sngie Groups[(int)PDB_MemberAccess::Protected]); 108281464Sngie Count += dumpAccessGroup(PDB_MemberAccess::Private, 109281464Sngie Groups[(int)PDB_MemberAccess::Private]); 110281464Sngie if (Count > 0) 111281464Sngie Printer.NewLine(); 112281464Sngie Printer << "}"; 113281464Sngie} 114281464Sngie 115281464Sngieint ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access, 116 const SymbolGroup &Group) { 117 if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty()) 118 return 0; 119 120 int Count = 0; 121 if (Access == PDB_MemberAccess::Private) { 122 Printer.NewLine(); 123 WithColor(Printer, PDB_ColorItem::Keyword).get() << "private"; 124 Printer << ":"; 125 } else if (Access == PDB_MemberAccess::Protected) { 126 Printer.NewLine(); 127 WithColor(Printer, PDB_ColorItem::Keyword).get() << "protected"; 128 Printer << ":"; 129 } else if (Access == PDB_MemberAccess::Public) { 130 Printer.NewLine(); 131 WithColor(Printer, PDB_ColorItem::Keyword).get() << "public"; 132 Printer << ":"; 133 } 134 Printer.Indent(); 135 for (auto iter = Group.Functions.begin(), end = Group.Functions.end(); 136 iter != end; ++iter) { 137 ++Count; 138 (*iter)->dump(*this); 139 } 140 for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end; 141 ++iter) { 142 ++Count; 143 (*iter)->dump(*this); 144 } 145 for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end(); 146 iter != end; ++iter) { 147 ++Count; 148 (*iter)->dump(*this); 149 } 150 Printer.Unindent(); 151 return Count; 152} 153 154void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {} 155 156void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) { 157 VariableDumper Dumper(Printer); 158 Dumper.start(Symbol); 159} 160 161void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) { 162 if (Printer.IsSymbolExcluded(Symbol.getName())) 163 return; 164 165 Printer.NewLine(); 166 FunctionDumper Dumper(Printer); 167 Dumper.start(Symbol, FunctionDumper::PointerType::None); 168} 169 170void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {} 171 172void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) { 173 if (Printer.IsTypeExcluded(Symbol.getName())) 174 return; 175 176 Printer.NewLine(); 177 EnumDumper Dumper(Printer); 178 Dumper.start(Symbol); 179} 180 181void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 182 if (Printer.IsTypeExcluded(Symbol.getName())) 183 return; 184 185 Printer.NewLine(); 186 TypedefDumper Dumper(Printer); 187 Dumper.start(Symbol); 188} 189 190void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {} 191