//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PrettyTypeDumper.h"

#include "LinePrinter.h"
#include "PrettyBuiltinDumper.h"
#include "PrettyClassDefinitionDumper.h"
#include "PrettyEnumDumper.h"
#include "PrettyTypedefDumper.h"
#include "llvm-pdbutil.h"

#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/DebugInfo/PDB/UDTLayout.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/FormatVariadic.h"

using namespace llvm;
using namespace llvm::pdb;

using LayoutPtr = std::unique_ptr<ClassLayout>;

typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);

static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
  return S1->getName() < S2->getName();
}

static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
  return S1->getSize() < S2->getSize();
}

static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
  return S1->deepPaddingSize() < S2->deepPaddingSize();
}

static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {
  double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();
  double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();
  return Pct1 < Pct2;
}

static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {
  return S1->immediatePadding() < S2->immediatePadding();
}

static bool ComparePaddingPctImmediate(const LayoutPtr &S1,
                                       const LayoutPtr &S2) {
  double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();
  double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();
  return Pct1 < Pct2;
}

static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
  switch (Mode) {
  case opts::pretty::ClassSortMode::Name:
    return CompareNames;
  case opts::pretty::ClassSortMode::Size:
    return CompareSizes;
  case opts::pretty::ClassSortMode::Padding:
    return ComparePadding;
  case opts::pretty::ClassSortMode::PaddingPct:
    return ComparePaddingPct;
  case opts::pretty::ClassSortMode::PaddingImmediate:
    return ComparePaddingImmediate;
  case opts::pretty::ClassSortMode::PaddingPctImmediate:
    return ComparePaddingPctImmediate;
  default:
    return nullptr;
  }
}

template <typename Enumerator>
static std::vector<std::unique_ptr<ClassLayout>>
filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
                       uint32_t UnfilteredCount) {
  std::vector<std::unique_ptr<ClassLayout>> Filtered;

  Filtered.reserve(UnfilteredCount);
  CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);

  if (UnfilteredCount > 10000) {
    errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);
    errs().flush();
  }
  uint32_t Examined = 0;
  uint32_t Discarded = 0;
  while (auto Class = E.getNext()) {
    ++Examined;
    if (Examined % 10000 == 0) {
      errs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
                        Examined, UnfilteredCount, Discarded);
      errs().flush();
    }

    if (Class->getUnmodifiedTypeId() != 0) {
      ++Discarded;
      continue;
    }

    if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
      ++Discarded;
      continue;
    }

    auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
    if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
      ++Discarded;
      continue;
    }
    if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {
      ++Discarded;
      continue;
    }

    Filtered.push_back(std::move(Layout));
  }

  if (Comp)
    std::sort(Filtered.begin(), Filtered.end(), Comp);
  return Filtered;
}

TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}

void TypeDumper::start(const PDBSymbolExe &Exe) {
  auto Children = Exe.findAllChildren();
  if (opts::pretty::Enums) {
    if (auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>()) {
      Printer.NewLine();
      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
      Printer << ": (" << Enums->getChildCount() << " items)";
      Printer.Indent();
      while (auto Enum = Enums->getNext())
        Enum->dump(*this);
      Printer.Unindent();
    }
  }

  if (opts::pretty::Typedefs) {
    if (auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>()) {
      Printer.NewLine();
      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
      Printer << ": (" << Typedefs->getChildCount() << " items)";
      Printer.Indent();
      while (auto Typedef = Typedefs->getNext())
        Typedef->dump(*this);
      Printer.Unindent();
    }
  }

  if (opts::pretty::Classes) {
    if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
      uint32_t All = Classes->getChildCount();

      Printer.NewLine();
      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";

      bool Precompute = false;
      Precompute =
          (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);

      // If we're using no sort mode, then we can start getting immediate output
      // from the tool by just filtering as we go, rather than processing
      // everything up front so that we can sort it.  This makes the tool more
      // responsive.  So only precompute the filtered/sorted set of classes if
      // necessary due to the specified options.
      std::vector<LayoutPtr> Filtered;
      uint32_t Shown = All;
      if (Precompute) {
        Filtered = filterAndSortClassDefs(Printer, *Classes, All);

        Shown = Filtered.size();
      }

      Printer << ": (Showing " << Shown << " items";
      if (Shown < All)
        Printer << ", " << (All - Shown) << " filtered";
      Printer << ")";
      Printer.Indent();

      // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
      // the DIA enumerator and filter on the fly.
      if (Precompute) {
        for (auto &Class : Filtered)
          dumpClassLayout(*Class);
      } else {
        while (auto Class = Classes->getNext()) {
          if (Class->getUnmodifiedTypeId() != 0)
            continue;

          if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
            continue;

          auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
          if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
            continue;

          dumpClassLayout(*Layout);
        }
      }

      Printer.Unindent();
    }
  }
}

void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
  assert(opts::pretty::Enums);

  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
    return;
  // Dump member enums when dumping their class definition.
  if (nullptr != Symbol.getClassParent())
    return;

  Printer.NewLine();
  EnumDumper Dumper(Printer);
  Dumper.start(Symbol);
}

void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
  assert(opts::pretty::Typedefs);

  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
    return;

  Printer.NewLine();
  TypedefDumper Dumper(Printer);
  Dumper.start(Symbol);
}

void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
  assert(opts::pretty::Classes);

  if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
    Printer.NewLine();
    WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
    WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getName();
  } else {
    ClassDefinitionDumper Dumper(Printer);
    Dumper.start(Class);
  }
}
