Revert "[CodeView] Provide a common interface for type collections."

This is a squash of ~5 reverts of, well, pretty much everything
I did today.  Something is seriously broken with lit on Windows
right now, and as a result assertions that fire in tests are
triggering failures.  I've been breaking non-Windows bots all
day which has seriously confused me because all my tests have
been passing, and after running lit with -a to view the output
even on successful runs, I find out that the tool is crashing
and yet lit is still reporting it as a success!

At this point I don't even know where to start, so rather than
leave the tree broken for who knows how long, I will get this
back to green, and then once lit is fixed on Windows, hopefully
hopefully fix the remaining set of problems for real.

llvm-svn: 303409
diff --git a/llvm/tools/llvm-pdbdump/Analyze.cpp b/llvm/tools/llvm-pdbdump/Analyze.cpp
index 3a026e5..ab4477e 100644
--- a/llvm/tools/llvm-pdbdump/Analyze.cpp
+++ b/llvm/tools/llvm-pdbdump/Analyze.cpp
@@ -14,6 +14,7 @@
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
diff --git a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp
index 3b609ae..5ad0bfa 100644
--- a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp
+++ b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp
@@ -29,15 +29,15 @@
   return StringRef();
 }
 
-CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
                                                ScopedPrinter *W)
-    : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex),
+    : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
                              W) {}
 
-CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
                                                TypeIndex FirstTI,
                                                ScopedPrinter *W)
-    : W(W), TI(FirstTI), Offset(0), Types(Types) {}
+    : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
 
 Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
   return Error::success();
@@ -46,7 +46,7 @@
 Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
   uint32_t I = TI.getIndex();
   StringRef Leaf = getLeafName(Record.Type);
-  StringRef Name = Types.getTypeName(TI);
+  StringRef Name = TypeDB.getTypeName(TI);
   W->printString(
       llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
                     Record.length(), Offset, Leaf, Name)
diff --git a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h
index 41ccea0..76fafc9 100644
--- a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h
+++ b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h
@@ -17,7 +17,7 @@
 namespace llvm {
 class ScopedPrinter;
 namespace codeview {
-class TypeCollection;
+class TypeDatabase;
 }
 
 namespace pdb {
@@ -26,8 +26,8 @@
 /// Dumps records on a single line, and ignores member records.
 class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
 public:
-  CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W);
-  CompactTypeDumpVisitor(codeview::TypeCollection &Types,
+  CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
+  CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
                          codeview::TypeIndex FirstTI, ScopedPrinter *W);
 
   /// Paired begin/end actions for all types. Receives all record data,
@@ -40,7 +40,7 @@
 
   codeview::TypeIndex TI;
   uint32_t Offset;
-  codeview::TypeCollection &Types;
+  codeview::TypeDatabase &TypeDB;
 };
 
 } // end namespace pdb
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
index f75a241..c4fecb8 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -14,9 +14,9 @@
 #include "StreamUtil.h"
 #include "llvm-pdbdump.h"
 
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
-#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
@@ -25,6 +25,7 @@
 #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@@ -83,7 +84,7 @@
 
 class C13RawVisitor : public C13DebugFragmentVisitor {
 public:
-  C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI)
+  C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
       : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
 
   Error handleLines() override {
@@ -159,7 +160,7 @@
         if (auto EC = printFileName("FileName", L.Header->FileID))
           return EC;
 
-        if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
+        if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
           return EC;
         P.printNumber("SourceLine", L.Header->SourceLineNum);
         if (IL.hasExtraFiles()) {
@@ -175,11 +176,11 @@
   }
 
 private:
-  Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
-    CompactTypeDumpVisitor CTDV(IPI, Index, &P);
+  Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
+    CompactTypeDumpVisitor CTDV(DB, Index, &P);
     DictScope D(P, Label);
-    if (IPI.contains(Index)) {
-      CVType Type = IPI.getType(Index);
+    if (DB.contains(Index)) {
+      CVType &Type = DB.getTypeRecord(Index);
       if (auto EC = codeview::visitTypeRecord(Type, CTDV))
         return EC;
     } else {
@@ -198,7 +199,7 @@
   }
 
   ScopedPrinter &P;
-  LazyRandomTypeCollection &IPI;
+  TypeDatabase &IPI;
 };
 }
 
@@ -608,19 +609,14 @@
     VerLabel = "IPI Version";
   }
 
+  if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
+    return Error::success();
+
   auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
                                       : File.getPDBIpiStream();
   if (!Tpi)
     return Tpi.takeError();
 
-  auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
-  if (!ExpectedTypes)
-    return ExpectedTypes.takeError();
-  auto &Types = *ExpectedTypes;
-
-  if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
-    return Error::success();
-
   std::unique_ptr<DictScope> StreamScope;
   std::unique_ptr<ListScope> RecordScope;
 
@@ -628,19 +624,25 @@
   P.printNumber(VerLabel, Tpi->getTpiVersion());
   P.printNumber("Record count", Tpi->getNumTypeRecords());
 
+  Optional<TypeDatabase> &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB;
+
   std::vector<std::unique_ptr<TypeVisitorCallbacks>> Visitors;
 
+  if (!StreamDB.hasValue()) {
+    StreamDB.emplace(Tpi->getNumTypeRecords());
+    Visitors.push_back(make_unique<TypeDatabaseVisitor>(*StreamDB));
+  }
   // If we're in dump mode, add a dumper with the appropriate detail level.
   if (DumpRecords) {
     std::unique_ptr<TypeVisitorCallbacks> Dumper;
     if (opts::raw::CompactRecords)
-      Dumper = make_unique<CompactTypeDumpVisitor>(Types, &P);
+      Dumper = make_unique<CompactTypeDumpVisitor>(*StreamDB, &P);
     else {
-      assert(TpiTypes);
+      assert(TypeDB.hasValue());
 
-      auto X = make_unique<TypeDumpVisitor>(*TpiTypes, &P, false);
+      auto X = make_unique<TypeDumpVisitor>(*TypeDB, &P, false);
       if (StreamIdx == StreamIPI)
-        X->setIpiTypes(*IpiTypes);
+        X->setItemDB(*ItemDB);
       Dumper = std::move(X);
     }
     Visitors.push_back(std::move(Dumper));
@@ -658,17 +660,23 @@
   if (DumpRecords || DumpRecordBytes)
     RecordScope = llvm::make_unique<ListScope>(P, "Records");
 
-  Optional<TypeIndex> I = Types.getFirst();
-  do {
+  bool HadError = false;
+
+  TypeIndex T(TypeIndex::FirstNonSimpleIndex);
+  for (auto Type : Tpi->types(&HadError)) {
     std::unique_ptr<DictScope> OneRecordScope;
 
     if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
       OneRecordScope = llvm::make_unique<DictScope>(P, "");
 
-    auto T = Types.getType(*I);
-    if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
+    if (auto EC = codeview::visitTypeRecord(Type, Pipeline))
       return EC;
-  } while ((I = Types.getNext(*I)));
+
+    ++T;
+  }
+  if (HadError)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "TPI stream contained corrupt record");
 
   if (DumpTpiHash) {
     DictScope DD(P, "Hash");
@@ -703,26 +711,35 @@
   return Error::success();
 }
 
-Expected<codeview::LazyRandomTypeCollection &>
-LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
-  auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
+Error LLVMOutputStyle::buildTypeDatabase(uint32_t SN) {
+  assert(SN == StreamIPI || SN == StreamTPI);
+
+  auto &DB = (SN == StreamIPI) ? ItemDB : TypeDB;
+
+  if (DB.hasValue())
+    return Error::success();
+
   auto Tpi =
       (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
+
   if (!Tpi)
     return Tpi.takeError();
 
-  if (!TypeCollection) {
-    // Initialize the type collection, even if we're not going to dump it.  This
-    // way if some other part of the dumper decides it wants to use some or all
-    // of the records for whatever purposes, it can still access them lazily.
-    auto &Types = Tpi->typeArray();
-    uint32_t Count = Tpi->getNumTypeRecords();
-    auto Offsets = Tpi->getTypeIndexOffsets();
-    TypeCollection =
-        llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
-  }
+  DB.emplace(Tpi->getNumTypeRecords());
 
-  return *TypeCollection;
+  TypeDatabaseVisitor DBV(*DB);
+
+  auto HashValues = Tpi->getHashValues();
+  if (HashValues.empty())
+    return codeview::visitTypeStream(Tpi->typeArray(), DBV);
+
+  TypeVisitorCallbackPipeline Pipeline;
+  Pipeline.addCallbackToPipeline(DBV);
+
+  TpiHashVerifier HashVerifier(HashValues, Tpi->getNumHashBuckets());
+  Pipeline.addCallbackToPipeline(HashVerifier);
+
+  return codeview::visitTypeStream(Tpi->typeArray(), Pipeline);
 }
 
 Error LLVMOutputStyle::dumpDbiStream() {
@@ -797,13 +814,11 @@
           return EC;
 
         if (ShouldDumpSymbols) {
-          auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
-          if (!ExpectedTypes)
-            return ExpectedTypes.takeError();
-          auto &Types = *ExpectedTypes;
+          if (auto EC = buildTypeDatabase(StreamTPI))
+            return EC;
 
           ListScope SS(P, "Symbols");
-          codeview::CVSymbolDumper SD(P, Types, nullptr, false);
+          codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
           bool HadError = false;
           for (auto S : ModS.symbols(&HadError)) {
             DictScope LL(P, "");
@@ -824,11 +839,10 @@
         }
         if (opts::raw::DumpLineInfo) {
           ListScope SS(P, "LineInfo");
-          auto ExpectedTypes = initializeTypeDatabase(StreamIPI);
-          if (!ExpectedTypes)
-            return ExpectedTypes.takeError();
-          auto &IpiItems = *ExpectedTypes;
-          C13RawVisitor V(P, File, IpiItems);
+          if (auto EC = buildTypeDatabase(StreamIPI))
+            return EC;
+
+          C13RawVisitor V(P, File, *ItemDB);
           if (auto EC = codeview::visitModuleDebugFragments(
                   ModS.linesAndChecksums(), V))
             return EC;
@@ -946,12 +960,10 @@
   P.printList("Section Offsets", Publics->getSectionOffsets(),
               printSectionOffset);
   ListScope L(P, "Symbols");
-  auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
-  if (!ExpectedTypes)
-    return ExpectedTypes.takeError();
-  auto &Tpi = *ExpectedTypes;
+  if (auto EC = buildTypeDatabase(StreamTPI))
+    return EC;
 
-  codeview::CVSymbolDumper SD(P, Tpi, nullptr, false);
+  codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false);
   bool HadError = false;
   for (auto S : Publics->getSymbols(&HadError)) {
     DictScope DD(P, "");
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
index 184dc4e..b0e7e34 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
@@ -21,11 +21,6 @@
 
 namespace llvm {
 class BitVector;
-
-namespace codeview {
-class LazyRandomTypeCollection;
-}
-
 namespace pdb {
 class LLVMOutputStyle : public OutputStyle {
 public:
@@ -34,8 +29,7 @@
   Error dump() override;
 
 private:
-  Expected<codeview::LazyRandomTypeCollection &>
-  initializeTypeDatabase(uint32_t SN);
+  Error buildTypeDatabase(uint32_t SN);
 
   Error dumpFileHeaders();
   Error dumpStreamSummary();
@@ -60,8 +54,8 @@
 
   PDBFile &File;
   ScopedPrinter P;
-  std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
-  std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
+  Optional<codeview::TypeDatabase> TypeDB;
+  Optional<codeview::TypeDatabase> ItemDB;
   SmallVector<std::string, 32> StreamPurposes;
 };
 }
diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
index dd32eca..6527bec 100644
--- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp
+++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
@@ -19,6 +19,7 @@
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@@ -370,6 +371,7 @@
 void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
     mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
             pdb::yaml::SerializationContext &Context) {
+
   if (IO.outputting()) {
     // For PDB to Yaml, deserialize into a high level record type, then dump it.
     consumeError(codeview::visitTypeRecord(Obj.Record, Context.Dumper));
diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
index 068312a..517c7d8 100644
--- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
+++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
@@ -13,6 +13,7 @@
 #include "OutputStyle.h"
 #include "PdbYaml.h"
 
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/YAMLTraits.h"
 
diff --git a/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp b/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp
index beb7007..3e447ca 100644
--- a/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp
+++ b/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 1767c3c..49a0dae 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -31,7 +31,6 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/config.h"
-#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
@@ -886,7 +885,7 @@
         DestIpi.addTypeRecord(Data, None);
       });
 
-  SmallString<64> OutFile(opts::merge::PdbOutputFile);
+  SmallString<64> OutFile = opts::merge::PdbOutputFile;
   if (OutFile.empty()) {
     OutFile = opts::merge::InputFilenames[0];
     llvm::sys::path::replace_extension(OutFile, "merged.pdb");
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 78bfa55..8e71c85 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -22,9 +22,8 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
@@ -35,13 +34,11 @@
 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/BinaryStreamReader.h"
@@ -73,7 +70,7 @@
 public:
   friend class COFFObjectDumpDelegate;
   COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
-      : ObjDumper(Writer), Obj(Obj), Writer(Writer), Types(100) {}
+      : ObjDumper(Writer), Obj(Obj), Writer(Writer), TypeDB(100) {}
 
   void printFileHeaders() override;
   void printSections() override;
@@ -109,7 +106,7 @@
   void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
   void printTypeIndex(StringRef FieldName, TypeIndex TI) {
     // Forward to CVTypeDumper for simplicity.
-    codeview::printTypeIndex(Writer, FieldName, TI, Types);
+    CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB);
   }
 
   void printCodeViewSymbolsSubsection(StringRef Subsection,
@@ -162,8 +159,7 @@
   StringTableRef CVStringTable;
 
   ScopedPrinter &Writer;
-  BinaryByteStream TypeContents;
-  LazyRandomTypeCollection Types;
+  TypeDatabase TypeDB;
 };
 
 class COFFObjectDumpDelegate : public SymbolDumpDelegate {
@@ -979,7 +975,9 @@
                                Subsection.bytes_end());
   auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
                                                         SectionContents);
-  CVSymbolDumper CVSD(W, Types, std::move(CODD), opts::CodeViewSubsectionBytes);
+
+  CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
+                      opts::CodeViewSubsectionBytes);
   CVSymbolArray Symbols;
   BinaryStreamReader Reader(BinaryData, llvm::support::little);
   if (auto EC = Reader.readArray(Symbols, Reader.getLength())) {
@@ -1096,11 +1094,12 @@
   if (Magic != COFF::DEBUG_SECTION_MAGIC)
     return error(object_error::parse_failed);
 
-  Types.reset(Data);
-
-  TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
-  error(codeview::visitTypeStream(Types, TDV));
-  W.flush();
+  CVTypeDumper CVTD(TypeDB);
+  TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes);
+  if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) {
+    W.flush();
+    error(llvm::errorToErrorCode(std::move(EC)));
+  }
 }
 
 void COFFDumper::printSections() {
@@ -1640,22 +1639,35 @@
     TypeBuf.append(Record.begin(), Record.end());
   });
 
-  TypeTableCollection TpiTypes(CVTypes.records());
+  TypeDatabase TypeDB(CVTypes.records().size());
   {
     ListScope S(Writer, "MergedTypeStream");
-    TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
-    error(codeview::visitTypeStream(TpiTypes, TDV));
-    Writer.flush();
+    CVTypeDumper CVTD(TypeDB);
+    TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
+    if (auto EC = CVTD.dump(
+            {TypeBuf.str().bytes_begin(), TypeBuf.str().bytes_end()}, TDV)) {
+      Writer.flush();
+      error(std::move(EC));
+    }
   }
 
   // Flatten the id stream and print it next. The ID stream refers to names from
   // the type stream.
-  TypeTableCollection IpiTypes(IDTable.records());
+  SmallString<0> IDBuf;
+  IDTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
+    IDBuf.append(Record.begin(), Record.end());
+  });
+
   {
     ListScope S(Writer, "MergedIDStream");
-    TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);
-    TDV.setIpiTypes(IpiTypes);
-    error(codeview::visitTypeStream(IpiTypes, TDV));
-    Writer.flush();
+    TypeDatabase IDDB(IDTable.records().size());
+    CVTypeDumper CVTD(IDDB);
+    TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
+    TDV.setItemDB(IDDB);
+    if (auto EC = CVTD.dump(
+            {IDBuf.str().bytes_begin(), IDBuf.str().bytes_end()}, TDV)) {
+      Writer.flush();
+      error(std::move(EC));
+    }
   }
 }