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