PrettyTypeDumper.cpp revision 353358
167754Smsmith//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===//
267754Smsmith//
367754Smsmith// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4151937Sjkim// See https://llvm.org/LICENSE.txt for license information.
567754Smsmith// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667754Smsmith//
767754Smsmith//===----------------------------------------------------------------------===//
867754Smsmith
967754Smsmith#include "PrettyTypeDumper.h"
1067754Smsmith
1167754Smsmith#include "LinePrinter.h"
12151937Sjkim#include "PrettyBuiltinDumper.h"
1370243Smsmith#include "PrettyClassDefinitionDumper.h"
1467754Smsmith#include "PrettyEnumDumper.h"
1567754Smsmith#include "PrettyFunctionDumper.h"
1667754Smsmith#include "PrettyTypedefDumper.h"
1767754Smsmith#include "llvm-pdbutil.h"
1867754Smsmith
1967754Smsmith#include "llvm/DebugInfo/PDB/IPDBSession.h"
2067754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
2167754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
2267754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
2367754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
2467754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
2567754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
2667754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
2767754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
2867754Smsmith#include "llvm/DebugInfo/PDB/UDTLayout.h"
2967754Smsmith#include "llvm/Support/Compiler.h"
3067754Smsmith#include "llvm/Support/FormatVariadic.h"
3167754Smsmith
3267754Smsmithusing namespace llvm;
3367754Smsmithusing namespace llvm::pdb;
3467754Smsmith
3567754Smsmithusing LayoutPtr = std::unique_ptr<ClassLayout>;
3667754Smsmith
3767754Smsmithtypedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
3867754Smsmith
3967754Smsmithstatic bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
4067754Smsmith  return S1->getName() < S2->getName();
4167754Smsmith}
4267754Smsmith
4367754Smsmithstatic bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
4467754Smsmith  return S1->getSize() < S2->getSize();
4567754Smsmith}
4667754Smsmith
4767754Smsmithstatic bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
4867754Smsmith  return S1->deepPaddingSize() < S2->deepPaddingSize();
4967754Smsmith}
5067754Smsmith
5167754Smsmithstatic bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {
5267754Smsmith  double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();
5367754Smsmith  double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();
5467754Smsmith  return Pct1 < Pct2;
5567754Smsmith}
5667754Smsmith
5767754Smsmithstatic bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {
5867754Smsmith  return S1->immediatePadding() < S2->immediatePadding();
5967754Smsmith}
6067754Smsmith
6167754Smsmithstatic bool ComparePaddingPctImmediate(const LayoutPtr &S1,
6267754Smsmith                                       const LayoutPtr &S2) {
6367754Smsmith  double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();
6467754Smsmith  double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();
6567754Smsmith  return Pct1 < Pct2;
6667754Smsmith}
6767754Smsmith
6867754Smsmithstatic CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
6967754Smsmith  switch (Mode) {
7067754Smsmith  case opts::pretty::ClassSortMode::Name:
7167754Smsmith    return CompareNames;
7267754Smsmith  case opts::pretty::ClassSortMode::Size:
7367754Smsmith    return CompareSizes;
7467754Smsmith  case opts::pretty::ClassSortMode::Padding:
7567754Smsmith    return ComparePadding;
7667754Smsmith  case opts::pretty::ClassSortMode::PaddingPct:
7767754Smsmith    return ComparePaddingPct;
7867754Smsmith  case opts::pretty::ClassSortMode::PaddingImmediate:
7967754Smsmith    return ComparePaddingImmediate;
8067754Smsmith  case opts::pretty::ClassSortMode::PaddingPctImmediate:
8167754Smsmith    return ComparePaddingPctImmediate;
8267754Smsmith  default:
8367754Smsmith    return nullptr;
8467754Smsmith  }
8567754Smsmith}
8667754Smsmith
8767754Smsmithtemplate <typename Enumerator>
8867754Smsmithstatic std::vector<std::unique_ptr<ClassLayout>>
8967754SmsmithfilterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
9067754Smsmith                       uint32_t UnfilteredCount) {
9167754Smsmith  std::vector<std::unique_ptr<ClassLayout>> Filtered;
9267754Smsmith
9367754Smsmith  Filtered.reserve(UnfilteredCount);
9467754Smsmith  CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
9567754Smsmith
9667754Smsmith  if (UnfilteredCount > 10000) {
9767754Smsmith    errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);
9867754Smsmith    errs().flush();
9967754Smsmith  }
10067754Smsmith  uint32_t Examined = 0;
10167754Smsmith  uint32_t Discarded = 0;
10267754Smsmith  while (auto Class = E.getNext()) {
10367754Smsmith    ++Examined;
10467754Smsmith    if (Examined % 10000 == 0) {
10567754Smsmith      errs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
10667754Smsmith                        Examined, UnfilteredCount, Discarded);
10767754Smsmith      errs().flush();
10867754Smsmith    }
10967754Smsmith
11067754Smsmith    if (Class->getUnmodifiedTypeId() != 0) {
11167754Smsmith      ++Discarded;
11267754Smsmith      continue;
11367754Smsmith    }
11467754Smsmith
11567754Smsmith    if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
11667754Smsmith      ++Discarded;
11767754Smsmith      continue;
11867754Smsmith    }
11967754Smsmith
120151600Sobrien    auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
121151600Sobrien    if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
122151600Sobrien      ++Discarded;
123151600Sobrien      continue;
12467754Smsmith    }
12577424Smsmith    if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {
12691116Smsmith      ++Discarded;
12767754Smsmith      continue;
12867754Smsmith    }
12977424Smsmith
13067754Smsmith    Filtered.push_back(std::move(Layout));
131138287Smarks  }
132138287Smarks
133138287Smarks  if (Comp)
134138287Smarks    llvm::sort(Filtered, Comp);
135138287Smarks  return Filtered;
136138287Smarks}
137138287Smarks
138138287SmarksTypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
139138287Smarks
140138287Smarkstemplate <typename T>
141138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) {
142138287Smarks  return false;
143138287Smarks}
144138287Smarks
145138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer,
146138287Smarks                           const PDBSymbolTypeEnum &Enum) {
147138287Smarks  if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength()))
148138287Smarks    return true;
149138287Smarks  // Dump member enums when dumping their class definition.
150138287Smarks  if (nullptr != Enum.getClassParent())
151138287Smarks    return true;
152138287Smarks  return false;
153138287Smarks}
154138287Smarks
155138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer,
156138287Smarks                           const PDBSymbolTypeTypedef &Typedef) {
157138287Smarks  return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength());
158138287Smarks}
159138287Smarks
160138287Smarkstemplate <typename SymbolT>
161138287Smarksstatic void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe,
162138287Smarks                               TypeDumper &TD, StringRef Label) {
163138287Smarks  if (auto Children = Exe.findAllChildren<SymbolT>()) {
164138287Smarks    Printer.NewLine();
165138287Smarks    WithColor(Printer, PDB_ColorItem::Identifier).get() << Label;
166138287Smarks    Printer << ": (" << Children->getChildCount() << " items)";
167138287Smarks    Printer.Indent();
168138287Smarks    while (auto Child = Children->getNext()) {
169138287Smarks      if (isTypeExcluded(Printer, *Child))
170138287Smarks        continue;
171138287Smarks
172138287Smarks      Printer.NewLine();
173138287Smarks      Child->dump(TD);
174138287Smarks    }
175138287Smarks    Printer.Unindent();
176138287Smarks  }
177138287Smarks}
17867754Smsmith
17967754Smsmithstatic void printClassDecl(LinePrinter &Printer,
18067754Smsmith                           const PDBSymbolTypeUDT &Class) {
18167754Smsmith  if (Class.getUnmodifiedTypeId() != 0) {
18267754Smsmith    if (Class.isConstType())
18367754Smsmith      WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
18467754Smsmith    if (Class.isVolatileType())
18567754Smsmith      WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
18667754Smsmith    if (Class.isUnalignedType())
18767754Smsmith      WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";
18867754Smsmith  }
18967754Smsmith  WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
19067754Smsmith  WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
19167754Smsmith}
19267754Smsmith
19367754Smsmithvoid TypeDumper::start(const PDBSymbolExe &Exe) {
19467754Smsmith  if (opts::pretty::Enums)
19577424Smsmith    dumpSymbolCategory<PDBSymbolTypeEnum>(Printer, Exe, *this, "Enums");
19667754Smsmith
19767754Smsmith  if (opts::pretty::Funcsigs)
19877424Smsmith    dumpSymbolCategory<PDBSymbolTypeFunctionSig>(Printer, Exe, *this,
19967754Smsmith                                                 "Function Signatures");
20067754Smsmith
20191116Smsmith  if (opts::pretty::Typedefs)
20267754Smsmith    dumpSymbolCategory<PDBSymbolTypeTypedef>(Printer, Exe, *this, "Typedefs");
20367754Smsmith
20477424Smsmith  if (opts::pretty::Arrays)
20577424Smsmith    dumpSymbolCategory<PDBSymbolTypeArray>(Printer, Exe, *this, "Arrays");
20677424Smsmith
20777424Smsmith  if (opts::pretty::Pointers)
20867754Smsmith    dumpSymbolCategory<PDBSymbolTypePointer>(Printer, Exe, *this, "Pointers");
20967754Smsmith
21067754Smsmith  if (opts::pretty::VTShapes)
21191116Smsmith    dumpSymbolCategory<PDBSymbolTypeVTableShape>(Printer, Exe, *this,
21291116Smsmith                                                 "VFTable Shapes");
21391116Smsmith
21491116Smsmith  if (opts::pretty::Classes) {
21591116Smsmith    if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
21667754Smsmith      uint32_t All = Classes->getChildCount();
21767754Smsmith
21867754Smsmith      Printer.NewLine();
21967754Smsmith      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
22067754Smsmith
22187031Smsmith      bool Precompute = false;
22267754Smsmith      Precompute =
22367754Smsmith          (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
22467754Smsmith
22585756Smsmith      // If we're using no sort mode, then we can start getting immediate output
22667754Smsmith      // from the tool by just filtering as we go, rather than processing
22767754Smsmith      // everything up front so that we can sort it.  This makes the tool more
22867754Smsmith      // responsive.  So only precompute the filtered/sorted set of classes if
22967754Smsmith      // necessary due to the specified options.
230117521Snjl      std::vector<LayoutPtr> Filtered;
23191116Smsmith      uint32_t Shown = All;
23267754Smsmith      if (Precompute) {
23382367Smsmith        Filtered = filterAndSortClassDefs(Printer, *Classes, All);
23467754Smsmith
23567754Smsmith        Shown = Filtered.size();
23667754Smsmith      }
23767754Smsmith
23867754Smsmith      Printer << ": (Showing " << Shown << " items";
23977424Smsmith      if (Shown < All)
24077424Smsmith        Printer << ", " << (All - Shown) << " filtered";
24177424Smsmith      Printer << ")";
24282367Smsmith      Printer.Indent();
24382367Smsmith
24467754Smsmith      // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
24567754Smsmith      // the DIA enumerator and filter on the fly.
24667754Smsmith      if (Precompute) {
24767754Smsmith        for (auto &Class : Filtered)
24891116Smsmith          dumpClassLayout(*Class);
24967754Smsmith      } else {
25067754Smsmith        while (auto Class = Classes->getNext()) {
25167754Smsmith          if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
25267754Smsmith            continue;
25377424Smsmith
25467754Smsmith          // No point duplicating a full class layout.  Just print the modified
25567754Smsmith          // declaration and continue.
25667754Smsmith          if (Class->getUnmodifiedTypeId() != 0) {
25767754Smsmith            Printer.NewLine();
25867754Smsmith            printClassDecl(Printer, *Class);
25967754Smsmith            continue;
26067754Smsmith          }
26167754Smsmith
26267754Smsmith          auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
26367754Smsmith          if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
26467754Smsmith            continue;
26567754Smsmith
26667754Smsmith          dumpClassLayout(*Layout);
26767754Smsmith        }
26867754Smsmith      }
26977424Smsmith
27067754Smsmith      Printer.Unindent();
27167754Smsmith    }
27267754Smsmith  }
27367754Smsmith}
27491116Smsmith
27567754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
27667754Smsmith  assert(opts::pretty::Enums);
27777424Smsmith
27877424Smsmith  EnumDumper Dumper(Printer);
27977424Smsmith  Dumper.start(Symbol);
28077424Smsmith}
28167754Smsmith
28267754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
28367754Smsmith  BuiltinDumper BD(Printer);
28491116Smsmith  BD.start(Symbol);
28591116Smsmith}
28691116Smsmith
28791116Smsmithvoid TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
28891116Smsmith  printClassDecl(Printer, Symbol);
28967754Smsmith}
29085756Smsmith
29167754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
292117521Snjl  assert(opts::pretty::Typedefs);
29369450Smsmith
29477424Smsmith  TypedefDumper Dumper(Printer);
29577424Smsmith  Dumper.start(Symbol);
29677424Smsmith}
29777424Smsmith
29877424Smsmithvoid TypeDumper::dump(const PDBSymbolTypeArray &Symbol) {
29991116Smsmith  auto ElementType = Symbol.getElementType();
30067754Smsmith
30182367Smsmith  ElementType->dump(*this);
30282367Smsmith  Printer << "[";
30377424Smsmith  WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getCount();
30477424Smsmith  Printer << "]";
30577424Smsmith}
30682367Smsmith
30767754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
30867754Smsmith  FunctionDumper Dumper(Printer);
30991116Smsmith  Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
31067754Smsmith}
31167754Smsmith
31267754Smsmithvoid TypeDumper::dump(const PDBSymbolTypePointer &Symbol) {
31367754Smsmith  std::unique_ptr<PDBSymbol> P = Symbol.getPointeeType();
31477424Smsmith
31567754Smsmith  if (auto *FS = dyn_cast<PDBSymbolTypeFunctionSig>(P.get())) {
31667754Smsmith    FunctionDumper Dumper(Printer);
31767754Smsmith    FunctionDumper::PointerType PT =
31867754Smsmith        Symbol.isReference() ? FunctionDumper::PointerType::Reference
31967754Smsmith                             : FunctionDumper::PointerType::Pointer;
32067754Smsmith    Dumper.start(*FS, nullptr, PT);
32167754Smsmith    return;
322129684Snjl  }
32367754Smsmith
32467754Smsmith  if (auto *UDT = dyn_cast<PDBSymbolTypeUDT>(P.get())) {
32567754Smsmith    printClassDecl(Printer, *UDT);
32667754Smsmith  } else if (P) {
32767754Smsmith    P->dump(*this);
32867754Smsmith  }
32967754Smsmith
33067754Smsmith  if (auto Parent = Symbol.getClassParent()) {
33167754Smsmith    auto UDT = llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Parent));
33267754Smsmith    if (UDT)
33367754Smsmith      Printer << " " << UDT->getName() << "::";
33467754Smsmith  }
33567754Smsmith
33677424Smsmith  if (Symbol.isReference())
33767754Smsmith    Printer << "&";
33867754Smsmith  else if (Symbol.isRValueReference())
33967754Smsmith    Printer << "&&";
34067754Smsmith  else
34199146Siwasaki    Printer << "*";
34291116Smsmith}
34367754Smsmith
34467754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {
34591116Smsmith  Printer.format("<vtshape ({0} methods)>", Symbol.getCount());
34667754Smsmith}
34767754Smsmith
34867754Smsmithvoid TypeDumper::dumpClassLayout(const ClassLayout &Class) {
34967754Smsmith  assert(opts::pretty::Classes);
35099146Siwasaki
35199146Siwasaki  if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
35267754Smsmith    WithColor(Printer, PDB_ColorItem::Keyword).get()
35367754Smsmith        << Class.getClass().getUdtKind() << " ";
35467754Smsmith    WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
35567754Smsmith  } else {
35667754Smsmith    ClassDefinitionDumper Dumper(Printer);
35791116Smsmith    Dumper.start(Class);
35891116Smsmith  }
35991116Smsmith}
36091116Smsmith