ClassDefinitionDumper.cpp revision ebe69fe11e48d322045d5949c83283927a0d790b
1//===- ClassDefinitionDumper.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 "ClassDefinitionDumper.h" 11#include "FunctionDumper.h" 12#include "llvm-pdbdump.h" 13#include "TypedefDumper.h" 14#include "VariableDumper.h" 15 16#include "llvm/DebugInfo/PDB/IPDBSession.h" 17#include "llvm/DebugInfo/PDB/PDBExtras.h" 18#include "llvm/DebugInfo/PDB/PDBSymbolData.h" 19#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 20#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" 21#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 22#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 23#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 24#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 25#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" 26#include "llvm/Support/Format.h" 27 28using namespace llvm; 29 30ClassDefinitionDumper::ClassDefinitionDumper() : PDBSymDumper(true) {} 31 32void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class, 33 raw_ostream &OS, int Indent) { 34 OS << "class " << Class.getName() << " {"; 35 auto Children = Class.findAllChildren(); 36 if (Children->getChildCount() == 0) { 37 OS << "}"; 38 return; 39 } 40 41 // Try to dump symbols organized by member access level. Public members 42 // first, then protected, then private. This might be slow, so it's worth 43 // reconsidering the value of this if performance of large PDBs is a problem. 44 // NOTE: Access level of nested types is not recorded in the PDB, so we have 45 // a special case for them. 46 SymbolGroupByAccess Groups; 47 Groups.insert(std::make_pair(0, SymbolGroup())); 48 Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup())); 49 Groups.insert( 50 std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup())); 51 Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup())); 52 53 while (auto Child = Children->getNext()) { 54 PDB_MemberAccess Access = Child->getRawSymbol().getAccess(); 55 if (isa<PDBSymbolTypeBaseClass>(*Child)) 56 continue; 57 58 auto &AccessGroup = Groups.find((int)Access)->second; 59 60 if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) { 61 if (Func->isCompilerGenerated()) 62 continue; 63 if (Func->getLength() == 0 && !Func->isPureVirtual()) 64 continue; 65 Child.release(); 66 AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func)); 67 } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) { 68 Child.release(); 69 AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data)); 70 } else { 71 AccessGroup.Unknown.push_back(std::move(Child)); 72 } 73 } 74 75 int Count = 0; 76 Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0], OS, Indent); 77 Count += dumpAccessGroup(PDB_MemberAccess::Public, 78 Groups[(int)PDB_MemberAccess::Public], OS, Indent); 79 Count += 80 dumpAccessGroup(PDB_MemberAccess::Protected, 81 Groups[(int)PDB_MemberAccess::Protected], OS, Indent); 82 Count += dumpAccessGroup(PDB_MemberAccess::Private, 83 Groups[(int)PDB_MemberAccess::Private], OS, Indent); 84 85 if (Count > 0) 86 OS << newline(Indent); 87 OS << "}"; 88} 89 90int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access, 91 const SymbolGroup &Group, 92 raw_ostream &OS, int Indent) { 93 if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty()) 94 return 0; 95 96 int Count = 0; 97 if (Access == PDB_MemberAccess::Private) 98 OS << newline(Indent) << "private:"; 99 else if (Access == PDB_MemberAccess::Protected) 100 OS << newline(Indent) << "protected:"; 101 else if (Access == PDB_MemberAccess::Public) 102 OS << newline(Indent) << "public:"; 103 for (auto iter = Group.Functions.begin(), end = Group.Functions.end(); 104 iter != end; ++iter) { 105 ++Count; 106 (*iter)->dump(OS, Indent + 2, *this); 107 } 108 for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end; 109 ++iter) { 110 ++Count; 111 (*iter)->dump(OS, Indent + 2, *this); 112 } 113 for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end(); 114 iter != end; ++iter) { 115 ++Count; 116 (*iter)->dump(OS, Indent + 2, *this); 117 } 118 return Count; 119} 120 121void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol, 122 raw_ostream &OS, int Indent) {} 123 124void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS, 125 int Indent) { 126 VariableDumper Dumper; 127 Dumper.start(Symbol, OS, Indent); 128} 129 130void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, 131 int Indent) { 132 FunctionDumper Dumper; 133 Dumper.start(Symbol, FunctionDumper::PointerType::None, OS, Indent); 134} 135 136void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol, 137 raw_ostream &OS, int Indent) {} 138 139void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol, 140 raw_ostream &OS, int Indent) { 141 OS << newline(Indent) << "enum " << Symbol.getName(); 142} 143 144void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol, 145 raw_ostream &OS, int Indent) { 146 OS << newline(Indent); 147 TypedefDumper Dumper; 148 Dumper.start(Symbol, OS, Indent); 149} 150 151void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol, 152 raw_ostream &OS, int Indent) {} 153