[PDB] Create a SymbolCache class.

Part of the responsibility of the native PDB reader is to cache
symbols the first time they are accessed, so they can then be
looked up by an ID.  Furthermore, we need to resolve type indices
to records that we vend to the user, and other things.  Previously
this code was all thrown together a bit haphazardly in the native
session class, but it makes sense to collect all of this into a
single class whose sole responsibility is to manage the collection
of known symbols.

llvm-svn: 341608
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index f6a529a..9bf97dd 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -62,6 +62,7 @@
   Native/PublicsStream.cpp
   Native/GSIStreamBuilder.cpp
   Native/RawError.cpp
+  Native/SymbolCache.cpp
   Native/SymbolStream.cpp
   Native/TpiHashing.cpp
   Native/TpiStream.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
index f545688..9dd66f3 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
@@ -24,12 +24,12 @@
     : Session(PDBSession), Index(Index) {}
 
 uint32_t NativeEnumModules::getChildCount() const {
-  return Session.getNativeGlobalScope().getNumCompilands();
+  return Session.getSymbolCache().getNumCompilands();
 }
 
 std::unique_ptr<PDBSymbol>
 NativeEnumModules::getChildAtIndex(uint32_t N) const {
-  return Session.getNativeGlobalScope().getOrCreateCompiland(N);
+  return Session.getSymbolCache().getOrCreateCompiland(N);
 }
 
 std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
index 5dbdff7..893afd4 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
@@ -12,6 +12,7 @@
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
 
 #include <cassert>
@@ -78,7 +79,8 @@
 }
 
 uint64_t NativeEnumSymbol::getLength() const {
-  const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType());
+  const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
+      Record.getUnderlyingType());
   const auto UnderlyingType =
       Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
   return UnderlyingType ? UnderlyingType->getLength() : 0;
@@ -104,5 +106,6 @@
 }
 
 uint32_t NativeEnumSymbol::getTypeId() const {
-  return Session.findSymbolByTypeIndex(Record.getUnderlyingType());
+  return Session.getSymbolCache().findSymbolByTypeIndex(
+      Record.getUnderlyingType());
 }
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
index 36a68a1..70a187b 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
@@ -41,7 +41,7 @@
 std::unique_ptr<PDBSymbol>
 NativeEnumTypes::getChildAtIndex(uint32_t Index) const {
   if (Index < Matches.size())
-    return Session.createEnumSymbol(Matches[Index]);
+    return Session.getSymbolCache().createEnumSymbol(Matches[Index]);
   return nullptr;
 }
 
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
index 3530570..59eaf3e 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -15,22 +15,24 @@
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
 
 using namespace llvm;
 using namespace llvm::pdb;
 
+static DbiStream *getDbiStreamPtr(NativeSession &Session) {
+  Expected<DbiStream &> DbiS = Session.getPDBFile().getPDBDbiStream();
+  if (DbiS)
+    return &DbiS.get();
+
+  consumeError(DbiS.takeError());
+  return nullptr;
+}
+
 NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId)
     : NativeRawSymbol(Session, PDB_SymType::Exe, SymbolId),
-      File(Session.getPDBFile()) {
-  Expected<DbiStream &> DbiS = File.getPDBDbiStream();
-  if (!DbiS) {
-    consumeError(DbiS.takeError());
-    return;
-  }
-  Dbi = &DbiS.get();
-  Compilands.resize(Dbi->modules().getModuleCount());
-}
+      Dbi(getDbiStreamPtr(Session)) {}
 
 std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const {
   return llvm::make_unique<NativeExeSymbol>(Session, SymbolId);
@@ -44,7 +46,7 @@
     break;
   }
   case PDB_SymType::Enum:
-    return Session.createTypeEnumerator(codeview::LF_ENUM);
+    return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM);
   default:
     break;
   }
@@ -52,7 +54,7 @@
 }
 
 uint32_t NativeExeSymbol::getAge() const {
-  auto IS = File.getPDBInfoStream();
+  auto IS = Session.getPDBFile().getPDBInfoStream();
   if (IS)
     return IS->getAge();
   consumeError(IS.takeError());
@@ -60,11 +62,11 @@
 }
 
 std::string NativeExeSymbol::getSymbolsFileName() const {
-  return File.getFilePath();
+  return Session.getPDBFile().getFilePath();
 }
 
 codeview::GUID NativeExeSymbol::getGuid() const {
-  auto IS = File.getPDBInfoStream();
+  auto IS = Session.getPDBFile().getPDBInfoStream();
   if (IS)
     return IS->getGuid();
   consumeError(IS.takeError());
@@ -72,7 +74,7 @@
 }
 
 bool NativeExeSymbol::hasCTypes() const {
-  auto Dbi = File.getPDBDbiStream();
+  auto Dbi = Session.getPDBFile().getPDBDbiStream();
   if (Dbi)
     return Dbi->hasCTypes();
   consumeError(Dbi.takeError());
@@ -80,33 +82,9 @@
 }
 
 bool NativeExeSymbol::hasPrivateSymbols() const {
-  auto Dbi = File.getPDBDbiStream();
+  auto Dbi = Session.getPDBFile().getPDBDbiStream();
   if (Dbi)
     return !Dbi->isStripped();
   consumeError(Dbi.takeError());
   return false;
 }
-
-uint32_t NativeExeSymbol::getNumCompilands() const {
-  if (!Dbi)
-    return 0;
-
-  return Dbi->modules().getModuleCount();
-}
-
-std::unique_ptr<PDBSymbolCompiland>
-NativeExeSymbol::getOrCreateCompiland(uint32_t Index) {
-  if (!Dbi)
-    return nullptr;
-
-  if (Index >= Compilands.size())
-    return nullptr;
-
-  if (Compilands[Index] == 0) {
-    const DbiModuleList &Modules = Dbi->modules();
-    Compilands[Index] = Session.createSymbol<NativeCompilandSymbol>(
-        Modules.getModuleDescriptor(Index));
-  }
-
-  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
-}
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index f3de408..1601b35 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -20,6 +20,7 @@
 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
@@ -39,34 +40,19 @@
 using namespace llvm::msf;
 using namespace llvm::pdb;
 
-namespace {
-// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
-// to instantiate a NativeBuiltinSymbol for that type.
-static const struct BuiltinTypeEntry {
-  codeview::SimpleTypeKind Kind;
-  PDB_BuiltinType Type;
-  uint32_t Size;
-} BuiltinTypes[] = {
-    {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
-    {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
-    {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
-    {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
-    {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
-    {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
-    {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
-    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
-    {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
-    // This table can be grown as necessary, but these are the only types we've
-    // needed so far.
-};
-} // namespace
+static DbiStream *getDbiStreamPtr(PDBFile &File) {
+  Expected<DbiStream &> DbiS = File.getPDBDbiStream();
+  if (DbiS)
+    return &DbiS.get();
+
+  consumeError(DbiS.takeError());
+  return nullptr;
+}
 
 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
                              std::unique_ptr<BumpPtrAllocator> Allocator)
-    : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {
-  // Id 0 is reserved for the invalid symbol.
-  SymbolCache.push_back(nullptr);
-}
+    : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
+      Cache(*this, getDbiStreamPtr(*Pdb)) {}
 
 NativeSession::~NativeSession() = default;
 
@@ -94,67 +80,6 @@
   return make_error<RawError>(raw_error_code::feature_unsupported);
 }
 
-std::unique_ptr<PDBSymbolTypeEnum>
-NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
-  const auto Id = findSymbolByTypeIndex(Index);
-  return PDBSymbol::createAs<PDBSymbolTypeEnum>(*this, *SymbolCache[Id]);
-}
-
-std::unique_ptr<IPDBEnumSymbols>
-NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
-  auto Tpi = Pdb->getPDBTpiStream();
-  if (!Tpi) {
-    consumeError(Tpi.takeError());
-    return nullptr;
-  }
-  auto &Types = Tpi->typeCollection();
-  return std::unique_ptr<IPDBEnumSymbols>(
-      new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
-}
-
-SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
-  // First see if it's already in our cache.
-  const auto Entry = TypeIndexToSymbolId.find(Index);
-  if (Entry != TypeIndexToSymbolId.end())
-    return Entry->second;
-
-  // Symbols for built-in types are created on the fly.
-  if (Index.isSimple()) {
-    // FIXME:  We will eventually need to handle pointers to other simple types,
-    // which are still simple types in the world of CodeView TypeIndexes.
-    if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
-      return 0;
-    const auto Kind = Index.getSimpleKind();
-    const auto It =
-        std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
-                     [Kind](const BuiltinTypeEntry &Builtin) {
-                       return Builtin.Kind == Kind;
-                     });
-    if (It == std::end(BuiltinTypes))
-      return 0;
-    SymIndexId Id = SymbolCache.size();
-    SymbolCache.emplace_back(
-        llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size));
-    TypeIndexToSymbolId[Index] = Id;
-    return Id;
-  }
-
-  // We need to instantiate and cache the desired type symbol.
-  auto Tpi = Pdb->getPDBTpiStream();
-  if (!Tpi) {
-    consumeError(Tpi.takeError());
-    return 0;
-  }
-  auto &Types = Tpi->typeCollection();
-  const auto &I = Types.getType(Index);
-  const auto Id = static_cast<SymIndexId>(SymbolCache.size());
-  // TODO(amccarth):  Make this handle all types, not just LF_ENUMs.
-  assert(I.kind() == codeview::LF_ENUM);
-  SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
-  TypeIndexToSymbolId[Index] = Id;
-  return Id;
-}
-
 uint64_t NativeSession::getLoadAddress() const { return 0; }
 
 bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
@@ -165,10 +90,7 @@
 
 std::unique_ptr<PDBSymbol>
 NativeSession::getSymbolById(uint32_t SymbolId) const {
-  // If the caller has a SymbolId, it'd better be in our SymbolCache.
-  return SymbolId < SymbolCache.size()
-             ? PDBSymbol::create(*this, *SymbolCache[SymbolId])
-             : nullptr;
+  return Cache.getSymbolById(SymbolId);
 }
 
 bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
@@ -278,10 +200,13 @@
   return nullptr;
 }
 
-NativeExeSymbol &NativeSession::getNativeGlobalScope() {
-  if (ExeSymbol == 0) {
-    ExeSymbol = static_cast<SymIndexId>(SymbolCache.size());
-    SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, ExeSymbol));
-  }
-  return static_cast<NativeExeSymbol &>(*SymbolCache[ExeSymbol]);
+void NativeSession::initializeExeSymbol() {
+  if (ExeSymbol == 0)
+    ExeSymbol = Cache.createSymbol<NativeExeSymbol>();
+}
+
+NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
+  const_cast<NativeSession &>(*this).initializeExeSymbol();
+
+  return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
 }
diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
new file mode 100644
index 0000000..9f8e020
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -0,0 +1,147 @@
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
+// to instantiate a NativeBuiltinSymbol for that type.
+static const struct BuiltinTypeEntry {
+  codeview::SimpleTypeKind Kind;
+  PDB_BuiltinType Type;
+  uint32_t Size;
+} BuiltinTypes[] = {
+    {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
+    {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
+    {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
+    {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
+    {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
+    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
+    {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
+    // This table can be grown as necessary, but these are the only types we've
+    // needed so far.
+};
+
+SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
+    : Session(Session), Dbi(Dbi) {
+  // Id 0 is reserved for the invalid symbol.
+  Cache.push_back(nullptr);
+
+  if (Dbi)
+    Compilands.resize(Dbi->modules().getModuleCount());
+}
+
+std::unique_ptr<PDBSymbolTypeEnum>
+SymbolCache::createEnumSymbol(codeview::TypeIndex Index) {
+  const auto Id = findSymbolByTypeIndex(Index);
+  return PDBSymbol::createAs<PDBSymbolTypeEnum>(Session, *Cache[Id]);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
+  auto Tpi = Session.getPDBFile().getPDBTpiStream();
+  if (!Tpi) {
+    consumeError(Tpi.takeError());
+    return nullptr;
+  }
+  auto &Types = Tpi->typeCollection();
+  return std::unique_ptr<IPDBEnumSymbols>(
+      new NativeEnumTypes(Session, Types, codeview::LF_ENUM));
+}
+
+SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
+  // First see if it's already in our cache.
+  const auto Entry = TypeIndexToSymbolId.find(Index);
+  if (Entry != TypeIndexToSymbolId.end())
+    return Entry->second;
+
+  // Symbols for built-in types are created on the fly.
+  if (Index.isSimple()) {
+    // FIXME:  We will eventually need to handle pointers to other simple types,
+    // which are still simple types in the world of CodeView TypeIndexes.
+    if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
+      return 0;
+    const auto Kind = Index.getSimpleKind();
+    const auto It =
+        std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
+                     [Kind](const BuiltinTypeEntry &Builtin) {
+                       return Builtin.Kind == Kind;
+                     });
+    if (It == std::end(BuiltinTypes))
+      return 0;
+    SymIndexId Id = Cache.size();
+    Cache.emplace_back(llvm::make_unique<NativeBuiltinSymbol>(
+        Session, Id, It->Type, It->Size));
+    TypeIndexToSymbolId[Index] = Id;
+    return Id;
+  }
+
+  // We need to instantiate and cache the desired type symbol.
+  auto Tpi = Session.getPDBFile().getPDBTpiStream();
+  if (!Tpi) {
+    consumeError(Tpi.takeError());
+    return 0;
+  }
+  codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
+  const codeview::CVType &CVT = Types.getType(Index);
+  // TODO(amccarth):  Make this handle all types, not just LF_ENUMs.
+  SymIndexId Id = 0;
+  switch (CVT.kind()) {
+  case codeview::LF_ENUM:
+    Id = createSymbol<NativeEnumSymbol>(CVT);
+    break;
+  default:
+    assert(false && "Unsupported native symbol type!");
+    return 0;
+  }
+  TypeIndexToSymbolId[Index] = Id;
+  return Id;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+  // If the caller has a SymbolId, it'd better be in our SymbolCache.
+  return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId])
+                                 : nullptr;
+}
+
+NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
+  return *Cache[SymbolId];
+}
+
+uint32_t SymbolCache::getNumCompilands() const {
+  if (!Dbi)
+    return 0;
+
+  return Dbi->modules().getModuleCount();
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+SymbolCache::getOrCreateCompiland(uint32_t Index) {
+  if (!Dbi)
+    return nullptr;
+
+  if (Index >= Compilands.size())
+    return nullptr;
+
+  if (Compilands[Index] == 0) {
+    const DbiModuleList &Modules = Dbi->modules();
+    Compilands[Index] =
+        createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
+  }
+
+  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
+}