[llvm-pdbdump] Rewrite dumper using visitor pattern.

This increases the flexibility of how to dump different
symbol types -- necessary for context-sensitive formatting of
symbol types -- and also improves the modularity by allowing
the dumping to be implemented in the actual dumper, as opposed
to in the PDB library.

llvm-svn: 230184
diff --git a/llvm/tools/llvm-pdbdump/FunctionDumper.cpp b/llvm/tools/llvm-pdbdump/FunctionDumper.cpp
new file mode 100644
index 0000000..851fa1f
--- /dev/null
+++ b/llvm/tools/llvm-pdbdump/FunctionDumper.cpp
@@ -0,0 +1,187 @@
+//===- FunctionDumper.cpp ------------------------------------ *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FunctionDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+namespace {
+template <class T>
+void dumpClassParentWithScopeOperator(const T &Symbol, llvm::raw_ostream &OS,
+                                      llvm::FunctionDumper &Dumper) {
+  uint32_t ClassParentId = Symbol.getClassParentId();
+  auto ClassParent =
+      Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+          ClassParentId);
+  if (!ClassParent)
+    return;
+
+  OS << ClassParent->getName() << "::";
+}
+}
+
+using namespace llvm;
+
+FunctionDumper::FunctionDumper() : PDBSymDumper(true) {}
+
+void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
+                           PointerType Pointer, raw_ostream &OS) {
+  auto ReturnType = Symbol.getReturnType();
+  ReturnType->dump(OS, 0, *this);
+  OS << " ";
+  uint32_t ClassParentId = Symbol.getClassParentId();
+  auto ClassParent =
+      Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+          ClassParentId);
+
+  if (Pointer == PointerType::None) {
+    OS << Symbol.getCallingConvention() << " ";
+    if (ClassParent)
+      OS << "(" << ClassParent->getName() << "::)";
+  } else {
+    OS << "(" << Symbol.getCallingConvention() << " ";
+    if (ClassParent)
+      OS << ClassParent->getName() << "::";
+    if (Pointer == PointerType::Reference)
+      OS << "&";
+    else
+      OS << "*";
+    OS << ")";
+  }
+
+  OS << "(";
+  if (auto ChildEnum = Symbol.getArguments()) {
+    uint32_t Index = 0;
+    while (auto Arg = ChildEnum->getNext()) {
+      Arg->dump(OS, 0, *this);
+      if (++Index < ChildEnum->getChildCount())
+        OS << ", ";
+    }
+  }
+  OS << ")";
+
+  if (Symbol.isConstType())
+    OS << " const";
+  if (Symbol.isVolatileType())
+    OS << " volatile";
+}
+
+void FunctionDumper::start(const PDBSymbolFunc &Symbol, raw_ostream &OS) {
+  if (Symbol.isVirtual() || Symbol.isPureVirtual())
+    OS << "virtual ";
+
+  auto Signature = Symbol.getSignature();
+  if (!Signature) {
+    OS << Symbol.getName();
+    return;
+  }
+
+  auto ReturnType = Signature->getReturnType();
+  ReturnType->dump(OS, 0, *this);
+
+  OS << " " << Signature->getCallingConvention() << " ";
+  OS << Symbol.getName();
+
+  OS << "(";
+  if (auto ChildEnum = Signature->getArguments()) {
+    uint32_t Index = 0;
+    while (auto Arg = ChildEnum->getNext()) {
+      Arg->dump(OS, 0, *this);
+      if (++Index < ChildEnum->getChildCount())
+        OS << ", ";
+    }
+  }
+  OS << ")";
+
+  if (Symbol.isConstType())
+    OS << " const";
+  if (Symbol.isVolatileType())
+    OS << " volatile";
+  if (Symbol.isPureVirtual())
+    OS << " = 0";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
+                          int Indent) {
+  uint32_t ElementTypeId = Symbol.getTypeId();
+  auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
+  if (!ElementType)
+    return;
+
+  ElementType->dump(OS, 0, *this);
+  OS << "[" << Symbol.getLength() << "]";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
+                          int Indent) {
+  PDB_BuiltinType Type = Symbol.getBuiltinType();
+  OS << Type;
+  if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
+    OS << (8 * Symbol.getLength()) << "_t";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
+                          int Indent) {
+  dumpClassParentWithScopeOperator(Symbol, OS, *this);
+  OS << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol,
+                          raw_ostream &OS, int Indent) {
+  // PDBSymbolTypeFunctionArg is just a shim over the real argument.  Just drill
+  // through to the
+  // real thing and dump it.
+  uint32_t TypeId = Symbol.getTypeId();
+  auto Type = Symbol.getSession().getSymbolById(TypeId);
+  if (!Type)
+    return;
+  Type->dump(OS, 0, *this);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
+                          int Indent) {
+  dumpClassParentWithScopeOperator(Symbol, OS, *this);
+  OS << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
+                          int Indent) {
+  uint32_t PointeeId = Symbol.getTypeId();
+  auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
+  if (!PointeeType)
+    return;
+
+  if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+    FunctionDumper NestedDumper;
+    PointerType Pointer =
+        Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
+    NestedDumper.start(*FuncSig, Pointer, OS);
+  } else {
+    if (Symbol.isConstType())
+      OS << "const ";
+    if (Symbol.isVolatileType())
+      OS << "volatile ";
+    PointeeType->dump(OS, Indent, *this);
+    OS << (Symbol.isReference() ? "&" : "*");
+  }
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
+                          int Indent) {
+  OS << Symbol.getName();
+}