ClassDefinitionDumper.cpp revision 4c5e43da7792f75567b693105cc53e3f1992ad98
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 "EnumDumper.h"
12#include "FunctionDumper.h"
13#include "LinePrinter.h"
14#include "llvm-pdbdump.h"
15#include "TypedefDumper.h"
16#include "VariableDumper.h"
17
18#include "llvm/DebugInfo/PDB/IPDBSession.h"
19#include "llvm/DebugInfo/PDB/PDBExtras.h"
20#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
21#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
22#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
23#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
24#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
25#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
26#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
27#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
28#include "llvm/Support/Format.h"
29
30using namespace llvm;
31
32ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
33    : PDBSymDumper(true), Printer(P) {}
34
35void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
36  std::string Name = Class.getName();
37  WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
38  WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
39
40  auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
41  if (Bases->getChildCount() > 0) {
42    Printer.Indent();
43    Printer.NewLine();
44    Printer << ":";
45    uint32_t BaseIndex = 0;
46    while (auto Base = Bases->getNext()) {
47      Printer << " ";
48      WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
49      if (Base->isVirtualBaseClass())
50        WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
51      WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
52      if (++BaseIndex < Bases->getChildCount()) {
53        Printer.NewLine();
54        Printer << ",";
55      }
56    }
57    Printer.Unindent();
58  }
59
60  Printer << " {";
61  auto Children = Class.findAllChildren();
62  if (Children->getChildCount() == 0) {
63    Printer << "}";
64    return;
65  }
66
67  // Try to dump symbols organized by member access level.  Public members
68  // first, then protected, then private.  This might be slow, so it's worth
69  // reconsidering the value of this if performance of large PDBs is a problem.
70  // NOTE: Access level of nested types is not recorded in the PDB, so we have
71  // a special case for them.
72  SymbolGroupByAccess Groups;
73  Groups.insert(std::make_pair(0, SymbolGroup()));
74  Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup()));
75  Groups.insert(
76      std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup()));
77  Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup()));
78
79  while (auto Child = Children->getNext()) {
80    PDB_MemberAccess Access = Child->getRawSymbol().getAccess();
81    if (isa<PDBSymbolTypeBaseClass>(*Child))
82      continue;
83
84    auto &AccessGroup = Groups.find((int)Access)->second;
85
86    if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
87      if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
88        continue;
89      if (Func->getLength() == 0 && !Func->isPureVirtual() &&
90          !Func->isIntroVirtualFunction())
91        continue;
92      Child.release();
93      AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
94    } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) {
95      Child.release();
96      AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data));
97    } else {
98      AccessGroup.Unknown.push_back(std::move(Child));
99    }
100  }
101
102  int Count = 0;
103  Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0]);
104  Count += dumpAccessGroup(PDB_MemberAccess::Public,
105                           Groups[(int)PDB_MemberAccess::Public]);
106  Count += dumpAccessGroup(PDB_MemberAccess::Protected,
107                           Groups[(int)PDB_MemberAccess::Protected]);
108  Count += dumpAccessGroup(PDB_MemberAccess::Private,
109                           Groups[(int)PDB_MemberAccess::Private]);
110  if (Count > 0)
111    Printer.NewLine();
112  Printer << "}";
113}
114
115int 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