From c46e6a5940c50058e00c0c5f9123fd82e338d29a Mon Sep 17 00:00:00 2001
From: Dimitry Andric <dim@FreeBSD.org>
Date: Mon, 8 May 2017 17:12:57 +0000
Subject: Vendor import of llvm trunk r302418:
 https://llvm.org/svn/llvm-project/llvm/trunk@302418

---
 include/llvm/DebugInfo/CodeView/TypeDatabase.h     |   2 +-
 include/llvm/DebugInfo/DWARF/DWARFContext.h        |   5 +
 include/llvm/DebugInfo/DWARF/DWARFFormValue.h      | 331 ++++++++++-----------
 .../DebugInfo/PDB/Native/DbiModuleDescriptor.h     |   8 -
 include/llvm/DebugInfo/PDB/Native/DbiModuleList.h  | 114 +++++++
 include/llvm/DebugInfo/PDB/Native/DbiStream.h      |  13 +-
 .../DebugInfo/PDB/Native/NativeCompilandSymbol.h   |   4 +-
 .../llvm/DebugInfo/PDB/Native/NativeEnumModules.h  |   8 +-
 include/llvm/DebugInfo/PDB/Native/RawTypes.h       |  11 +-
 include/llvm/DebugInfo/PDB/Native/TpiStream.h      |   6 +-
 10 files changed, 301 insertions(+), 201 deletions(-)
 create mode 100644 include/llvm/DebugInfo/PDB/Native/DbiModuleList.h

(limited to 'include/llvm/DebugInfo')

diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
index 220de4bf0ee4..be7b19e7df0c 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDatabase.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
@@ -21,7 +21,7 @@ namespace llvm {
 namespace codeview {
 class TypeDatabase {
 public:
-  TypeDatabase() : TypeNameStorage(Allocator) {}
+  explicit TypeDatabase(uint32_t ExpectedSize);
 
   /// Gets the type index for the next type record.
   TypeIndex getNextTypeIndex() const;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index b9f3425d5deb..3fae8b441439 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -310,6 +310,11 @@ class DWARFContextInMemory : public DWARFContext {
 
   StringRef *MapSectionToMember(StringRef Name);
 
+  /// If Sec is compressed section, decompresses and updates its contents
+  /// provided by Data. Otherwise leaves it unchanged.
+  Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
+                        StringRef &Data);
+
 public:
   DWARFContextInMemory(const object::ObjectFile &Obj,
     const LoadedObjectInfo *L = nullptr);
diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 36b27228f5c6..f3516ebdecba 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -39,20 +39,18 @@ public:
 
 private:
   struct ValueType {
-    ValueType() {
-      uval = 0;
-    }
+    ValueType() { uval = 0; }
 
     union {
       uint64_t uval;
       int64_t sval;
-      const char* cstr;
+      const char *cstr;
     };
-    const uint8_t* data = nullptr;
+    const uint8_t *data = nullptr;
   };
 
-  dwarf::Form Form; // Form for this value.
-  ValueType Value; // Contains all data for the form.
+  dwarf::Form Form;             // Form for this value.
+  ValueType Value;              // Contains all data for the form.
   const DWARFUnit *U = nullptr; // Remember the DWARFUnit at extract time.
 
 public:
@@ -84,7 +82,7 @@ public:
                     const DWARFUnit *U);
 
   bool isInlinedCStr() const {
-    return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr;
+    return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;
   }
 
   /// getAsFoo functions below return the extracted value as Foo if only
@@ -135,45 +133,45 @@ public:
                                             uint8_t AddrSize,
                                             llvm::dwarf::DwarfFormat Format);
 
-  /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
+  /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
   ///
   /// Skips the bytes for this form in the debug info and updates the offset.
   ///
-  /// \param debug_info_data the .debug_info data to use to skip the value.
-  /// \param offset_ptr a reference to the offset that will be updated.
+  /// \param DebugInfoData the .debug_info data to use to skip the value.
+  /// \param OffsetPtr a reference to the offset that will be updated.
   /// \param U the DWARFUnit to use when skipping the form in case the form
   /// size differs according to data in the DWARFUnit.
   /// \returns true on success, false if the form was not skipped.
-  bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
+  bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
                  const DWARFUnit *U) const;
 
-  /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
+  /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
   ///
   /// Skips the bytes for this form in the debug info and updates the offset.
   ///
-  /// \param form the DW_FORM enumeration that indicates the form to skip.
-  /// \param debug_info_data the .debug_info data to use to skip the value.
-  /// \param offset_ptr a reference to the offset that will be updated.
+  /// \param Form the DW_FORM enumeration that indicates the form to skip.
+  /// \param DebugInfoData the .debug_info data to use to skip the value.
+  /// \param OffsetPtr a reference to the offset that will be updated.
   /// \param U the DWARFUnit to use when skipping the form in case the form
   /// size differs according to data in the DWARFUnit.
   /// \returns true on success, false if the form was not skipped.
-  static bool skipValue(dwarf::Form form, DataExtractor debug_info_data,
-                        uint32_t *offset_ptr, const DWARFUnit *U);
+  static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
+                        uint32_t *OffsetPtr, const DWARFUnit *U);
 
-  /// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
+  /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
   ///
   /// Skips the bytes for this form in the debug info and updates the offset.
   ///
-  /// \param form the DW_FORM enumeration that indicates the form to skip.
-  /// \param debug_info_data the .debug_info data to use to skip the value.
-  /// \param offset_ptr a reference to the offset that will be updated.
+  /// \param Form the DW_FORM enumeration that indicates the form to skip.
+  /// \param DebugInfoData the .debug_info data to use to skip the value.
+  /// \param OffsetPtr a reference to the offset that will be updated.
   /// \param Version DWARF version number.
   /// \param AddrSize size of an address in bytes.
   /// \param Format enum value from llvm::dwarf::DwarfFormat.
   /// \returns true on success, false if the form was not skipped.
-  static bool skipValue(dwarf::Form form, DataExtractor debug_info_data,
-                        uint32_t *offset_ptr, uint16_t Version,
-                        uint8_t AddrSize, llvm::dwarf::DwarfFormat Format);
+  static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
+                        uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize,
+                        llvm::dwarf::DwarfFormat Format);
 
 private:
   void dumpString(raw_ostream &OS) const;
@@ -181,149 +179,146 @@ private:
 
 namespace dwarf {
 
-  /// Take an optional DWARFFormValue and try to extract a string value from it.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and was a string.
-  inline Optional<const char*> toString(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsCString();
-    return None;
-  }
-  
-  /// Take an optional DWARFFormValue and extract a string value from it.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the string value or Default if the V doesn't have a value or the
-  /// form value's encoding wasn't a string.
-  inline const char*
-  toString(const Optional<DWARFFormValue>& V, const char *Default) {
-    return toString(V).getValueOr(Default);
-  }
-
-  /// Take an optional DWARFFormValue and try to extract an unsigned constant.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a unsigned constant form.
-  inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsUnsignedConstant();
-    return None;
-  }
-  
-  /// Take an optional DWARFFormValue and extract a unsigned constant.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the extracted unsigned value or Default if the V doesn't have a
-  /// value or the form value's encoding wasn't an unsigned constant form.
-  inline uint64_t
-  toUnsigned(const Optional<DWARFFormValue>& V, uint64_t Default) {
-    return toUnsigned(V).getValueOr(Default);
-  }
-  
-  /// Take an optional DWARFFormValue and try to extract an reference.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a reference form.
-  inline Optional<uint64_t> toReference(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsReference();
-    return None;
-  }
-  
-  /// Take an optional DWARFFormValue and extract a reference.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the extracted reference value or Default if the V doesn't have a
-  /// value or the form value's encoding wasn't a reference form.
-  inline uint64_t
-  toReference(const Optional<DWARFFormValue>& V, uint64_t Default) {
-    return toReference(V).getValueOr(Default);
-  }
-  
-  /// Take an optional DWARFFormValue and try to extract an signed constant.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a signed constant form.
-  inline Optional<int64_t> toSigned(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsSignedConstant();
-    return None;
-  }
-
-  /// Take an optional DWARFFormValue and extract a signed integer.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the extracted signed integer value or Default if the V doesn't
-  /// have a value or the form value's encoding wasn't a signed integer form.
-  inline int64_t
-  toSigned(const Optional<DWARFFormValue>& V, int64_t Default) {
-    return toSigned(V).getValueOr(Default);
-  }
-
-  /// Take an optional DWARFFormValue and try to extract an address.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a address form.
-  inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsAddress();
-    return None;
-  }
-
-  /// Take an optional DWARFFormValue and extract a address.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the extracted address value or Default if the V doesn't have a
-  /// value or the form value's encoding wasn't an address form.
-  inline uint64_t
-  toAddress(const Optional<DWARFFormValue>& V, uint64_t Default) {
-    return toAddress(V).getValueOr(Default);
-  }
-
-  /// Take an optional DWARFFormValue and try to extract an section offset.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a section offset form.
-  inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsSectionOffset();
-    return None;
-  }
-
-  /// Take an optional DWARFFormValue and extract a section offset.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \param Default the default value to return in case of failure.
-  /// \returns the extracted section offset value or Default if the V doesn't
-  /// have a value or the form value's encoding wasn't a section offset form.
-  inline uint64_t
-  toSectionOffset(const Optional<DWARFFormValue>& V, uint64_t Default) {
-    return toSectionOffset(V).getValueOr(Default);
-  }
-
-  /// Take an optional DWARFFormValue and try to extract block data.
-  ///
-  /// \param V and optional DWARFFormValue to attempt to extract the value from.
-  /// \returns an optional value that contains a value if the form value
-  /// was valid and has a block form.
-  inline Optional<ArrayRef<uint8_t>>
-  toBlock(const Optional<DWARFFormValue>& V) {
-    if (V)
-      return V->getAsBlock();
-    return None;
-  }
+/// Take an optional DWARFFormValue and try to extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and was a string.
+inline Optional<const char *> toString(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsCString();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the string value or Default if the V doesn't have a value or the
+/// form value's encoding wasn't a string.
+inline const char *toString(const Optional<DWARFFormValue> &V,
+                            const char *Default) {
+  return toString(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an unsigned constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a unsigned constant form.
+inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsUnsignedConstant();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a unsigned constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted unsigned value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't an unsigned constant form.
+inline uint64_t toUnsigned(const Optional<DWARFFormValue> &V,
+                           uint64_t Default) {
+  return toUnsigned(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an reference.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a reference form.
+inline Optional<uint64_t> toReference(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsReference();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a reference.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted reference value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't a reference form.
+inline uint64_t toReference(const Optional<DWARFFormValue> &V,
+                            uint64_t Default) {
+  return toReference(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an signed constant.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a signed constant form.
+inline Optional<int64_t> toSigned(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsSignedConstant();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a signed integer.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted signed integer value or Default if the V doesn't
+/// have a value or the form value's encoding wasn't a signed integer form.
+inline int64_t toSigned(const Optional<DWARFFormValue> &V, int64_t Default) {
+  return toSigned(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an address.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a address form.
+inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsAddress();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a address.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted address value or Default if the V doesn't have a
+/// value or the form value's encoding wasn't an address form.
+inline uint64_t toAddress(const Optional<DWARFFormValue> &V, uint64_t Default) {
+  return toAddress(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract an section offset.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a section offset form.
+inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsSectionOffset();
+  return None;
+}
+
+/// Take an optional DWARFFormValue and extract a section offset.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \param Default the default value to return in case of failure.
+/// \returns the extracted section offset value or Default if the V doesn't
+/// have a value or the form value's encoding wasn't a section offset form.
+inline uint64_t toSectionOffset(const Optional<DWARFFormValue> &V,
+                                uint64_t Default) {
+  return toSectionOffset(V).getValueOr(Default);
+}
+
+/// Take an optional DWARFFormValue and try to extract block data.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and has a block form.
+inline Optional<ArrayRef<uint8_t>> toBlock(const Optional<DWARFFormValue> &V) {
+  if (V)
+    return V->getAsBlock();
+  return None;
+}
 
 } // end namespace dwarf
 
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
index d1f791b9daed..7e77f5a3eef9 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
@@ -53,14 +53,6 @@ private:
   const ModuleInfoHeader *Layout = nullptr;
 };
 
-struct ModuleInfoEx {
-  ModuleInfoEx(const DbiModuleDescriptor &Info) : Info(Info) {}
-  ModuleInfoEx(const ModuleInfoEx &Ex) = default;
-
-  DbiModuleDescriptor Info;
-  std::vector<StringRef> SourceFiles;
-};
-
 } // end namespace pdb
 
 template <> struct VarStreamArrayExtractor<pdb::DbiModuleDescriptor> {
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
new file mode 100644
index 000000000000..bcf1cff8f6e5
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
@@ -0,0 +1,114 @@
+//===- DbiModuleList.h - PDB module information list ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
+#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class DbiModuleList;
+struct FileInfoSubstreamHeader;
+
+class DbiModuleSourceFilesIterator
+    : public iterator_facade_base<DbiModuleSourceFilesIterator,
+                                  std::random_access_iterator_tag, StringRef> {
+  typedef iterator_facade_base<DbiModuleSourceFilesIterator,
+                               std::random_access_iterator_tag, StringRef>
+      BaseType;
+
+public:
+  DbiModuleSourceFilesIterator(const DbiModuleList &Modules, uint32_t Modi,
+                               uint16_t Filei);
+  DbiModuleSourceFilesIterator() = default;
+  DbiModuleSourceFilesIterator &
+  operator=(const DbiModuleSourceFilesIterator &R) = default;
+
+  bool operator==(const DbiModuleSourceFilesIterator &R) const;
+
+  const StringRef &operator*() const { return ThisValue; }
+  StringRef &operator*() { return ThisValue; }
+
+  bool operator<(const DbiModuleSourceFilesIterator &RHS) const;
+  std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const;
+  DbiModuleSourceFilesIterator &operator+=(std::ptrdiff_t N);
+  DbiModuleSourceFilesIterator &operator-=(std::ptrdiff_t N);
+
+private:
+  void setValue();
+
+  bool isEnd() const;
+  bool isCompatible(const DbiModuleSourceFilesIterator &R) const;
+  bool isUniversalEnd() const;
+
+  StringRef ThisValue;
+  const DbiModuleList *Modules{nullptr};
+  uint32_t Modi{0};
+  uint16_t Filei{0};
+};
+
+class DbiModuleList {
+  friend DbiModuleSourceFilesIterator;
+
+public:
+  Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo);
+
+  Expected<StringRef> getFileName(uint32_t Index) const;
+  uint32_t getModuleCount() const;
+  uint32_t getSourceFileCount() const;
+  uint16_t getSourceFileCount(uint32_t Modi) const;
+
+  iterator_range<DbiModuleSourceFilesIterator>
+  source_files(uint32_t Modi) const;
+
+  DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const;
+
+private:
+  Error initializeModInfo(BinaryStreamRef ModInfo);
+  Error initializeFileInfo(BinaryStreamRef FileInfo);
+
+  VarStreamArray<DbiModuleDescriptor> Descriptors;
+
+  FixedStreamArray<support::little32_t> FileNameOffsets;
+  FixedStreamArray<support::ulittle16_t> ModFileCountArray;
+
+  // For each module, there are multiple filenames, which can be obtained by
+  // knowing the index of the file.  Given the index of the file, one can use
+  // that as an offset into the FileNameOffsets array, which contains the
+  // absolute offset of the file name in NamesBuffer.  Thus, for each module
+  // we store the first index in the FileNameOffsets array for this module.
+  // The number of files for the corresponding module is stored in
+  // ModFileCountArray.
+  std::vector<uint32_t> ModuleInitialFileIndex;
+
+  // In order to provide random access into the Descriptors array, we iterate it
+  // once up front to find the offsets of the individual items and store them in
+  // this array.
+  std::vector<uint32_t> ModuleDescriptorOffsets;
+
+  const FileInfoSubstreamHeader *FileInfoHeader = nullptr;
+
+  BinaryStreamRef ModInfoSubstream;
+  BinaryStreamRef FileInfoSubstream;
+  BinaryStreamRef NamesBuffer;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
\ No newline at end of file
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/include/llvm/DebugInfo/PDB/Native/DbiStream.h
index 08262e47f77f..8f95481f4152 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStream.h
@@ -13,6 +13,7 @@
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
@@ -68,9 +69,7 @@ public:
   /// not present, returns InvalidStreamIndex.
   uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
 
-  ArrayRef<ModuleInfoEx> modules() const;
-
-  Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
+  const DbiModuleList &modules() const;
 
   FixedStreamArray<object::coff_section> getSectionHeaders();
 
@@ -80,27 +79,22 @@ public:
   void visitSectionContributions(ISectionContribVisitor &Visitor) const;
 
 private:
-  Error initializeModInfoArray();
   Error initializeSectionContributionData();
   Error initializeSectionHeadersData();
   Error initializeSectionMapData();
-  Error initializeFileInfo();
   Error initializeFpoRecords();
 
   PDBFile &Pdb;
   std::unique_ptr<msf::MappedBlockStream> Stream;
 
-  std::vector<ModuleInfoEx> ModuleInfos;
   PDBStringTable ECNames;
 
-  BinaryStreamRef ModInfoSubstream;
   BinaryStreamRef SecContrSubstream;
   BinaryStreamRef SecMapSubstream;
-  BinaryStreamRef FileInfoSubstream;
   BinaryStreamRef TypeServerMapSubstream;
   BinaryStreamRef ECSubstream;
 
-  BinaryStreamRef NamesBuffer;
+  DbiModuleList Modules;
 
   FixedStreamArray<support::ulittle16_t> DbgStreams;
 
@@ -108,7 +102,6 @@ private:
   FixedStreamArray<SectionContrib> SectionContribs;
   FixedStreamArray<SectionContrib2> SectionContribs2;
   FixedStreamArray<SecMapEntry> SectionMap;
-  FixedStreamArray<support::little32_t> FileNameOffsets;
 
   std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
   FixedStreamArray<object::coff_section> SectionHeaders;
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h
index b1d980679a45..22ed61910d94 100644
--- a/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h
+++ b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h
@@ -18,7 +18,7 @@ namespace pdb {
 
 class NativeCompilandSymbol : public NativeRawSymbol {
 public:
-  NativeCompilandSymbol(NativeSession &Session, const ModuleInfoEx &MI);
+  NativeCompilandSymbol(NativeSession &Session, DbiModuleDescriptor MI);
   PDB_SymType getSymTag() const override;
   bool isEditAndContinueEnabled() const override;
   uint32_t getLexicalParentId() const override;
@@ -26,7 +26,7 @@ public:
   std::string getName() const override;
 
 private:
-  ModuleInfoEx Module;
+  DbiModuleDescriptor Module;
 };
 
 } // namespace pdb
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
index 18022f599bba..6aa1460dbb4e 100644
--- a/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
+++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
@@ -16,13 +16,13 @@
 namespace llvm {
 namespace pdb {
 
+class DbiModuleList;
 class NativeSession;
 
 class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> {
 public:
-  explicit NativeEnumModules(NativeSession &Session,
-                             ArrayRef<ModuleInfoEx> Modules,
-                             uint32_t Index = 0);
+  NativeEnumModules(NativeSession &Session, const DbiModuleList &Modules,
+                    uint32_t Index = 0);
 
   uint32_t getChildCount() const override;
   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
@@ -32,7 +32,7 @@ public:
 
 private:
   NativeSession &Session;
-  ArrayRef<ModuleInfoEx> Modules;
+  const DbiModuleList &Modules;
   uint32_t Index;
 };
 }
diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
index 93622d0a4394..979b8454dd5e 100644
--- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
@@ -211,7 +211,7 @@ struct ModInfoFlags {
 };
 
 /// The header preceeding each entry in the Module Info substream of the DBI
-/// stream.
+/// stream.  Corresponds to the type MODI in the reference implementation.
 struct ModuleInfoHeader {
   /// Currently opened module. This field is a pointer in the reference
   /// implementation, but that won't work on 64-bit systems, and anyway it
@@ -243,9 +243,12 @@ struct ModuleInfoHeader {
   /// Padding so the next field is 4-byte aligned.
   char Padding1[2];
 
-  /// Array of [0..NumFiles) DBI name buffer offsets.  This field is a pointer
-  /// in the reference implementation, but as with `Mod`, we ignore it for now
-  /// since it is unused.
+  /// Array of [0..NumFiles) DBI name buffer offsets.  In the reference
+  /// implementation this field is a pointer.  But since you can't portably
+  /// serialize a pointer, on 64-bit platforms they copy all the values except
+  /// this one into the 32-bit version of the struct and use that for
+  /// serialization.  Regardless, this field is unused, it is only there to
+  /// store a pointer that can be accessed at runtime.
   support::ulittle32_t FileNameOffs;
 
   /// Name Index for src file name
diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
index 62dde0ef08b7..9fef9bee5e1a 100644
--- a/include/llvm/DebugInfo/PDB/Native/TpiStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
@@ -40,12 +40,12 @@ public:
 
   uint32_t TypeIndexBegin() const;
   uint32_t TypeIndexEnd() const;
-  uint32_t NumTypeRecords() const;
+  uint32_t getNumTypeRecords() const;
   uint16_t getTypeHashStreamIndex() const;
   uint16_t getTypeHashStreamAuxIndex() const;
 
   uint32_t getHashKeySize() const;
-  uint32_t NumHashBuckets() const;
+  uint32_t getNumHashBuckets() const;
   FixedStreamArray<support::ulittle32_t> getHashValues() const;
   FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
   HashTable &getHashAdjusters();
@@ -55,8 +55,6 @@ public:
   Error commit();
 
 private:
-  Error verifyHashValues();
-
   const PDBFile &Pdb;
   std::unique_ptr<msf::MappedBlockStream> Stream;
 
-- 
cgit v1.2.3