Initial check in

Bug: 137197907
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/CMakeLists.txt
new file mode 100644
index 0000000..e7be0a0
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_subdirectory(DWARF)
+add_subdirectory(MSF)
+add_subdirectory(CodeView)
+add_subdirectory(PDB)
+add_subdirectory(Symbolize)
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp
new file mode 100644
index 0000000..8828671
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp
@@ -0,0 +1,101 @@
+//===- AppendingTypeTableBuilder.cpp --------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+TypeIndex AppendingTypeTableBuilder::nextTypeIndex() const {
+  return TypeIndex::fromArrayIndex(SeenRecords.size());
+}
+
+AppendingTypeTableBuilder::AppendingTypeTableBuilder(BumpPtrAllocator &Storage)
+    : RecordStorage(Storage) {}
+
+AppendingTypeTableBuilder::~AppendingTypeTableBuilder() = default;
+
+Optional<TypeIndex> AppendingTypeTableBuilder::getFirst() {
+  if (empty())
+    return None;
+
+  return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+}
+
+Optional<TypeIndex> AppendingTypeTableBuilder::getNext(TypeIndex Prev) {
+  if (++Prev == nextTypeIndex())
+    return None;
+  return Prev;
+}
+
+CVType AppendingTypeTableBuilder::getType(TypeIndex Index) {
+  CVType Type;
+  Type.RecordData = SeenRecords[Index.toArrayIndex()];
+  const RecordPrefix *P =
+      reinterpret_cast<const RecordPrefix *>(Type.RecordData.data());
+  Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+  return Type;
+}
+
+StringRef AppendingTypeTableBuilder::getTypeName(TypeIndex Index) {
+  llvm_unreachable("Method not implemented");
+}
+
+bool AppendingTypeTableBuilder::contains(TypeIndex Index) {
+  if (Index.isSimple() || Index.isNoneType())
+    return false;
+
+  return Index.toArrayIndex() < SeenRecords.size();
+}
+
+uint32_t AppendingTypeTableBuilder::size() { return SeenRecords.size(); }
+
+uint32_t AppendingTypeTableBuilder::capacity() { return SeenRecords.size(); }
+
+ArrayRef<ArrayRef<uint8_t>> AppendingTypeTableBuilder::records() const {
+  return SeenRecords;
+}
+
+void AppendingTypeTableBuilder::reset() { SeenRecords.clear(); }
+
+TypeIndex
+AppendingTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> &Record) {
+  TypeIndex NewTI = nextTypeIndex();
+  uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size());
+  memcpy(Stable, Record.data(), Record.size());
+  Record = ArrayRef<uint8_t>(Stable, Record.size());
+  SeenRecords.push_back(Record);
+  return NewTI;
+}
+
+TypeIndex
+AppendingTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
+  TypeIndex TI;
+  auto Fragments = Builder.end(nextTypeIndex());
+  assert(!Fragments.empty());
+  for (auto C : Fragments)
+    TI = insertRecordBytes(C.RecordData);
+  return TI;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
new file mode 100644
index 0000000..1610ca4
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -0,0 +1,45 @@
+add_llvm_library(LLVMDebugInfoCodeView
+  AppendingTypeTableBuilder.cpp
+  CodeViewError.cpp
+  CodeViewRecordIO.cpp
+  ContinuationRecordBuilder.cpp
+  CVSymbolVisitor.cpp
+  CVTypeVisitor.cpp
+  DebugChecksumsSubsection.cpp
+  DebugCrossExSubsection.cpp
+  DebugCrossImpSubsection.cpp
+  DebugFrameDataSubsection.cpp
+  DebugInlineeLinesSubsection.cpp
+  DebugLinesSubsection.cpp
+  DebugStringTableSubsection.cpp
+  DebugSubsection.cpp
+  DebugSubsectionRecord.cpp
+  DebugSubsectionVisitor.cpp
+  DebugSymbolRVASubsection.cpp
+  DebugSymbolsSubsection.cpp
+  EnumTables.cpp
+  Formatters.cpp
+  GlobalTypeTableBuilder.cpp
+  LazyRandomTypeCollection.cpp
+  Line.cpp
+  MergingTypeTableBuilder.cpp
+  RecordName.cpp
+  RecordSerialization.cpp
+  SimpleTypeSerializer.cpp
+  StringsAndChecksums.cpp
+  SymbolDumper.cpp
+  SymbolRecordHelpers.cpp
+  SymbolRecordMapping.cpp
+  SymbolSerializer.cpp
+  TypeDumpVisitor.cpp
+  TypeIndex.cpp
+  TypeIndexDiscovery.cpp
+  TypeHashing.cpp
+  TypeRecordHelpers.cpp
+  TypeRecordMapping.cpp
+  TypeStreamMerger.cpp
+  TypeTableCollection.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
+  )
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
new file mode 100644
index 0000000..cbcaa56
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
@@ -0,0 +1,83 @@
+//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
+    : Callbacks(Callbacks) {}
+
+template <typename T>
+static Error visitKnownRecord(CVSymbol &Record,
+                              SymbolVisitorCallbacks &Callbacks) {
+  SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+static Error finishVisitation(CVSymbol &Record,
+                              SymbolVisitorCallbacks &Callbacks) {
+  switch (Record.Type) {
+  default:
+    if (auto EC = Callbacks.visitUnknownSymbol(Record))
+      return EC;
+    break;
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+  }
+
+  if (auto EC = Callbacks.visitSymbolEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
+  if (auto EC = Callbacks.visitSymbolBegin(Record))
+    return EC;
+  return finishVisitation(Record, Callbacks);
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {
+  if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))
+    return EC;
+  return finishVisitation(Record, Callbacks);
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
+  for (auto I : Symbols) {
+    if (auto EC = visitSymbolRecord(I))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
+                                         uint32_t InitialOffset) {
+  for (auto I : Symbols) {
+    if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))
+      return EC;
+    InitialOffset += I.length();
+  }
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
new file mode 100644
index 0000000..a4182a3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -0,0 +1,275 @@
+//===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+
+template <typename T>
+static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
+  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+template <typename T>
+static Error visitKnownMember(CVMemberRecord &Record,
+                              TypeVisitorCallbacks &Callbacks) {
+  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+static Error visitMemberRecord(CVMemberRecord &Record,
+                               TypeVisitorCallbacks &Callbacks) {
+  if (auto EC = Callbacks.visitMemberBegin(Record))
+    return EC;
+
+  switch (Record.Kind) {
+  default:
+    if (auto EC = Callbacks.visitUnknownMember(Record))
+      return EC;
+    break;
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+  }
+
+  if (auto EC = Callbacks.visitMemberEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
+namespace {
+
+class CVTypeVisitor {
+public:
+  explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
+
+  Error visitTypeRecord(CVType &Record, TypeIndex Index);
+  Error visitTypeRecord(CVType &Record);
+
+  /// Visits the type records in Data. Sets the error flag on parse failures.
+  Error visitTypeStream(const CVTypeArray &Types);
+  Error visitTypeStream(CVTypeRange Types);
+  Error visitTypeStream(TypeCollection &Types);
+
+  Error visitMemberRecord(CVMemberRecord Record);
+  Error visitFieldListMemberStream(BinaryStreamReader &Stream);
+
+private:
+  Error finishVisitation(CVType &Record);
+
+  /// The interface to the class that gets notified of each visitation.
+  TypeVisitorCallbacks &Callbacks;
+};
+
+CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
+    : Callbacks(Callbacks) {}
+
+Error CVTypeVisitor::finishVisitation(CVType &Record) {
+  switch (Record.Type) {
+  default:
+    if (auto EC = Callbacks.visitUnknownType(Record))
+      return EC;
+    break;
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
+  TYPE_RECORD(EnumVal, EnumVal, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+  }
+
+  if (auto EC = Callbacks.visitTypeEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
+  if (auto EC = Callbacks.visitTypeBegin(Record, Index))
+    return EC;
+
+  return finishVisitation(Record);
+}
+
+Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
+  if (auto EC = Callbacks.visitTypeBegin(Record))
+    return EC;
+
+  return finishVisitation(Record);
+}
+
+Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) {
+  return ::visitMemberRecord(Record, Callbacks);
+}
+
+/// Visits the type records in Data. Sets the error flag on parse failures.
+Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
+  for (auto I : Types) {
+    if (auto EC = visitTypeRecord(I))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) {
+  for (auto I : Types) {
+    if (auto EC = visitTypeRecord(I))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) {
+  Optional<TypeIndex> I = Types.getFirst();
+  while (I) {
+    CVType Type = Types.getType(*I);
+    if (auto EC = visitTypeRecord(Type, *I))
+      return EC;
+    I = Types.getNext(*I);
+  }
+  return Error::success();
+}
+
+Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) {
+  TypeLeafKind Leaf;
+  while (!Reader.empty()) {
+    if (auto EC = Reader.readEnum(Leaf))
+      return EC;
+
+    CVMemberRecord Record;
+    Record.Kind = Leaf;
+    if (auto EC = ::visitMemberRecord(Record, Callbacks))
+      return EC;
+  }
+
+  return Error::success();
+}
+
+struct FieldListVisitHelper {
+  FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef<uint8_t> Data,
+                       VisitorDataSource Source)
+      : Stream(Data, llvm::support::little), Reader(Stream),
+        Deserializer(Reader),
+        Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
+    if (Source == VDS_BytesPresent) {
+      Pipeline.addCallbackToPipeline(Deserializer);
+      Pipeline.addCallbackToPipeline(Callbacks);
+    }
+  }
+
+  BinaryByteStream Stream;
+  BinaryStreamReader Reader;
+  FieldListDeserializer Deserializer;
+  TypeVisitorCallbackPipeline Pipeline;
+  CVTypeVisitor Visitor;
+};
+
+struct VisitHelper {
+  VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source)
+      : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) {
+    if (Source == VDS_BytesPresent) {
+      Pipeline.addCallbackToPipeline(Deserializer);
+      Pipeline.addCallbackToPipeline(Callbacks);
+    }
+  }
+
+  TypeDeserializer Deserializer;
+  TypeVisitorCallbackPipeline Pipeline;
+  CVTypeVisitor Visitor;
+};
+}
+
+Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
+                                      TypeVisitorCallbacks &Callbacks,
+                                      VisitorDataSource Source) {
+  VisitHelper V(Callbacks, Source);
+  return V.Visitor.visitTypeRecord(Record, Index);
+}
+
+Error llvm::codeview::visitTypeRecord(CVType &Record,
+                                      TypeVisitorCallbacks &Callbacks,
+                                      VisitorDataSource Source) {
+  VisitHelper V(Callbacks, Source);
+  return V.Visitor.visitTypeRecord(Record);
+}
+
+Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
+                                      TypeVisitorCallbacks &Callbacks,
+                                      VisitorDataSource Source) {
+  VisitHelper V(Callbacks, Source);
+  return V.Visitor.visitTypeStream(Types);
+}
+
+Error llvm::codeview::visitTypeStream(CVTypeRange Types,
+                                      TypeVisitorCallbacks &Callbacks) {
+  VisitHelper V(Callbacks, VDS_BytesPresent);
+  return V.Visitor.visitTypeStream(Types);
+}
+
+Error llvm::codeview::visitTypeStream(TypeCollection &Types,
+                                      TypeVisitorCallbacks &Callbacks) {
+  // When the internal visitor calls Types.getType(Index) the interface is
+  // required to return a CVType with the bytes filled out.  So we can assume
+  // that the bytes will be present when individual records are visited.
+  VisitHelper V(Callbacks, VDS_BytesPresent);
+  return V.Visitor.visitTypeStream(Types);
+}
+
+Error llvm::codeview::visitMemberRecord(CVMemberRecord Record,
+                                        TypeVisitorCallbacks &Callbacks,
+                                        VisitorDataSource Source) {
+  FieldListVisitHelper V(Callbacks, Record.Data, Source);
+  return V.Visitor.visitMemberRecord(Record);
+}
+
+Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind,
+                                        ArrayRef<uint8_t> Record,
+                                        TypeVisitorCallbacks &Callbacks) {
+  CVMemberRecord R;
+  R.Data = Record;
+  R.Kind = Kind;
+  return visitMemberRecord(R, Callbacks, VDS_BytesPresent);
+}
+
+Error llvm::codeview::visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
+                                              TypeVisitorCallbacks &Callbacks) {
+  FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent);
+  return V.Visitor.visitFieldListMemberStream(V.Reader);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
new file mode 100644
index 0000000..2a9753a
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
@@ -0,0 +1,48 @@
+//===- CodeViewError.cpp - Error extensions for CodeView --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class CodeViewErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.codeview"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<cv_error_code>(Condition)) {
+    case cv_error_code::unspecified:
+      return "An unknown CodeView error has occurred.";
+    case cv_error_code::insufficient_buffer:
+      return "The buffer is not large enough to read the requested number of "
+             "bytes.";
+    case cv_error_code::corrupt_record:
+      return "The CodeView record is corrupted.";
+    case cv_error_code::no_records:
+      return "There are no records.";
+    case cv_error_code::operation_unsupported:
+      return "The requested operation is not supported.";
+    case cv_error_code::unknown_member_record:
+      return "The member record is of an unknown type.";
+    }
+    llvm_unreachable("Unrecognized cv_error_code");
+  }
+};
+
+static llvm::ManagedStatic<CodeViewErrorCategory> CodeViewErrCategory;
+const std::error_category &llvm::codeview::CVErrorCategory() {
+  return *CodeViewErrCategory;
+}
+
+char CodeViewError::ID;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
new file mode 100644
index 0000000..4fc1448
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -0,0 +1,257 @@
+//===- CodeViewRecordIO.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) {
+  RecordLimit Limit;
+  Limit.MaxLength = MaxLength;
+  Limit.BeginOffset = getCurrentOffset();
+  Limits.push_back(Limit);
+  return Error::success();
+}
+
+Error CodeViewRecordIO::endRecord() {
+  assert(!Limits.empty() && "Not in a record!");
+  Limits.pop_back();
+  // We would like to assert that we actually read / wrote all the bytes that we
+  // expected to for this record, but unfortunately we can't do this.  Some
+  // producers such as MASM over-allocate for certain types of records and
+  // commit the extraneous data, so when reading we can't be sure every byte
+  // will have been read.  And when writing we over-allocate temporarily since
+  // we don't know how big the record is until we're finished writing it, so
+  // even though we don't commit the extraneous data, we still can't guarantee
+  // we're at the end of the allocated data.
+  return Error::success();
+}
+
+uint32_t CodeViewRecordIO::maxFieldLength() const {
+  assert(!Limits.empty() && "Not in a record!");
+
+  // The max length of the next field is the minimum of all lengths that would
+  // be allowed by any of the sub-records we're in.  In practice, we can only
+  // ever be at most 1 sub-record deep (in a FieldList), but this works for
+  // the general case.
+  uint32_t Offset = getCurrentOffset();
+  Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset);
+  for (auto X : makeArrayRef(Limits).drop_front()) {
+    Optional<uint32_t> ThisMin = X.bytesRemaining(Offset);
+    if (ThisMin.hasValue())
+      Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin;
+  }
+  assert(Min.hasValue() && "Every field must have a maximum length!");
+
+  return *Min;
+}
+
+Error CodeViewRecordIO::padToAlignment(uint32_t Align) {
+  if (isReading())
+    return Reader->padToAlignment(Align);
+  return Writer->padToAlignment(Align);
+}
+
+Error CodeViewRecordIO::skipPadding() {
+  assert(!isWriting() && "Cannot skip padding while writing!");
+
+  if (Reader->bytesRemaining() == 0)
+    return Error::success();
+
+  uint8_t Leaf = Reader->peek();
+  if (Leaf < LF_PAD0)
+    return Error::success();
+  // Leaf is greater than 0xf0. We should advance by the number of bytes in
+  // the low 4 bits.
+  unsigned BytesToAdvance = Leaf & 0x0F;
+  return Reader->skip(BytesToAdvance);
+}
+
+Error CodeViewRecordIO::mapByteVectorTail(ArrayRef<uint8_t> &Bytes) {
+  if (isWriting()) {
+    if (auto EC = Writer->writeBytes(Bytes))
+      return EC;
+  } else {
+    if (auto EC = Reader->readBytes(Bytes, Reader->bytesRemaining()))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapByteVectorTail(std::vector<uint8_t> &Bytes) {
+  ArrayRef<uint8_t> BytesRef(Bytes);
+  if (auto EC = mapByteVectorTail(BytesRef))
+    return EC;
+  if (!isWriting())
+    Bytes.assign(BytesRef.begin(), BytesRef.end());
+
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd) {
+  if (isWriting()) {
+    if (auto EC = Writer->writeInteger(TypeInd.getIndex()))
+      return EC;
+    return Error::success();
+  }
+
+  uint32_t I;
+  if (auto EC = Reader->readInteger(I))
+    return EC;
+  TypeInd.setIndex(I);
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(int64_t &Value) {
+  if (isWriting()) {
+    if (Value >= 0) {
+      if (auto EC = writeEncodedUnsignedInteger(static_cast<uint64_t>(Value)))
+        return EC;
+    } else {
+      if (auto EC = writeEncodedSignedInteger(Value))
+        return EC;
+    }
+  } else {
+    APSInt N;
+    if (auto EC = consume(*Reader, N))
+      return EC;
+    Value = N.getExtValue();
+  }
+
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(uint64_t &Value) {
+  if (isWriting()) {
+    if (auto EC = writeEncodedUnsignedInteger(Value))
+      return EC;
+  } else {
+    APSInt N;
+    if (auto EC = consume(*Reader, N))
+      return EC;
+    Value = N.getZExtValue();
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) {
+  if (isWriting()) {
+    if (Value.isSigned())
+      return writeEncodedSignedInteger(Value.getSExtValue());
+    return writeEncodedUnsignedInteger(Value.getZExtValue());
+  }
+
+  return consume(*Reader, Value);
+}
+
+Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
+  if (isWriting()) {
+    // Truncate if we attempt to write too much.
+    StringRef S = Value.take_front(maxFieldLength() - 1);
+    if (auto EC = Writer->writeCString(S))
+      return EC;
+  } else {
+    if (auto EC = Reader->readCString(Value))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapGuid(GUID &Guid) {
+  constexpr uint32_t GuidSize = 16;
+  if (maxFieldLength() < GuidSize)
+    return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+
+  if (isWriting()) {
+    if (auto EC = Writer->writeBytes(Guid.Guid))
+      return EC;
+  } else {
+    ArrayRef<uint8_t> GuidBytes;
+    if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
+      return EC;
+    memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value) {
+  if (isWriting()) {
+    for (auto V : Value) {
+      if (auto EC = mapStringZ(V))
+        return EC;
+    }
+    if (auto EC = Writer->writeInteger<uint8_t>(0))
+      return EC;
+  } else {
+    StringRef S;
+    if (auto EC = mapStringZ(S))
+      return EC;
+    while (!S.empty()) {
+      Value.push_back(S);
+      if (auto EC = mapStringZ(S))
+        return EC;
+    };
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) {
+  assert(Value < 0 && "Encoded integer is not signed!");
+  if (Value >= std::numeric_limits<int8_t>::min()) {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR))
+      return EC;
+    if (auto EC = Writer->writeInteger<int8_t>(Value))
+      return EC;
+  } else if (Value >= std::numeric_limits<int16_t>::min()) {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT))
+      return EC;
+    if (auto EC = Writer->writeInteger<int16_t>(Value))
+      return EC;
+  } else if (Value >= std::numeric_limits<int32_t>::min()) {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG))
+      return EC;
+    if (auto EC = Writer->writeInteger<int32_t>(Value))
+      return EC;
+  } else {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_QUADWORD))
+      return EC;
+    if (auto EC = Writer->writeInteger(Value))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error CodeViewRecordIO::writeEncodedUnsignedInteger(const uint64_t &Value) {
+  if (Value < LF_NUMERIC) {
+    if (auto EC = Writer->writeInteger<uint16_t>(Value))
+      return EC;
+  } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_USHORT))
+      return EC;
+    if (auto EC = Writer->writeInteger<uint16_t>(Value))
+      return EC;
+  } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_ULONG))
+      return EC;
+    if (auto EC = Writer->writeInteger<uint32_t>(Value))
+      return EC;
+  } else {
+    if (auto EC = Writer->writeInteger<uint16_t>(LF_UQUADWORD))
+      return EC;
+    if (auto EC = Writer->writeInteger(Value))
+      return EC;
+  }
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp
new file mode 100644
index 0000000..f180fc6
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp
@@ -0,0 +1,259 @@
+#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+struct ContinuationRecord {
+  ulittle16_t Kind{uint16_t(TypeLeafKind::LF_INDEX)};
+  ulittle16_t Size{0};
+  ulittle32_t IndexRef{0xB0C0B0C0};
+};
+
+struct SegmentInjection {
+  SegmentInjection(TypeLeafKind Kind) { Prefix.RecordKind = Kind; }
+
+  ContinuationRecord Cont;
+  RecordPrefix Prefix;
+};
+} // namespace
+
+static void addPadding(BinaryStreamWriter &Writer) {
+  uint32_t Align = Writer.getOffset() % 4;
+  if (Align == 0)
+    return;
+
+  int PaddingBytes = 4 - Align;
+  while (PaddingBytes > 0) {
+    uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
+    cantFail(Writer.writeInteger(Pad));
+    --PaddingBytes;
+  }
+}
+
+static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST);
+static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST);
+
+static constexpr uint32_t ContinuationLength = sizeof(ContinuationRecord);
+static constexpr uint32_t MaxSegmentLength =
+    MaxRecordLength - ContinuationLength;
+
+static inline TypeLeafKind getTypeLeafKind(ContinuationRecordKind CK) {
+  return (CK == ContinuationRecordKind::FieldList) ? LF_FIELDLIST
+                                                   : LF_METHODLIST;
+}
+
+ContinuationRecordBuilder::ContinuationRecordBuilder()
+    : SegmentWriter(Buffer), Mapping(SegmentWriter) {}
+
+ContinuationRecordBuilder::~ContinuationRecordBuilder() {}
+
+void ContinuationRecordBuilder::begin(ContinuationRecordKind RecordKind) {
+  assert(!Kind.hasValue());
+  Kind = RecordKind;
+  Buffer.clear();
+  SegmentWriter.setOffset(0);
+  SegmentOffsets.clear();
+  SegmentOffsets.push_back(0);
+  assert(SegmentWriter.getOffset() == 0);
+  assert(SegmentWriter.getLength() == 0);
+
+  const SegmentInjection *FLI =
+      (RecordKind == ContinuationRecordKind::FieldList)
+          ? &InjectFieldList
+          : &InjectMethodOverloadList;
+  const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI);
+  InjectedSegmentBytes =
+      ArrayRef<uint8_t>(FLIB, FLIB + sizeof(SegmentInjection));
+
+  CVType Type;
+  Type.Type = getTypeLeafKind(RecordKind);
+  cantFail(Mapping.visitTypeBegin(Type));
+
+  // Seed the first trecord with an appropriate record prefix.
+  RecordPrefix Prefix;
+  Prefix.RecordLen = 0;
+  Prefix.RecordKind = Type.Type;
+  cantFail(SegmentWriter.writeObject(Prefix));
+}
+
+template <typename RecordType>
+void ContinuationRecordBuilder::writeMemberType(RecordType &Record) {
+  assert(Kind.hasValue());
+
+  uint32_t OriginalOffset = SegmentWriter.getOffset();
+  CVMemberRecord CVMR;
+  CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
+
+  // Member Records aren't length-prefixed, they only have a 2-byte TypeLeafKind
+  // at the beginning.
+  cantFail(SegmentWriter.writeEnum(CVMR.Kind));
+
+  // Let the Mapping handle the rest.
+  cantFail(Mapping.visitMemberBegin(CVMR));
+  cantFail(Mapping.visitKnownMember(CVMR, Record));
+  cantFail(Mapping.visitMemberEnd(CVMR));
+
+  // Make sure it's padded to 4 bytes.
+  addPadding(SegmentWriter);
+  assert(getCurrentSegmentLength() % 4 == 0);
+
+  // The maximum length of a single segment is 64KB minus the size to insert a
+  // continuation.  So if we are over that, inject a continuation between the
+  // previous member and the member that was just written, then end the previous
+  // segment after the continuation and begin a new one with the just-written
+  // member.
+  if (getCurrentSegmentLength() > MaxSegmentLength) {
+    // We need to inject some bytes before the member we just wrote but after
+    // the previous member.  Save off the length of the member we just wrote so
+    // that we can do some sanity checking on it.
+    uint32_t MemberLength = SegmentWriter.getOffset() - OriginalOffset;
+    (void) MemberLength;
+    insertSegmentEnd(OriginalOffset);
+    // Since this member now becomes a new top-level record, it should have
+    // gotten a RecordPrefix injected, and that RecordPrefix + the member we
+    // just wrote should now constitute the entirety of the current "new"
+    // segment.
+    assert(getCurrentSegmentLength() == MemberLength + sizeof(RecordPrefix));
+  }
+
+  assert(getCurrentSegmentLength() % 4 == 0);
+  assert(getCurrentSegmentLength() <= MaxSegmentLength);
+}
+
+uint32_t ContinuationRecordBuilder::getCurrentSegmentLength() const {
+  return SegmentWriter.getOffset() - SegmentOffsets.back();
+}
+
+void ContinuationRecordBuilder::insertSegmentEnd(uint32_t Offset) {
+  uint32_t SegmentBegin = SegmentOffsets.back();
+  (void)SegmentBegin;
+  assert(Offset > SegmentBegin);
+  assert(Offset - SegmentBegin <= MaxSegmentLength);
+
+  // We need to make space for the continuation record.  For now we can't fill
+  // out the length or the TypeIndex of the back-reference, but we need the
+  // space to at least be there.
+  Buffer.insert(Offset, InjectedSegmentBytes);
+
+  uint32_t NewSegmentBegin = Offset + ContinuationLength;
+  uint32_t SegmentLength = NewSegmentBegin - SegmentOffsets.back();
+  (void) SegmentLength;
+
+  assert(SegmentLength % 4 == 0);
+  assert(SegmentLength <= MaxRecordLength);
+  SegmentOffsets.push_back(NewSegmentBegin);
+
+  // Seek to the end so that we can keep writing against the new segment.
+  SegmentWriter.setOffset(SegmentWriter.getLength());
+  assert(SegmentWriter.bytesRemaining() == 0);
+}
+
+CVType ContinuationRecordBuilder::createSegmentRecord(
+    uint32_t OffBegin, uint32_t OffEnd, Optional<TypeIndex> RefersTo) {
+  assert(OffEnd - OffBegin <= USHRT_MAX);
+
+  MutableArrayRef<uint8_t> Data = Buffer.data();
+  Data = Data.slice(OffBegin, OffEnd - OffBegin);
+
+  CVType Type;
+  Type.Type = getTypeLeafKind(*Kind);
+  Type.RecordData = Data;
+
+  // Write the length to the RecordPrefix, making sure it does not include
+  // sizeof(RecordPrefix.Length)
+  RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(Data.data());
+  assert(Prefix->RecordKind == Type.Type);
+  Prefix->RecordLen = Data.size() - sizeof(RecordPrefix::RecordLen);
+
+  if (RefersTo.hasValue()) {
+    auto Continuation = Data.take_back(ContinuationLength);
+    ContinuationRecord *CR =
+        reinterpret_cast<ContinuationRecord *>(Continuation.data());
+    assert(CR->Kind == TypeLeafKind::LF_INDEX);
+    assert(CR->IndexRef == 0xB0C0B0C0);
+    CR->IndexRef = RefersTo->getIndex();
+  }
+
+  return Type;
+}
+
+std::vector<CVType> ContinuationRecordBuilder::end(TypeIndex Index) {
+  CVType Type;
+  Type.Type = getTypeLeafKind(*Kind);
+  cantFail(Mapping.visitTypeEnd(Type));
+
+  // We're now done, and we have a series of segments each beginning at an
+  // offset specified in the SegmentOffsets array.  We now need to iterate
+  // over each segment and post-process them in the following two ways:
+  // 1) Each top-level record has a RecordPrefix whose type is either
+  //    LF_FIELDLIST or LF_METHODLIST, but the Length field is still 0.
+  //    Those should all be set to the correct length now.
+  // 2) Each continuation record has an IndexRef field which we set to the
+  //    magic value 0xB0C0B0C0.  Now that the caller has told us the TypeIndex
+  //    they want this sequence to start from, we can go through and update
+  //    each one.
+  //
+  // Logically, the sequence of records we've built up looks like this:
+  //
+  // SegmentOffsets[0]:   <Length>                    (Initially: uninitialized)
+  // SegmentOffsets[0]+2: LF_FIELDLIST
+  // SegmentOffsets[0]+4: Member[0]
+  // SegmentOffsets[0]+?: ...
+  // SegmentOffsets[0]+?: Member[4]
+  // SegmentOffsets[1]-8: LF_INDEX
+  // SegmentOffsets[1]-6: 0
+  // SegmentOffsets[1]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0)
+  //
+  // SegmentOffsets[1]:   <Length>                    (Initially: uninitialized)
+  // SegmentOffsets[1]+2: LF_FIELDLIST
+  // SegmentOffsets[1]+4: Member[0]
+  // SegmentOffsets[1]+?: ...
+  // SegmentOffsets[1]+?: Member[s]
+  // SegmentOffsets[2]-8: LF_INDEX
+  // SegmentOffsets[2]-6: 0
+  // SegmentOffsets[2]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0)
+  //
+  // ...
+  //
+  // SegmentOffsets[N]:   <Length>                    (Initially: uninitialized)
+  // SegmentOffsets[N]+2: LF_FIELDLIST
+  // SegmentOffsets[N]+4: Member[0]
+  // SegmentOffsets[N]+?: ...
+  // SegmentOffsets[N]+?: Member[t]
+  //
+  // And this is the way we have laid them out in the serialization buffer.  But
+  // we cannot actually commit them to the underlying stream this way, due to
+  // the topological sorting requirement of a type stream (specifically,
+  // TypeIndex references can only point backwards, not forwards).  So the
+  // sequence that we return to the caller contains the records in reverse
+  // order, which is the proper order for committing the serialized records.
+
+  std::vector<CVType> Types;
+  Types.reserve(SegmentOffsets.size());
+
+  auto SO = makeArrayRef(SegmentOffsets);
+
+  uint32_t End = SegmentWriter.getOffset();
+
+  Optional<TypeIndex> RefersTo;
+  for (uint32_t Offset : reverse(SO)) {
+    Types.push_back(createSegmentRecord(Offset, End, RefersTo));
+
+    End = Offset;
+    RefersTo = Index++;
+  }
+
+  Kind.reset();
+  return Types;
+}
+
+// Explicitly instantiate the member function for each known type so that we can
+// implement this in the cpp file.
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  template void llvm::codeview::ContinuationRecordBuilder::writeMemberType(    \
+      Name##Record &Record);
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
new file mode 100644
index 0000000..0f155a9
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
@@ -0,0 +1,116 @@
+//===- DebugChecksumsSubsection.cpp ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+struct FileChecksumEntryHeader {
+  using ulittle32_t = support::ulittle32_t;
+
+  ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
+  uint8_t ChecksumSize;       // Number of bytes of checksum.
+  uint8_t ChecksumKind;       // FileChecksumKind
+                              // Checksum bytes follow.
+};
+
+Error VarStreamArrayExtractor<FileChecksumEntry>::
+operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) {
+  BinaryStreamReader Reader(Stream);
+
+  const FileChecksumEntryHeader *Header;
+  if (auto EC = Reader.readObject(Header))
+    return EC;
+
+  Item.FileNameOffset = Header->FileNameOffset;
+  Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
+  if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
+    return EC;
+
+  Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4);
+  return Error::success();
+}
+
+Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) {
+  if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
+    return EC;
+
+  return Error::success();
+}
+
+Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) {
+  BinaryStreamReader Reader(Section);
+  return initialize(Reader);
+}
+
+DebugChecksumsSubsection::DebugChecksumsSubsection(
+    DebugStringTableSubsection &Strings)
+    : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {}
+
+void DebugChecksumsSubsection::addChecksum(StringRef FileName,
+                                           FileChecksumKind Kind,
+                                           ArrayRef<uint8_t> Bytes) {
+  FileChecksumEntry Entry;
+  if (!Bytes.empty()) {
+    uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
+    ::memcpy(Copy, Bytes.data(), Bytes.size());
+    Entry.Checksum = makeArrayRef(Copy, Bytes.size());
+  }
+
+  Entry.FileNameOffset = Strings.insert(FileName);
+  Entry.Kind = Kind;
+  Checksums.push_back(Entry);
+
+  // This maps the offset of this string in the string table to the offset
+  // of this checksum entry in the checksum buffer.
+  OffsetMap[Entry.FileNameOffset] = SerializedSize;
+  assert(SerializedSize % 4 == 0);
+
+  uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
+  SerializedSize += Len;
+}
+
+uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {
+  return SerializedSize;
+}
+
+Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const {
+  for (const auto &FC : Checksums) {
+    FileChecksumEntryHeader Header;
+    Header.ChecksumKind = uint8_t(FC.Kind);
+    Header.ChecksumSize = FC.Checksum.size();
+    Header.FileNameOffset = FC.FileNameOffset;
+    if (auto EC = Writer.writeObject(Header))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
+      return EC;
+    if (auto EC = Writer.padToAlignment(4))
+      return EC;
+  }
+  return Error::success();
+}
+
+uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const {
+  uint32_t Offset = Strings.getIdForString(FileName);
+  auto Iter = OffsetMap.find(Offset);
+  assert(Iter != OffsetMap.end());
+  return Iter->second;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp
new file mode 100644
index 0000000..cef27787
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp
@@ -0,0 +1,53 @@
+//===- DebugCrossExSubsection.cpp -----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error DebugCrossModuleExportsSubsectionRef::initialize(
+    BinaryStreamReader Reader) {
+  if (Reader.bytesRemaining() % sizeof(CrossModuleExport) != 0)
+    return make_error<CodeViewError>(
+        cv_error_code::corrupt_record,
+        "Cross Scope Exports section is an invalid size!");
+
+  uint32_t Size = Reader.bytesRemaining() / sizeof(CrossModuleExport);
+  return Reader.readArray(References, Size);
+}
+
+Error DebugCrossModuleExportsSubsectionRef::initialize(BinaryStreamRef Stream) {
+  BinaryStreamReader Reader(Stream);
+  return initialize(Reader);
+}
+
+void DebugCrossModuleExportsSubsection::addMapping(uint32_t Local,
+                                                   uint32_t Global) {
+  Mappings[Local] = Global;
+}
+
+uint32_t DebugCrossModuleExportsSubsection::calculateSerializedSize() const {
+  return Mappings.size() * sizeof(CrossModuleExport);
+}
+
+Error DebugCrossModuleExportsSubsection::commit(
+    BinaryStreamWriter &Writer) const {
+  for (const auto &M : Mappings) {
+    if (auto EC = Writer.writeInteger(M.first))
+      return EC;
+    if (auto EC = Writer.writeInteger(M.second))
+      return EC;
+  }
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp
new file mode 100644
index 0000000..4001741
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp
@@ -0,0 +1,97 @@
+//===- DebugCrossImpSubsection.cpp ----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error VarStreamArrayExtractor<CrossModuleImportItem>::
+operator()(BinaryStreamRef Stream, uint32_t &Len,
+           codeview::CrossModuleImportItem &Item) {
+  BinaryStreamReader Reader(Stream);
+  if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
+    return make_error<CodeViewError>(
+        cv_error_code::insufficient_buffer,
+        "Not enough bytes for a Cross Module Import Header!");
+  if (auto EC = Reader.readObject(Item.Header))
+    return EC;
+  if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
+    return make_error<CodeViewError>(
+        cv_error_code::insufficient_buffer,
+        "Not enough to read specified number of Cross Module References!");
+  if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
+    return EC;
+  return Error::success();
+}
+
+Error DebugCrossModuleImportsSubsectionRef::initialize(
+    BinaryStreamReader Reader) {
+  return Reader.readArray(References, Reader.bytesRemaining());
+}
+
+Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
+  BinaryStreamReader Reader(Stream);
+  return initialize(Reader);
+}
+
+void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
+                                                  uint32_t ImportId) {
+  Strings.insert(Module);
+  std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
+  auto Result = Mappings.insert(std::make_pair(Module, Targets));
+  if (!Result.second)
+    Result.first->getValue().push_back(Targets[0]);
+}
+
+uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
+  uint32_t Size = 0;
+  for (const auto &Item : Mappings) {
+    Size += sizeof(CrossModuleImport);
+    Size += sizeof(support::ulittle32_t) * Item.second.size();
+  }
+  return Size;
+}
+
+Error DebugCrossModuleImportsSubsection::commit(
+    BinaryStreamWriter &Writer) const {
+  using T = decltype(&*Mappings.begin());
+  std::vector<T> Ids;
+  Ids.reserve(Mappings.size());
+
+  for (const auto &M : Mappings)
+    Ids.push_back(&M);
+
+  llvm::sort(Ids, [this](const T &L1, const T &L2) {
+    return Strings.getIdForString(L1->getKey()) <
+           Strings.getIdForString(L2->getKey());
+  });
+
+  for (const auto &Item : Ids) {
+    CrossModuleImport Imp;
+    Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey());
+    Imp.Count = Item->getValue().size();
+    if (auto EC = Writer.writeObject(Imp))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
+      return EC;
+  }
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
new file mode 100644
index 0000000..5881bf1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
@@ -0,0 +1,62 @@
+//===- DebugFrameDataSubsection.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
+  if (Reader.bytesRemaining() % sizeof(FrameData) != 0) {
+    if (auto EC = Reader.readObject(RelocPtr))
+      return EC;
+  }
+
+  if (Reader.bytesRemaining() % sizeof(FrameData) != 0)
+    return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                     "Invalid frame data record format!");
+
+  uint32_t Count = Reader.bytesRemaining() / sizeof(FrameData);
+  if (auto EC = Reader.readArray(Frames, Count))
+    return EC;
+  return Error::success();
+}
+
+Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) {
+  BinaryStreamReader Reader(Section);
+  return initialize(Reader);
+}
+
+uint32_t DebugFrameDataSubsection::calculateSerializedSize() const {
+  uint32_t Size = sizeof(FrameData) * Frames.size();
+  if (IncludeRelocPtr)
+    Size += sizeof(uint32_t);
+  return Size;
+}
+
+Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const {
+  if (IncludeRelocPtr) {
+    if (auto EC = Writer.writeInteger<uint32_t>(0))
+      return EC;
+  }
+
+  std::vector<FrameData> SortedFrames(Frames.begin(), Frames.end());
+  std::sort(SortedFrames.begin(), SortedFrames.end(),
+            [](const FrameData &LHS, const FrameData &RHS) {
+              return LHS.RvaStart < RHS.RvaStart;
+            });
+  if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames)))
+    return EC;
+  return Error::success();
+}
+
+void DebugFrameDataSubsection::addFrameData(const FrameData &Frame) {
+  Frames.push_back(Frame);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp
new file mode 100644
index 0000000..077c103
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp
@@ -0,0 +1,126 @@
+//===- DebugInlineeLinesSubsection.cpp ------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error VarStreamArrayExtractor<InlineeSourceLine>::
+operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
+  BinaryStreamReader Reader(Stream);
+
+  if (auto EC = Reader.readObject(Item.Header))
+    return EC;
+
+  if (HasExtraFiles) {
+    uint32_t ExtraFileCount;
+    if (auto EC = Reader.readInteger(ExtraFileCount))
+      return EC;
+    if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
+      return EC;
+  }
+
+  Len = Reader.getOffset();
+  return Error::success();
+}
+
+DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
+    : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
+
+Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
+  if (auto EC = Reader.readEnum(Signature))
+    return EC;
+
+  Lines.getExtractor().HasExtraFiles = hasExtraFiles();
+  if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
+    return EC;
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
+  return Signature == InlineeLinesSignature::ExtraFiles;
+}
+
+DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
+    DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
+    : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
+      HasExtraFiles(HasExtraFiles) {}
+
+uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
+  // 4 bytes for the signature
+  uint32_t Size = sizeof(InlineeLinesSignature);
+
+  // one header for each entry.
+  Size += Entries.size() * sizeof(InlineeSourceLineHeader);
+  if (HasExtraFiles) {
+    // If extra files are enabled, one count for each entry.
+    Size += Entries.size() * sizeof(uint32_t);
+
+    // And one file id for each file.
+    Size += ExtraFileCount * sizeof(uint32_t);
+  }
+  assert(Size % 4 == 0);
+  return Size;
+}
+
+Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
+  InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
+  if (HasExtraFiles)
+    Sig = InlineeLinesSignature::ExtraFiles;
+
+  if (auto EC = Writer.writeEnum(Sig))
+    return EC;
+
+  for (const auto &E : Entries) {
+    if (auto EC = Writer.writeObject(E.Header))
+      return EC;
+
+    if (!HasExtraFiles)
+      continue;
+
+    if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
+      return EC;
+  }
+
+  return Error::success();
+}
+
+void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
+  uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+  auto &Entry = Entries.back();
+  Entry.ExtraFiles.push_back(ulittle32_t(Offset));
+  ++ExtraFileCount;
+}
+
+void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
+                                                StringRef FileName,
+                                                uint32_t SourceLine) {
+  uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+  Entries.emplace_back();
+  auto &Entry = Entries.back();
+  Entry.Header.FileID = Offset;
+  Entry.Header.SourceLineNum = SourceLine;
+  Entry.Header.Inlinee = FuncId;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp
new file mode 100644
index 0000000..57ad408
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp
@@ -0,0 +1,161 @@
+//===- DebugLinesSubsection.cpp -------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error LineColumnExtractor::operator()(BinaryStreamRef Stream, uint32_t &Len,
+                                      LineColumnEntry &Item) {
+  const LineBlockFragmentHeader *BlockHeader;
+  BinaryStreamReader Reader(Stream);
+  if (auto EC = Reader.readObject(BlockHeader))
+    return EC;
+  bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns);
+  uint32_t LineInfoSize =
+      BlockHeader->NumLines *
+      (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));
+  if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader))
+    return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                     "Invalid line block record size");
+  uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader);
+  if (LineInfoSize > Size)
+    return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                     "Invalid line block record size");
+  // The value recorded in BlockHeader->BlockSize includes the size of
+  // LineBlockFragmentHeader.
+  Len = BlockHeader->BlockSize;
+  Item.NameIndex = BlockHeader->NameIndex;
+  if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
+    return EC;
+  if (HasColumn) {
+    if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))
+      return EC;
+  }
+  return Error::success();
+}
+
+DebugLinesSubsectionRef::DebugLinesSubsectionRef()
+    : DebugSubsectionRef(DebugSubsectionKind::Lines) {}
+
+Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
+  if (auto EC = Reader.readObject(Header))
+    return EC;
+
+  LinesAndColumns.getExtractor().Header = Header;
+  if (auto EC = Reader.readArray(LinesAndColumns, Reader.bytesRemaining()))
+    return EC;
+
+  return Error::success();
+}
+
+bool DebugLinesSubsectionRef::hasColumnInfo() const {
+  return !!(Header->Flags & LF_HaveColumns);
+}
+
+DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
+                                           DebugStringTableSubsection &Strings)
+    : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {}
+
+void DebugLinesSubsection::createBlock(StringRef FileName) {
+  uint32_t Offset = Checksums.mapChecksumOffset(FileName);
+
+  Blocks.emplace_back(Offset);
+}
+
+void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) {
+  Block &B = Blocks.back();
+  LineNumberEntry LNE;
+  LNE.Flags = Line.getRawData();
+  LNE.Offset = Offset;
+  B.Lines.push_back(LNE);
+}
+
+void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset,
+                                                const LineInfo &Line,
+                                                uint32_t ColStart,
+                                                uint32_t ColEnd) {
+  Block &B = Blocks.back();
+  assert(B.Lines.size() == B.Columns.size());
+
+  addLineInfo(Offset, Line);
+  ColumnNumberEntry CNE;
+  CNE.StartColumn = ColStart;
+  CNE.EndColumn = ColEnd;
+  B.Columns.push_back(CNE);
+}
+
+Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const {
+  LineFragmentHeader Header;
+  Header.CodeSize = CodeSize;
+  Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
+  Header.RelocOffset = RelocOffset;
+  Header.RelocSegment = RelocSegment;
+
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+
+  for (const auto &B : Blocks) {
+    LineBlockFragmentHeader BlockHeader;
+    assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
+
+    BlockHeader.NumLines = B.Lines.size();
+    BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
+    BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
+    if (hasColumnInfo())
+      BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
+    BlockHeader.NameIndex = B.ChecksumBufferOffset;
+    if (auto EC = Writer.writeObject(BlockHeader))
+      return EC;
+
+    if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
+      return EC;
+
+    if (hasColumnInfo()) {
+      if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
+        return EC;
+    }
+  }
+  return Error::success();
+}
+
+uint32_t DebugLinesSubsection::calculateSerializedSize() const {
+  uint32_t Size = sizeof(LineFragmentHeader);
+  for (const auto &B : Blocks) {
+    Size += sizeof(LineBlockFragmentHeader);
+    Size += B.Lines.size() * sizeof(LineNumberEntry);
+    if (hasColumnInfo())
+      Size += B.Columns.size() * sizeof(ColumnNumberEntry);
+  }
+  return Size;
+}
+
+void DebugLinesSubsection::setRelocationAddress(uint16_t Segment,
+                                                uint32_t Offset) {
+  RelocOffset = Offset;
+  RelocSegment = Segment;
+}
+
+void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; }
+
+void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; }
+
+bool DebugLinesSubsection::hasColumnInfo() const {
+  return Flags & LF_HaveColumns;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
new file mode 100644
index 0000000..9b251f5
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
@@ -0,0 +1,108 @@
+//===- DebugStringTableSubsection.cpp - CodeView String Table -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+DebugStringTableSubsectionRef::DebugStringTableSubsectionRef()
+    : DebugSubsectionRef(DebugSubsectionKind::StringTable) {}
+
+Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
+  Stream = Contents;
+  return Error::success();
+}
+
+Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
+  return Reader.readStreamRef(Stream);
+}
+
+Expected<StringRef>
+DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
+  BinaryStreamReader Reader(Stream);
+  Reader.setOffset(Offset);
+  StringRef Result;
+  if (auto EC = Reader.readCString(Result))
+    return std::move(EC);
+  return Result;
+}
+
+DebugStringTableSubsection::DebugStringTableSubsection()
+    : DebugSubsection(DebugSubsectionKind::StringTable) {}
+
+uint32_t DebugStringTableSubsection::insert(StringRef S) {
+  auto P = StringToId.insert({S, StringSize});
+
+  // If a given string didn't exist in the string table, we want to increment
+  // the string table size and insert it into the reverse lookup.
+  if (P.second) {
+    IdToString.insert({P.first->getValue(), P.first->getKey()});
+    StringSize += S.size() + 1; // +1 for '\0'
+  }
+
+  return P.first->second;
+}
+
+uint32_t DebugStringTableSubsection::calculateSerializedSize() const {
+  return StringSize;
+}
+
+Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
+  uint32_t Begin = Writer.getOffset();
+  uint32_t End = Begin + StringSize;
+
+  // Write a null string at the beginning.
+  if (auto EC = Writer.writeCString(StringRef()))
+    return EC;
+
+  for (auto &Pair : StringToId) {
+    StringRef S = Pair.getKey();
+    uint32_t Offset = Begin + Pair.getValue();
+    Writer.setOffset(Offset);
+    if (auto EC = Writer.writeCString(S))
+      return EC;
+    assert(Writer.getOffset() <= End);
+  }
+
+  Writer.setOffset(End);
+  assert((End - Begin) == StringSize);
+  return Error::success();
+}
+
+uint32_t DebugStringTableSubsection::size() const { return StringToId.size(); }
+
+std::vector<uint32_t> DebugStringTableSubsection::sortedIds() const {
+  std::vector<uint32_t> Result;
+  Result.reserve(IdToString.size());
+  for (const auto &Entry : IdToString)
+    Result.push_back(Entry.first);
+  llvm::sort(Result);
+  return Result;
+}
+
+uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const {
+  auto Iter = StringToId.find(S);
+  assert(Iter != StringToId.end());
+  return Iter->second;
+}
+
+StringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const {
+  auto Iter = IdToString.find(Id);
+  assert(Iter != IdToString.end());
+  return Iter->second;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp
new file mode 100644
index 0000000..67b428b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp
@@ -0,0 +1,16 @@
+//===- DebugSubsection.cpp -----------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+
+using namespace llvm::codeview;
+
+DebugSubsectionRef::~DebugSubsectionRef() {}
+
+DebugSubsection::~DebugSubsection() {}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
new file mode 100644
index 0000000..55f343c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
@@ -0,0 +1,97 @@
+//===- DebugSubsectionRecord.cpp ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+DebugSubsectionRecord::DebugSubsectionRecord() = default;
+
+DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
+                                             BinaryStreamRef Data,
+                                             CodeViewContainer Container)
+    : Container(Container), Kind(Kind), Data(Data) {}
+
+Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
+                                        DebugSubsectionRecord &Info,
+                                        CodeViewContainer Container) {
+  const DebugSubsectionHeader *Header;
+  BinaryStreamReader Reader(Stream);
+  if (auto EC = Reader.readObject(Header))
+    return EC;
+
+  DebugSubsectionKind Kind =
+      static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
+  if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
+    return EC;
+  Info.Container = Container;
+  Info.Kind = Kind;
+  return Error::success();
+}
+
+uint32_t DebugSubsectionRecord::getRecordLength() const {
+  return sizeof(DebugSubsectionHeader) + Data.getLength();
+}
+
+DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
+
+BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
+
+DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
+    std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
+    : Subsection(std::move(Subsection)), Container(Container) {}
+
+DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
+    const DebugSubsectionRecord &Contents, CodeViewContainer Container)
+    : Contents(Contents), Container(Container) {}
+
+uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
+  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
+                                 : Contents.getRecordData().getLength();
+  // The length of the entire subsection is always padded to 4 bytes,
+  // regardless of the container kind.
+  return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
+}
+
+Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
+  assert(Writer.getOffset() % alignOf(Container) == 0 &&
+         "Debug Subsection not properly aligned");
+
+  DebugSubsectionHeader Header;
+  Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
+  // The value written into the Header's Length field is only padded to the
+  // container's alignment
+  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
+                                 : Contents.getRecordData().getLength();
+  Header.Length = alignTo(DataSize, alignOf(Container));
+
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+  if (Subsection) {
+    if (auto EC = Subsection->commit(Writer))
+      return EC;
+  } else {
+    if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
+      return EC;
+  }
+  if (auto EC = Writer.padToAlignment(4))
+    return EC;
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
new file mode 100644
index 0000000..9b82433
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
@@ -0,0 +1,95 @@
+//===- DebugSubsectionVisitor.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error llvm::codeview::visitDebugSubsection(
+    const DebugSubsectionRecord &R, DebugSubsectionVisitor &V,
+    const StringsAndChecksumsRef &State) {
+  BinaryStreamReader Reader(R.getRecordData());
+  switch (R.kind()) {
+  case DebugSubsectionKind::Lines: {
+    DebugLinesSubsectionRef Fragment;
+    if (auto EC = Fragment.initialize(Reader))
+      return EC;
+
+    return V.visitLines(Fragment, State);
+  }
+  case DebugSubsectionKind::FileChecksums: {
+    DebugChecksumsSubsectionRef Fragment;
+    if (auto EC = Fragment.initialize(Reader))
+      return EC;
+
+    return V.visitFileChecksums(Fragment, State);
+  }
+  case DebugSubsectionKind::InlineeLines: {
+    DebugInlineeLinesSubsectionRef Fragment;
+    if (auto EC = Fragment.initialize(Reader))
+      return EC;
+    return V.visitInlineeLines(Fragment, State);
+  }
+  case DebugSubsectionKind::CrossScopeExports: {
+    DebugCrossModuleExportsSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitCrossModuleExports(Section, State);
+  }
+  case DebugSubsectionKind::CrossScopeImports: {
+    DebugCrossModuleImportsSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitCrossModuleImports(Section, State);
+  }
+  case DebugSubsectionKind::Symbols: {
+    DebugSymbolsSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitSymbols(Section, State);
+  }
+  case DebugSubsectionKind::StringTable: {
+    DebugStringTableSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitStringTable(Section, State);
+  }
+  case DebugSubsectionKind::FrameData: {
+    DebugFrameDataSubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitFrameData(Section, State);
+  }
+  case DebugSubsectionKind::CoffSymbolRVA: {
+    DebugSymbolRVASubsectionRef Section;
+    if (auto EC = Section.initialize(Reader))
+      return EC;
+    return V.visitCOFFSymbolRVAs(Section, State);
+  }
+  default: {
+    DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
+    return V.visitUnknown(Fragment);
+  }
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolRVASubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolRVASubsection.cpp
new file mode 100644
index 0000000..60fbf9d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolRVASubsection.cpp
@@ -0,0 +1,36 @@
+//===- DebugSymbolRVASubsection.cpp ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+DebugSymbolRVASubsectionRef::DebugSymbolRVASubsectionRef()
+    : DebugSubsectionRef(DebugSubsectionKind::CoffSymbolRVA) {}
+
+Error DebugSymbolRVASubsectionRef::initialize(BinaryStreamReader &Reader) {
+  return Reader.readArray(RVAs, Reader.bytesRemaining() / sizeof(uint32_t));
+}
+
+DebugSymbolRVASubsection::DebugSymbolRVASubsection()
+    : DebugSubsection(DebugSubsectionKind::CoffSymbolRVA) {}
+
+Error DebugSymbolRVASubsection::commit(BinaryStreamWriter &Writer) const {
+  return Writer.writeArray(makeArrayRef(RVAs));
+}
+
+uint32_t DebugSymbolRVASubsection::calculateSerializedSize() const {
+  return RVAs.size() * sizeof(uint32_t);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp
new file mode 100644
index 0000000..dc8ba8c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp
@@ -0,0 +1,34 @@
+//===- DebugSymbolsSubsection.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error DebugSymbolsSubsectionRef::initialize(BinaryStreamReader Reader) {
+  return Reader.readArray(Records, Reader.getLength());
+}
+
+uint32_t DebugSymbolsSubsection::calculateSerializedSize() const {
+  return Length;
+}
+
+Error DebugSymbolsSubsection::commit(BinaryStreamWriter &Writer) const {
+  for (const auto &Record : Records) {
+    if (auto EC = Writer.writeBytes(Record.RecordData))
+      return EC;
+  }
+  return Error::success();
+}
+
+void DebugSymbolsSubsection::addSymbol(CVSymbol Symbol) {
+  Records.push_back(Symbol);
+  Length += Symbol.length();
+}
\ No newline at end of file
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
new file mode 100644
index 0000000..ef4e42f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/EnumTables.cpp
@@ -0,0 +1,369 @@
+//===- EnumTables.cpp - Enum to string conversion tables ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include <type_traits>
+
+using namespace llvm;
+using namespace codeview;
+
+#define CV_ENUM_CLASS_ENT(enum_class, enum)                                    \
+  { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
+
+#define CV_ENUM_ENT(ns, enum)                                                  \
+  { #enum, ns::enum }
+
+static const EnumEntry<SymbolKind> SymbolTypeNames[] = {
+#define CV_SYMBOL(enum, val) {#enum, enum},
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+#undef CV_SYMBOL
+};
+
+static const EnumEntry<TypeLeafKind> TypeLeafNames[] = {
+#define CV_TYPE(name, val) {#name, name},
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+#undef CV_TYPE
+};
+
+static const EnumEntry<uint16_t> RegisterNames[] = {
+#define CV_REGISTER(name, val) CV_ENUM_CLASS_ENT(RegisterId, name),
+#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
+#undef CV_REGISTER
+};
+
+static const EnumEntry<uint32_t> PublicSymFlagNames[] = {
+    CV_ENUM_CLASS_ENT(PublicSymFlags, Code),
+    CV_ENUM_CLASS_ENT(PublicSymFlags, Function),
+    CV_ENUM_CLASS_ENT(PublicSymFlags, Managed),
+    CV_ENUM_CLASS_ENT(PublicSymFlags, MSIL),
+};
+
+static const EnumEntry<uint8_t> ProcSymFlagNames[] = {
+    CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, HasFRET),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoReturn),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, IsUnreachable),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, HasCustomCallingConv),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, IsNoInline),
+    CV_ENUM_CLASS_ENT(ProcSymFlags, HasOptimizedDebugInfo),
+};
+
+static const EnumEntry<uint16_t> LocalFlags[] = {
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsParameter),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsAddressTaken),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsCompilerGenerated),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregate),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsAggregated),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsAliased),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsAlias),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsReturnValue),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsOptimizedOut),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredGlobal),
+    CV_ENUM_CLASS_ENT(LocalSymFlags, IsEnregisteredStatic),
+};
+
+static const EnumEntry<uint8_t> FrameCookieKinds[] = {
+    CV_ENUM_CLASS_ENT(FrameCookieKind, Copy),
+    CV_ENUM_CLASS_ENT(FrameCookieKind, XorStackPointer),
+    CV_ENUM_CLASS_ENT(FrameCookieKind, XorFramePointer),
+    CV_ENUM_CLASS_ENT(FrameCookieKind, XorR13),
+};
+
+static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = {
+    CV_ENUM_ENT(SourceLanguage, C),       CV_ENUM_ENT(SourceLanguage, Cpp),
+    CV_ENUM_ENT(SourceLanguage, Fortran), CV_ENUM_ENT(SourceLanguage, Masm),
+    CV_ENUM_ENT(SourceLanguage, Pascal),  CV_ENUM_ENT(SourceLanguage, Basic),
+    CV_ENUM_ENT(SourceLanguage, Cobol),   CV_ENUM_ENT(SourceLanguage, Link),
+    CV_ENUM_ENT(SourceLanguage, Cvtres),  CV_ENUM_ENT(SourceLanguage, Cvtpgd),
+    CV_ENUM_ENT(SourceLanguage, CSharp),  CV_ENUM_ENT(SourceLanguage, VB),
+    CV_ENUM_ENT(SourceLanguage, ILAsm),   CV_ENUM_ENT(SourceLanguage, Java),
+    CV_ENUM_ENT(SourceLanguage, JScript), CV_ENUM_ENT(SourceLanguage, MSIL),
+    CV_ENUM_ENT(SourceLanguage, HLSL),    CV_ENUM_ENT(SourceLanguage, D),
+};
+
+static const EnumEntry<uint32_t> CompileSym2FlagNames[] = {
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, EC),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDbgInfo),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, LTCG),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, NoDataAlign),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, ManagedPresent),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, SecurityChecks),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, HotPatch),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, CVTCIL),
+    CV_ENUM_CLASS_ENT(CompileSym2Flags, MSILModule),
+};
+
+static const EnumEntry<uint32_t> CompileSym3FlagNames[] = {
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, EC),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDbgInfo),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, LTCG),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, NoDataAlign),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, ManagedPresent),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, SecurityChecks),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, HotPatch),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, CVTCIL),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, MSILModule),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, Sdl),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, PGO),
+    CV_ENUM_CLASS_ENT(CompileSym3Flags, Exp),
+};
+
+static const EnumEntry<uint32_t> FileChecksumNames[] = {
+    CV_ENUM_CLASS_ENT(FileChecksumKind, None),
+    CV_ENUM_CLASS_ENT(FileChecksumKind, MD5),
+    CV_ENUM_CLASS_ENT(FileChecksumKind, SHA1),
+    CV_ENUM_CLASS_ENT(FileChecksumKind, SHA256),
+};
+
+static const EnumEntry<unsigned> CPUTypeNames[] = {
+    CV_ENUM_CLASS_ENT(CPUType, Intel8080),
+    CV_ENUM_CLASS_ENT(CPUType, Intel8086),
+    CV_ENUM_CLASS_ENT(CPUType, Intel80286),
+    CV_ENUM_CLASS_ENT(CPUType, Intel80386),
+    CV_ENUM_CLASS_ENT(CPUType, Intel80486),
+    CV_ENUM_CLASS_ENT(CPUType, Pentium),
+    CV_ENUM_CLASS_ENT(CPUType, PentiumPro),
+    CV_ENUM_CLASS_ENT(CPUType, Pentium3),
+    CV_ENUM_CLASS_ENT(CPUType, MIPS),
+    CV_ENUM_CLASS_ENT(CPUType, MIPS16),
+    CV_ENUM_CLASS_ENT(CPUType, MIPS32),
+    CV_ENUM_CLASS_ENT(CPUType, MIPS64),
+    CV_ENUM_CLASS_ENT(CPUType, MIPSI),
+    CV_ENUM_CLASS_ENT(CPUType, MIPSII),
+    CV_ENUM_CLASS_ENT(CPUType, MIPSIII),
+    CV_ENUM_CLASS_ENT(CPUType, MIPSIV),
+    CV_ENUM_CLASS_ENT(CPUType, MIPSV),
+    CV_ENUM_CLASS_ENT(CPUType, M68000),
+    CV_ENUM_CLASS_ENT(CPUType, M68010),
+    CV_ENUM_CLASS_ENT(CPUType, M68020),
+    CV_ENUM_CLASS_ENT(CPUType, M68030),
+    CV_ENUM_CLASS_ENT(CPUType, M68040),
+    CV_ENUM_CLASS_ENT(CPUType, Alpha),
+    CV_ENUM_CLASS_ENT(CPUType, Alpha21164),
+    CV_ENUM_CLASS_ENT(CPUType, Alpha21164A),
+    CV_ENUM_CLASS_ENT(CPUType, Alpha21264),
+    CV_ENUM_CLASS_ENT(CPUType, Alpha21364),
+    CV_ENUM_CLASS_ENT(CPUType, PPC601),
+    CV_ENUM_CLASS_ENT(CPUType, PPC603),
+    CV_ENUM_CLASS_ENT(CPUType, PPC604),
+    CV_ENUM_CLASS_ENT(CPUType, PPC620),
+    CV_ENUM_CLASS_ENT(CPUType, PPCFP),
+    CV_ENUM_CLASS_ENT(CPUType, PPCBE),
+    CV_ENUM_CLASS_ENT(CPUType, SH3),
+    CV_ENUM_CLASS_ENT(CPUType, SH3E),
+    CV_ENUM_CLASS_ENT(CPUType, SH3DSP),
+    CV_ENUM_CLASS_ENT(CPUType, SH4),
+    CV_ENUM_CLASS_ENT(CPUType, SHMedia),
+    CV_ENUM_CLASS_ENT(CPUType, ARM3),
+    CV_ENUM_CLASS_ENT(CPUType, ARM4),
+    CV_ENUM_CLASS_ENT(CPUType, ARM4T),
+    CV_ENUM_CLASS_ENT(CPUType, ARM5),
+    CV_ENUM_CLASS_ENT(CPUType, ARM5T),
+    CV_ENUM_CLASS_ENT(CPUType, ARM6),
+    CV_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
+    CV_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
+    CV_ENUM_CLASS_ENT(CPUType, ARM7),
+    CV_ENUM_CLASS_ENT(CPUType, Omni),
+    CV_ENUM_CLASS_ENT(CPUType, Ia64),
+    CV_ENUM_CLASS_ENT(CPUType, Ia64_2),
+    CV_ENUM_CLASS_ENT(CPUType, CEE),
+    CV_ENUM_CLASS_ENT(CPUType, AM33),
+    CV_ENUM_CLASS_ENT(CPUType, M32R),
+    CV_ENUM_CLASS_ENT(CPUType, TriCore),
+    CV_ENUM_CLASS_ENT(CPUType, X64),
+    CV_ENUM_CLASS_ENT(CPUType, EBC),
+    CV_ENUM_CLASS_ENT(CPUType, Thumb),
+    CV_ENUM_CLASS_ENT(CPUType, ARMNT),
+    CV_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
+};
+
+static const EnumEntry<uint32_t> FrameProcSymFlagNames[] = {
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, HasStructuredExceptionHandling),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, Naked),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, AsynchronousExceptionHandling),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, NoStackOrderingForSecurityChecks),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedLocalBasePointerMask),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedParamBasePointerMask),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg),
+    CV_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
+};
+
+static const EnumEntry<uint32_t> ModuleSubstreamKindNames[] = {
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, None),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, Lines),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput),
+    CV_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA),
+};
+
+static const EnumEntry<uint16_t> ExportSymFlagNames[] = {
+    CV_ENUM_CLASS_ENT(ExportFlags, IsConstant),
+    CV_ENUM_CLASS_ENT(ExportFlags, IsData),
+    CV_ENUM_CLASS_ENT(ExportFlags, IsPrivate),
+    CV_ENUM_CLASS_ENT(ExportFlags, HasNoName),
+    CV_ENUM_CLASS_ENT(ExportFlags, HasExplicitOrdinal),
+    CV_ENUM_CLASS_ENT(ExportFlags, IsForwarder),
+};
+
+static const EnumEntry<uint8_t> ThunkOrdinalNames[] = {
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, Standard),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, ThisAdjustor),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, Vcall),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, Pcode),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, UnknownLoad),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, TrampIncremental),
+    CV_ENUM_CLASS_ENT(ThunkOrdinal, BranchIsland),
+};
+
+static const EnumEntry<uint16_t> TrampolineNames[] = {
+    CV_ENUM_CLASS_ENT(TrampolineType, TrampIncremental),
+    CV_ENUM_CLASS_ENT(TrampolineType, BranchIsland),
+};
+
+static const EnumEntry<COFF::SectionCharacteristics>
+    ImageSectionCharacteristicNames[] = {
+        CV_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_GPREL),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ),
+        CV_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE)};
+
+namespace llvm {
+namespace codeview {
+
+ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames() {
+  return makeArrayRef(SymbolTypeNames);
+}
+
+ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() {
+  return makeArrayRef(TypeLeafNames);
+}
+
+ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {
+  return makeArrayRef(RegisterNames);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames() {
+  return makeArrayRef(PublicSymFlagNames);
+}
+
+ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames() {
+  return makeArrayRef(ProcSymFlagNames);
+}
+
+ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames() {
+  return makeArrayRef(LocalFlags);
+}
+
+ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames() {
+  return makeArrayRef(FrameCookieKinds);
+}
+
+ArrayRef<EnumEntry<SourceLanguage>> getSourceLanguageNames() {
+  return makeArrayRef(SourceLanguages);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getCompileSym2FlagNames() {
+  return makeArrayRef(CompileSym2FlagNames);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getCompileSym3FlagNames() {
+  return makeArrayRef(CompileSym3FlagNames);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getFileChecksumNames() {
+  return makeArrayRef(FileChecksumNames);
+}
+
+ArrayRef<EnumEntry<unsigned>> getCPUTypeNames() {
+  return makeArrayRef(CPUTypeNames);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getFrameProcSymFlagNames() {
+  return makeArrayRef(FrameProcSymFlagNames);
+}
+
+ArrayRef<EnumEntry<uint16_t>> getExportSymFlagNames() {
+  return makeArrayRef(ExportSymFlagNames);
+}
+
+ArrayRef<EnumEntry<uint32_t>> getModuleSubstreamKindNames() {
+  return makeArrayRef(ModuleSubstreamKindNames);
+}
+
+ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames() {
+  return makeArrayRef(ThunkOrdinalNames);
+}
+
+ArrayRef<EnumEntry<uint16_t>> getTrampolineNames() {
+  return makeArrayRef(TrampolineNames);
+}
+
+ArrayRef<EnumEntry<COFF::SectionCharacteristics>>
+getImageSectionCharacteristicNames() {
+  return makeArrayRef(ImageSectionCharacteristicNames);
+}
+
+} // end namespace codeview
+} // end namespace llvm
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp
new file mode 100644
index 0000000..b8d89c7
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Formatters.cpp
@@ -0,0 +1,48 @@
+//===- Formatters.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/GUID.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::codeview::detail;
+
+GuidAdapter::GuidAdapter(StringRef Guid)
+    : FormatAdapter(makeArrayRef(Guid.bytes_begin(), Guid.bytes_end())) {}
+
+GuidAdapter::GuidAdapter(ArrayRef<uint8_t> Guid)
+    : FormatAdapter(std::move(Guid)) {}
+
+void GuidAdapter::format(raw_ostream &Stream, StringRef Style) {
+  static const char *Lookup = "0123456789ABCDEF";
+
+  assert(Item.size() == 16 && "Expected 16-byte GUID");
+  Stream << "{";
+  for (int i = 0; i < 16;) {
+    uint8_t Byte = Item[i];
+    uint8_t HighNibble = (Byte >> 4) & 0xF;
+    uint8_t LowNibble = Byte & 0xF;
+    Stream << Lookup[HighNibble] << Lookup[LowNibble];
+    ++i;
+    if (i >= 4 && i <= 10 && i % 2 == 0)
+      Stream << "-";
+  }
+  Stream << "}";
+}
+
+raw_ostream &llvm::codeview::operator<<(raw_ostream &OS, const GUID &Guid) {
+  codeview::detail::GuidAdapter A(Guid.Guid);
+  A.format(OS, "");
+  return OS;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp
new file mode 100644
index 0000000..e76f9e1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp
@@ -0,0 +1,114 @@
+//===- GlobalTypeTableBuilder.cpp -----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+TypeIndex GlobalTypeTableBuilder::nextTypeIndex() const {
+  return TypeIndex::fromArrayIndex(SeenRecords.size());
+}
+
+GlobalTypeTableBuilder::GlobalTypeTableBuilder(BumpPtrAllocator &Storage)
+    : RecordStorage(Storage) {
+  SeenRecords.reserve(4096);
+}
+
+GlobalTypeTableBuilder::~GlobalTypeTableBuilder() = default;
+
+Optional<TypeIndex> GlobalTypeTableBuilder::getFirst() {
+  if (empty())
+    return None;
+
+  return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+}
+
+Optional<TypeIndex> GlobalTypeTableBuilder::getNext(TypeIndex Prev) {
+  if (++Prev == nextTypeIndex())
+    return None;
+  return Prev;
+}
+
+CVType GlobalTypeTableBuilder::getType(TypeIndex Index) {
+  CVType Type;
+  Type.RecordData = SeenRecords[Index.toArrayIndex()];
+  if (!Type.RecordData.empty()) {
+    assert(Type.RecordData.size() >= sizeof(RecordPrefix));
+    const RecordPrefix *P =
+        reinterpret_cast<const RecordPrefix *>(Type.RecordData.data());
+    Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+  }
+  return Type;
+}
+
+StringRef GlobalTypeTableBuilder::getTypeName(TypeIndex Index) {
+  llvm_unreachable("Method not implemented");
+}
+
+bool GlobalTypeTableBuilder::contains(TypeIndex Index) {
+  if (Index.isSimple() || Index.isNoneType())
+    return false;
+
+  return Index.toArrayIndex() < SeenRecords.size();
+}
+
+uint32_t GlobalTypeTableBuilder::size() { return SeenRecords.size(); }
+
+uint32_t GlobalTypeTableBuilder::capacity() { return SeenRecords.size(); }
+
+ArrayRef<ArrayRef<uint8_t>> GlobalTypeTableBuilder::records() const {
+  return SeenRecords;
+}
+
+ArrayRef<GloballyHashedType> GlobalTypeTableBuilder::hashes() const {
+  return SeenHashes;
+}
+
+void GlobalTypeTableBuilder::reset() {
+  HashedRecords.clear();
+  SeenRecords.clear();
+}
+
+TypeIndex GlobalTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> Record) {
+  GloballyHashedType GHT =
+      GloballyHashedType::hashType(Record, SeenHashes, SeenHashes);
+  return insertRecordAs(GHT, Record.size(),
+                        [Record](MutableArrayRef<uint8_t> Data) {
+                          assert(Data.size() == Record.size());
+                          ::memcpy(Data.data(), Record.data(), Record.size());
+                          return Data;
+                        });
+}
+
+TypeIndex
+GlobalTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
+  TypeIndex TI;
+  auto Fragments = Builder.end(nextTypeIndex());
+  assert(!Fragments.empty());
+  for (auto C : Fragments)
+    TI = insertRecordBytes(C.RecordData);
+  return TI;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/CodeView/LLVMBuild.txt
new file mode 100644
index 0000000..f799a9e
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/DebugInfo/CodeView/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoCodeView
+parent = DebugInfo
+required_libraries = Support DebugInfoMSF
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
new file mode 100644
index 0000000..ddcad8c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
@@ -0,0 +1,280 @@
+//===- LazyRandomTypeCollection.cpp ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static void error(Error &&EC) {
+  assert(!static_cast<bool>(EC));
+  if (EC)
+    consumeError(std::move(EC));
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)
+    : LazyRandomTypeCollection(CVTypeArray(), RecordCountHint,
+                               PartialOffsetArray()) {}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(
+    const CVTypeArray &Types, uint32_t RecordCountHint,
+    PartialOffsetArray PartialOffsets)
+    : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) {
+  Records.resize(RecordCountHint);
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
+                                                   uint32_t RecordCountHint)
+    : LazyRandomTypeCollection(RecordCountHint) {
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
+                                                   uint32_t RecordCountHint)
+    : LazyRandomTypeCollection(
+          makeArrayRef(Data.bytes_begin(), Data.bytes_end()), RecordCountHint) {
+}
+
+LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,
+                                                   uint32_t NumRecords)
+    : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
+
+void LazyRandomTypeCollection::reset(BinaryStreamReader &Reader,
+                                     uint32_t RecordCountHint) {
+  Count = 0;
+  PartialOffsets = PartialOffsetArray();
+
+  error(Reader.readArray(Types, Reader.bytesRemaining()));
+
+  // Clear and then resize, to make sure existing data gets destroyed.
+  Records.clear();
+  Records.resize(RecordCountHint);
+}
+
+void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) {
+  BinaryStreamReader Reader(Data, support::little);
+  reset(Reader, RecordCountHint);
+}
+
+void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data,
+                                     uint32_t RecordCountHint) {
+  BinaryStreamReader Reader(Data, support::little);
+  reset(Reader, RecordCountHint);
+}
+
+uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) {
+  error(ensureTypeExists(Index));
+  assert(contains(Index));
+
+  return Records[Index.toArrayIndex()].Offset;
+}
+
+CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
+  assert(!Index.isSimple());
+
+  auto EC = ensureTypeExists(Index);
+  error(std::move(EC));
+  assert(contains(Index));
+
+  return Records[Index.toArrayIndex()].Type;
+}
+
+Optional<CVType> LazyRandomTypeCollection::tryGetType(TypeIndex Index) {
+  if (Index.isSimple())
+    return None;
+
+  if (auto EC = ensureTypeExists(Index)) {
+    consumeError(std::move(EC));
+    return None;
+  }
+
+  assert(contains(Index));
+  return Records[Index.toArrayIndex()].Type;
+}
+
+StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
+  if (Index.isNoneType() || Index.isSimple())
+    return TypeIndex::simpleTypeName(Index);
+
+  // Try to make sure the type exists.  Even if it doesn't though, it may be
+  // because we're dumping a symbol stream with no corresponding type stream
+  // present, in which case we still want to be able to print <unknown UDT>
+  // for the type names.
+  if (auto EC = ensureTypeExists(Index)) {
+    consumeError(std::move(EC));
+    return "<unknown UDT>";
+  }
+
+  uint32_t I = Index.toArrayIndex();
+  ensureCapacityFor(Index);
+  if (Records[I].Name.data() == nullptr) {
+    StringRef Result = NameStorage.save(computeTypeName(*this, Index));
+    Records[I].Name = Result;
+  }
+  return Records[I].Name;
+}
+
+bool LazyRandomTypeCollection::contains(TypeIndex Index) {
+  if (Index.isSimple() || Index.isNoneType())
+    return false;
+
+  if (Records.size() <= Index.toArrayIndex())
+    return false;
+  if (!Records[Index.toArrayIndex()].Type.valid())
+    return false;
+  return true;
+}
+
+uint32_t LazyRandomTypeCollection::size() { return Count; }
+
+uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); }
+
+Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
+  if (contains(TI))
+    return Error::success();
+
+  return visitRangeForType(TI);
+}
+
+void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) {
+  assert(!Index.isSimple());
+  uint32_t MinSize = Index.toArrayIndex() + 1;
+
+  if (MinSize <= capacity())
+    return;
+
+  uint32_t NewCapacity = MinSize * 3 / 2;
+
+  assert(NewCapacity > capacity());
+  Records.resize(NewCapacity);
+}
+
+Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
+  assert(!TI.isSimple());
+  if (PartialOffsets.empty())
+    return fullScanForType(TI);
+
+  auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI,
+                               [](TypeIndex Value, const TypeIndexOffset &IO) {
+                                 return Value < IO.Type;
+                               });
+
+  assert(Next != PartialOffsets.begin());
+  auto Prev = std::prev(Next);
+
+  TypeIndex TIB = Prev->Type;
+  if (contains(TIB)) {
+    // They've asked us to fetch a type index, but the entry we found in the
+    // partial offsets array has already been visited.  Since we visit an entire
+    // block every time, that means this record should have been previously
+    // discovered.  Ultimately, this means this is a request for a non-existant
+    // type index.
+    return make_error<CodeViewError>("Invalid type index");
+  }
+
+  TypeIndex TIE;
+  if (Next == PartialOffsets.end()) {
+    TIE = TypeIndex::fromArrayIndex(capacity());
+  } else {
+    TIE = Next->Type;
+  }
+
+  visitRange(TIB, Prev->Offset, TIE);
+  return Error::success();
+}
+
+Optional<TypeIndex> LazyRandomTypeCollection::getFirst() {
+  TypeIndex TI = TypeIndex::fromArrayIndex(0);
+  if (auto EC = ensureTypeExists(TI)) {
+    consumeError(std::move(EC));
+    return None;
+  }
+  return TI;
+}
+
+Optional<TypeIndex> LazyRandomTypeCollection::getNext(TypeIndex Prev) {
+  // We can't be sure how long this type stream is, given that the initial count
+  // given to the constructor is just a hint.  So just try to make sure the next
+  // record exists, and if anything goes wrong, we must be at the end.
+  if (auto EC = ensureTypeExists(Prev + 1)) {
+    consumeError(std::move(EC));
+    return None;
+  }
+
+  return Prev + 1;
+}
+
+Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {
+  assert(!TI.isSimple());
+  assert(PartialOffsets.empty());
+
+  TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
+  auto Begin = Types.begin();
+
+  if (Count > 0) {
+    // In the case of type streams which we don't know the number of records of,
+    // it's possible to search for a type index triggering a full scan, but then
+    // later additional records are added since we didn't know how many there
+    // would be until we did a full visitation, then you try to access the new
+    // type triggering another full scan.  To avoid this, we assume that if the
+    // database has some records, this must be what's going on.  We can also
+    // assume that this index must be larger than the largest type index we've
+    // visited, so we start from there and scan forward.
+    uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset;
+    CurrentTI = LargestTypeIndex + 1;
+    Begin = Types.at(Offset);
+    ++Begin;
+  }
+
+  auto End = Types.end();
+  while (Begin != End) {
+    ensureCapacityFor(CurrentTI);
+    LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI);
+    auto Idx = CurrentTI.toArrayIndex();
+    Records[Idx].Type = *Begin;
+    Records[Idx].Offset = Begin.offset();
+    ++Count;
+    ++Begin;
+    ++CurrentTI;
+  }
+  if (CurrentTI <= TI) {
+    return make_error<CodeViewError>("Type Index does not exist!");
+  }
+  return Error::success();
+}
+
+void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset,
+                                          TypeIndex End) {
+  auto RI = Types.at(BeginOffset);
+  assert(RI != Types.end());
+
+  ensureCapacityFor(End);
+  while (Begin != End) {
+    LargestTypeIndex = std::max(LargestTypeIndex, Begin);
+    auto Idx = Begin.toArrayIndex();
+    Records[Idx].Type = *RI;
+    Records[Idx].Offset = RI.offset();
+    ++Count;
+    ++Begin;
+    ++RI;
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/Line.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Line.cpp
new file mode 100644
index 0000000..4cb766b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/Line.cpp
@@ -0,0 +1,22 @@
+//===-- Line.cpp ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/Line.h"
+
+using namespace llvm;
+using namespace codeview;
+
+LineInfo::LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement) {
+  LineData = StartLine & StartLineMask;
+  uint32_t LineDelta = EndLine - StartLine;
+  LineData |= (LineDelta << EndLineDeltaShift) & EndLineDeltaMask;
+  if (IsStatement) {
+    LineData |= StatementFlag;
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp
new file mode 100644
index 0000000..8aee4aa
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp
@@ -0,0 +1,128 @@
+//===- MergingTypeTableBuilder.cpp ----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+TypeIndex MergingTypeTableBuilder::nextTypeIndex() const {
+  return TypeIndex::fromArrayIndex(SeenRecords.size());
+}
+
+MergingTypeTableBuilder::MergingTypeTableBuilder(BumpPtrAllocator &Storage)
+    : RecordStorage(Storage) {
+  SeenRecords.reserve(4096);
+}
+
+MergingTypeTableBuilder::~MergingTypeTableBuilder() = default;
+
+Optional<TypeIndex> MergingTypeTableBuilder::getFirst() {
+  if (empty())
+    return None;
+
+  return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+}
+
+Optional<TypeIndex> MergingTypeTableBuilder::getNext(TypeIndex Prev) {
+  if (++Prev == nextTypeIndex())
+    return None;
+  return Prev;
+}
+
+CVType MergingTypeTableBuilder::getType(TypeIndex Index) {
+  CVType Type;
+  Type.RecordData = SeenRecords[Index.toArrayIndex()];
+  const RecordPrefix *P =
+      reinterpret_cast<const RecordPrefix *>(Type.RecordData.data());
+  Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+  return Type;
+}
+
+StringRef MergingTypeTableBuilder::getTypeName(TypeIndex Index) {
+  llvm_unreachable("Method not implemented");
+}
+
+bool MergingTypeTableBuilder::contains(TypeIndex Index) {
+  if (Index.isSimple() || Index.isNoneType())
+    return false;
+
+  return Index.toArrayIndex() < SeenRecords.size();
+}
+
+uint32_t MergingTypeTableBuilder::size() { return SeenRecords.size(); }
+
+uint32_t MergingTypeTableBuilder::capacity() { return SeenRecords.size(); }
+
+ArrayRef<ArrayRef<uint8_t>> MergingTypeTableBuilder::records() const {
+  return SeenRecords;
+}
+
+void MergingTypeTableBuilder::reset() {
+  HashedRecords.clear();
+  SeenRecords.clear();
+}
+
+static inline ArrayRef<uint8_t> stabilize(BumpPtrAllocator &Alloc,
+                                          ArrayRef<uint8_t> Data) {
+  uint8_t *Stable = Alloc.Allocate<uint8_t>(Data.size());
+  memcpy(Stable, Data.data(), Data.size());
+  return makeArrayRef(Stable, Data.size());
+}
+
+TypeIndex MergingTypeTableBuilder::insertRecordAs(hash_code Hash,
+                                                  ArrayRef<uint8_t> &Record) {
+  assert(Record.size() < UINT32_MAX && "Record too big");
+  assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
+
+  LocallyHashedType WeakHash{Hash, Record};
+  auto Result = HashedRecords.try_emplace(WeakHash, nextTypeIndex());
+
+  if (Result.second) {
+    ArrayRef<uint8_t> RecordData = stabilize(RecordStorage, Record);
+    Result.first->first.RecordData = RecordData;
+    SeenRecords.push_back(RecordData);
+  }
+
+  // Update the caller's copy of Record to point a stable copy.
+  TypeIndex ActualTI = Result.first->second;
+  Record = SeenRecords[ActualTI.toArrayIndex()];
+  return ActualTI;
+}
+
+TypeIndex
+MergingTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> &Record) {
+  return insertRecordAs(hash_value(Record), Record);
+}
+
+TypeIndex
+MergingTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
+  TypeIndex TI;
+  auto Fragments = Builder.end(nextTypeIndex());
+  assert(!Fragments.empty());
+  for (auto C : Fragments)
+    TI = insertRecordBytes(C.RecordData);
+  return TI;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordName.cpp
new file mode 100644
index 0000000..d868ae2
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordName.cpp
@@ -0,0 +1,338 @@
+//===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+class TypeNameComputer : public TypeVisitorCallbacks {
+  /// The type collection.  Used to calculate names of nested types.
+  TypeCollection &Types;
+  TypeIndex CurrentTypeIndex = TypeIndex::None();
+
+  /// Name of the current type. Only valid before visitTypeEnd.
+  SmallString<256> Name;
+
+public:
+  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
+
+  StringRef name() const { return Name; }
+
+  /// Paired begin/end actions for all types. Receives all record data,
+  /// including the fixed-length record prefix.
+  Error visitTypeBegin(CVType &Record) override;
+  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
+  Error visitTypeEnd(CVType &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+};
+} // namespace
+
+Error TypeNameComputer::visitTypeBegin(CVType &Record) {
+  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
+  return Error::success();
+}
+
+Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
+  // Reset Name to the empty string. If the visitor sets it, we know it.
+  Name = "";
+  CurrentTypeIndex = Index;
+  return Error::success();
+}
+
+Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         FieldListRecord &FieldList) {
+  Name = "<field list>";
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+                                         StringIdRecord &String) {
+  Name = String.getString();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
+  auto Indices = Args.getIndices();
+  uint32_t Size = Indices.size();
+  Name = "(";
+  for (uint32_t I = 0; I < Size; ++I) {
+    assert(Indices[I] < CurrentTypeIndex);
+
+    Name.append(Types.getTypeName(Indices[I]));
+    if (I + 1 != Size)
+      Name.append(", ");
+  }
+  Name.push_back(')');
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         StringListRecord &Strings) {
+  auto Indices = Strings.getIndices();
+  uint32_t Size = Indices.size();
+  Name = "\"";
+  for (uint32_t I = 0; I < Size; ++I) {
+    Name.append(Types.getTypeName(Indices[I]));
+    if (I + 1 != Size)
+      Name.append("\" \"");
+  }
+  Name.push_back('\"');
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
+  Name = Class.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
+  Name = Union.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+  Name = Enum.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+  Name = AT.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
+  Name = VFT.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
+  Name = Id.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
+  StringRef Ret = Types.getTypeName(Proc.getReturnType());
+  StringRef Params = Types.getTypeName(Proc.getArgumentList());
+  Name = formatv("{0} {1}", Ret, Params).sstr<256>();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         MemberFunctionRecord &MF) {
+  StringRef Ret = Types.getTypeName(MF.getReturnType());
+  StringRef Class = Types.getTypeName(MF.getClassType());
+  StringRef Params = Types.getTypeName(MF.getArgumentList());
+  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
+  Name = Func.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
+  Name = TS.getName();
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
+
+  if (Ptr.isPointerToMember()) {
+    const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+    StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
+    StringRef Class = Types.getTypeName(MI.getContainingType());
+    Name = formatv("{0} {1}::*", Pointee, Class);
+  } else {
+    Name.append(Types.getTypeName(Ptr.getReferentType()));
+
+    if (Ptr.getMode() == PointerMode::LValueReference)
+      Name.append("&");
+    else if (Ptr.getMode() == PointerMode::RValueReference)
+      Name.append("&&");
+    else if (Ptr.getMode() == PointerMode::Pointer)
+      Name.append("*");
+
+    // Qualifiers in pointer records apply to the pointer, not the pointee, so
+    // they go on the right.
+    if (Ptr.isConst())
+      Name.append(" const");
+    if (Ptr.isVolatile())
+      Name.append(" volatile");
+    if (Ptr.isUnaligned())
+      Name.append(" __unaligned");
+    if (Ptr.isRestrict())
+      Name.append(" __restrict");
+  }
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
+  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+
+  if (Mods & uint16_t(ModifierOptions::Const))
+    Name.append("const ");
+  if (Mods & uint16_t(ModifierOptions::Volatile))
+    Name.append("volatile ");
+  if (Mods & uint16_t(ModifierOptions::Unaligned))
+    Name.append("__unaligned ");
+  Name.append(Types.getTypeName(Mod.getModifiedType()));
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         VFTableShapeRecord &Shape) {
+  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(
+    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         UdtSourceLineRecord &SourceLine) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         MethodOverloadListRecord &Overloads) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         PrecompRecord &Precomp) {
+  return Error::success();
+}
+
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,
+                                         EndPrecompRecord &EndPrecomp) {
+  return Error::success();
+}
+
+std::string llvm::codeview::computeTypeName(TypeCollection &Types,
+                                            TypeIndex Index) {
+  TypeNameComputer Computer(Types);
+  CVType Record = Types.getType(Index);
+  if (auto EC = visitTypeRecord(Record, Index, Computer)) {
+    consumeError(std::move(EC));
+    return "<unknown UDT>";
+  }
+  return Computer.name();
+}
+
+static int getSymbolNameOffset(CVSymbol Sym) {
+  switch (Sym.kind()) {
+  // See ProcSym
+  case SymbolKind::S_GPROC32:
+  case SymbolKind::S_LPROC32:
+  case SymbolKind::S_GPROC32_ID:
+  case SymbolKind::S_LPROC32_ID:
+  case SymbolKind::S_LPROC32_DPC:
+  case SymbolKind::S_LPROC32_DPC_ID:
+    return 35;
+  // See Thunk32Sym
+  case SymbolKind::S_THUNK32:
+    return 21;
+  // See SectionSym
+  case SymbolKind::S_SECTION:
+    return 16;
+  // See CoffGroupSym
+  case SymbolKind::S_COFFGROUP:
+    return 14;
+  // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
+  case SymbolKind::S_PUB32:
+  case SymbolKind::S_FILESTATIC:
+  case SymbolKind::S_REGREL32:
+  case SymbolKind::S_GDATA32:
+  case SymbolKind::S_LDATA32:
+  case SymbolKind::S_LMANDATA:
+  case SymbolKind::S_GMANDATA:
+  case SymbolKind::S_LTHREAD32:
+  case SymbolKind::S_GTHREAD32:
+  case SymbolKind::S_PROCREF:
+  case SymbolKind::S_LPROCREF:
+    return 10;
+  // See RegisterSym and LocalSym
+  case SymbolKind::S_REGISTER:
+  case SymbolKind::S_LOCAL:
+    return 6;
+  // See BlockSym
+  case SymbolKind::S_BLOCK32:
+    return 18;
+  // See LabelSym
+  case SymbolKind::S_LABEL32:
+    return 7;
+  // See ObjNameSym, ExportSym, and UDTSym
+  case SymbolKind::S_OBJNAME:
+  case SymbolKind::S_EXPORT:
+  case SymbolKind::S_UDT:
+    return 4;
+  // See BPRelativeSym
+  case SymbolKind::S_BPREL32:
+    return 8;
+  // See UsingNamespaceSym
+  case SymbolKind::S_UNAMESPACE:
+    return 0;
+  default:
+    return -1;
+  }
+}
+
+StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
+  if (Sym.kind() == SymbolKind::S_CONSTANT) {
+    // S_CONSTANT is preceded by an APSInt, which has a variable length.  So we
+    // have to do a full deserialization.
+    BinaryStreamReader Reader(Sym.content(), llvm::support::little);
+    // The container doesn't matter for single records.
+    SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
+    ConstantSym Const(SymbolKind::S_CONSTANT);
+    cantFail(Mapping.visitSymbolBegin(Sym));
+    cantFail(Mapping.visitKnownRecord(Sym, Const));
+    cantFail(Mapping.visitSymbolEnd(Sym));
+    return Const.Name;
+  }
+
+  int Offset = getSymbolNameOffset(Sym);
+  if (Offset == -1)
+    return StringRef();
+
+  StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
+  return StringData.split('\0').first;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
new file mode 100644
index 0000000..bff9a61
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp
@@ -0,0 +1,155 @@
+//===-- RecordSerialization.cpp -------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for serializing and deserializing CodeView records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/BinaryByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::support;
+
+/// Reinterpret a byte array as an array of characters. Does not interpret as
+/// a C string, as StringRef has several helpers (split) that make that easy.
+StringRef llvm::codeview::getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
+  return StringRef(reinterpret_cast<const char *>(LeafData.data()),
+                   LeafData.size());
+}
+
+StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) {
+  return getBytesAsCharacters(LeafData).split('\0').first;
+}
+
+Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) {
+  // Used to avoid overload ambiguity on APInt construtor.
+  bool FalseVal = false;
+  uint16_t Short;
+  if (auto EC = Reader.readInteger(Short))
+    return EC;
+
+  if (Short < LF_NUMERIC) {
+    Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
+                 /*isUnsigned=*/true);
+    return Error::success();
+  }
+
+  switch (Short) {
+  case LF_CHAR: {
+    int8_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(8, N, true), false);
+    return Error::success();
+  }
+  case LF_SHORT: {
+    int16_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(16, N, true), false);
+    return Error::success();
+  }
+  case LF_USHORT: {
+    uint16_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(16, N, false), true);
+    return Error::success();
+  }
+  case LF_LONG: {
+    int32_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(32, N, true), false);
+    return Error::success();
+  }
+  case LF_ULONG: {
+    uint32_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(32, N, FalseVal), true);
+    return Error::success();
+  }
+  case LF_QUADWORD: {
+    int64_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(64, N, true), false);
+    return Error::success();
+  }
+  case LF_UQUADWORD: {
+    uint64_t N;
+    if (auto EC = Reader.readInteger(N))
+      return EC;
+    Num = APSInt(APInt(64, N, false), true);
+    return Error::success();
+  }
+  }
+  return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                   "Buffer contains invalid APSInt type");
+}
+
+Error llvm::codeview::consume(StringRef &Data, APSInt &Num) {
+  ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
+  BinaryByteStream S(Bytes, llvm::support::little);
+  BinaryStreamReader SR(S);
+  auto EC = consume(SR, Num);
+  Data = Data.take_back(SR.bytesRemaining());
+  return EC;
+}
+
+/// Decode a numeric leaf value that is known to be a uint64_t.
+Error llvm::codeview::consume_numeric(BinaryStreamReader &Reader,
+                                      uint64_t &Num) {
+  APSInt N;
+  if (auto EC = consume(Reader, N))
+    return EC;
+  if (N.isSigned() || !N.isIntN(64))
+    return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                     "Data is not a numeric value!");
+  Num = N.getLimitedValue();
+  return Error::success();
+}
+
+Error llvm::codeview::consume(BinaryStreamReader &Reader, uint32_t &Item) {
+  return Reader.readInteger(Item);
+}
+
+Error llvm::codeview::consume(StringRef &Data, uint32_t &Item) {
+  ArrayRef<uint8_t> Bytes(Data.bytes_begin(), Data.bytes_end());
+  BinaryByteStream S(Bytes, llvm::support::little);
+  BinaryStreamReader SR(S);
+  auto EC = consume(SR, Item);
+  Data = Data.take_back(SR.bytesRemaining());
+  return EC;
+}
+
+Error llvm::codeview::consume(BinaryStreamReader &Reader, int32_t &Item) {
+  return Reader.readInteger(Item);
+}
+
+Error llvm::codeview::consume(BinaryStreamReader &Reader, StringRef &Item) {
+  if (Reader.empty())
+    return make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                     "Null terminated string buffer is empty!");
+
+  return Reader.readCString(Item);
+}
+
+Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
+                                                        uint32_t Offset) {
+  return readCVRecordFromStream<SymbolKind>(Stream, Offset);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp
new file mode 100644
index 0000000..d28b7c3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp
@@ -0,0 +1,62 @@
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static void writeRecordPrefix(BinaryStreamWriter &Writer, TypeLeafKind Kind) {
+  RecordPrefix Prefix;
+  Prefix.RecordKind = Kind;
+  Prefix.RecordLen = 0;
+  cantFail(Writer.writeObject(Prefix));
+}
+
+static void addPadding(BinaryStreamWriter &Writer) {
+  uint32_t Align = Writer.getOffset() % 4;
+  if (Align == 0)
+    return;
+
+  int PaddingBytes = 4 - Align;
+  while (PaddingBytes > 0) {
+    uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
+    cantFail(Writer.writeInteger(Pad));
+    --PaddingBytes;
+  }
+}
+
+SimpleTypeSerializer::SimpleTypeSerializer() : ScratchBuffer(MaxRecordLength) {}
+
+SimpleTypeSerializer::~SimpleTypeSerializer() {}
+
+template <typename T>
+ArrayRef<uint8_t> SimpleTypeSerializer::serialize(T &Record) {
+  BinaryStreamWriter Writer(ScratchBuffer, support::little);
+  TypeRecordMapping Mapping(Writer);
+
+  CVType CVT;
+  CVT.Type = static_cast<TypeLeafKind>(Record.getKind());
+
+  writeRecordPrefix(Writer, CVT.Type);
+
+  cantFail(Mapping.visitTypeBegin(CVT));
+  cantFail(Mapping.visitKnownRecord(CVT, Record));
+  cantFail(Mapping.visitTypeEnd(CVT));
+
+  addPadding(Writer);
+
+  RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(ScratchBuffer.data());
+
+  Prefix->RecordKind = CVT.kind();
+  Prefix->RecordLen = Writer.getOffset() - sizeof(uint16_t);
+
+  return {ScratchBuffer.data(), Writer.getOffset()};
+}
+
+// Explicitly instantiate the member function for each known type so that we can
+// implement this in the cpp file.
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  template ArrayRef<uint8_t> llvm::codeview::SimpleTypeSerializer::serialize(  \
+      Name##Record &Record);
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp
new file mode 100644
index 0000000..85d9dbb
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp
@@ -0,0 +1,81 @@
+//===- StringsAndChecksums.cpp --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+StringsAndChecksumsRef::StringsAndChecksumsRef() = default;
+
+StringsAndChecksumsRef::StringsAndChecksumsRef(
+    const DebugStringTableSubsectionRef &Strings)
+    : Strings(&Strings) {}
+
+StringsAndChecksumsRef::StringsAndChecksumsRef(
+    const DebugStringTableSubsectionRef &Strings,
+    const DebugChecksumsSubsectionRef &Checksums)
+    : Strings(&Strings), Checksums(&Checksums) {}
+
+void StringsAndChecksumsRef::initializeStrings(
+    const DebugSubsectionRecord &SR) {
+  assert(SR.kind() == DebugSubsectionKind::StringTable);
+  assert(!Strings && "Found a string table even though we already have one!");
+
+  OwnedStrings = std::make_shared<DebugStringTableSubsectionRef>();
+  consumeError(OwnedStrings->initialize(SR.getRecordData()));
+  Strings = OwnedStrings.get();
+}
+
+void StringsAndChecksumsRef::reset() {
+  resetStrings();
+  resetChecksums();
+}
+
+void StringsAndChecksumsRef::resetStrings() {
+  OwnedStrings.reset();
+  Strings = nullptr;
+}
+
+void StringsAndChecksumsRef::resetChecksums() {
+  OwnedChecksums.reset();
+  Checksums = nullptr;
+}
+
+void StringsAndChecksumsRef::setStrings(
+    const DebugStringTableSubsectionRef &StringsRef) {
+  OwnedStrings = std::make_shared<DebugStringTableSubsectionRef>();
+  *OwnedStrings = StringsRef;
+  Strings = OwnedStrings.get();
+}
+
+void StringsAndChecksumsRef::setChecksums(
+    const DebugChecksumsSubsectionRef &CS) {
+  OwnedChecksums = std::make_shared<DebugChecksumsSubsectionRef>();
+  *OwnedChecksums = CS;
+  Checksums = OwnedChecksums.get();
+}
+
+void StringsAndChecksumsRef::initializeChecksums(
+    const DebugSubsectionRecord &FCR) {
+  assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
+  if (Checksums)
+    return;
+
+  OwnedChecksums = std::make_shared<DebugChecksumsSubsectionRef>();
+  consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
+  Checksums = OwnedChecksums.get();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
new file mode 100644
index 0000000..04e0bab
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -0,0 +1,665 @@
+//===-- SymbolDumper.cpp - CodeView symbol info dumper ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+#include <system_error>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+/// Use this private dumper implementation to keep implementation details about
+/// the visitor out of SymbolDumper.h.
+class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
+public:
+  CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate,
+                     ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes)
+      : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU),
+        PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
+
+/// CVSymbolVisitor overrides.
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+
+  Error visitSymbolBegin(CVSymbol &Record) override;
+  Error visitSymbolEnd(CVSymbol &Record) override;
+  Error visitUnknownSymbol(CVSymbol &Record) override;
+
+  CPUType getCompilationCPUType() const { return CompilationCPUType; }
+
+private:
+  void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
+                                   uint32_t RelocationOffset);
+  void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
+  void printTypeIndex(StringRef FieldName, TypeIndex TI);
+
+  TypeCollection &Types;
+  SymbolDumpDelegate *ObjDelegate;
+  ScopedPrinter &W;
+
+  /// Save the machine or CPU type when dumping a compile symbols.
+  CPUType CompilationCPUType = CPUType::X64;
+
+  bool PrintRecordBytes;
+  bool InFunctionScope;
+};
+}
+
+static StringRef getSymbolKindName(SymbolKind Kind) {
+  switch (Kind) {
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName:                                                               \
+    return #Name;
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+  default:
+    break;
+  }
+  return "UnknownSym";
+}
+
+void CVSymbolDumperImpl::printLocalVariableAddrRange(
+    const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
+  DictScope S(W, "LocalVariableAddrRange");
+  if (ObjDelegate)
+    ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
+                                     Range.OffsetStart);
+  W.printHex("ISectStart", Range.ISectStart);
+  W.printHex("Range", Range.Range);
+}
+
+void CVSymbolDumperImpl::printLocalVariableAddrGap(
+    ArrayRef<LocalVariableAddrGap> Gaps) {
+  for (auto &Gap : Gaps) {
+    ListScope S(W, "LocalVariableAddrGap");
+    W.printHex("GapStartOffset", Gap.GapStartOffset);
+    W.printHex("Range", Gap.Range);
+  }
+}
+
+void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
+  codeview::printTypeIndex(W, FieldName, TI, Types);
+}
+
+Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
+  W.startLine() << getSymbolKindName(CVR.Type);
+  W.getOStream() << " {\n";
+  W.indent();
+  W.printEnum("Kind", unsigned(CVR.Type), getSymbolTypeNames());
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
+  if (PrintRecordBytes && ObjDelegate)
+    ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
+
+  W.unindent();
+  W.startLine() << "}\n";
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+  StringRef LinkageName;
+  W.printHex("PtrParent", Block.Parent);
+  W.printHex("PtrEnd", Block.End);
+  W.printHex("CodeSize", Block.CodeSize);
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset", Block.getRelocationOffset(),
+                                     Block.CodeOffset, &LinkageName);
+  }
+  W.printHex("Segment", Block.Segment);
+  W.printString("BlockName", Block.Name);
+  W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+  W.printString("Name", Thunk.Name);
+  W.printNumber("Parent", Thunk.Parent);
+  W.printNumber("End", Thunk.End);
+  W.printNumber("Next", Thunk.Next);
+  W.printNumber("Off", Thunk.Offset);
+  W.printNumber("Seg", Thunk.Segment);
+  W.printNumber("Len", Thunk.Length);
+  W.printEnum("Ordinal", uint8_t(Thunk.Thunk), getThunkOrdinalNames());
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           TrampolineSym &Tramp) {
+  W.printEnum("Type", uint16_t(Tramp.Type), getTrampolineNames());
+  W.printNumber("Size", Tramp.Size);
+  W.printNumber("ThunkOff", Tramp.ThunkOffset);
+  W.printNumber("TargetOff", Tramp.TargetOffset);
+  W.printNumber("ThunkSection", Tramp.ThunkSection);
+  W.printNumber("TargetSection", Tramp.TargetSection);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
+  W.printNumber("SectionNumber", Section.SectionNumber);
+  W.printNumber("Alignment", Section.Alignment);
+  W.printNumber("Rva", Section.Rva);
+  W.printNumber("Length", Section.Length);
+  W.printFlags("Characteristics", Section.Characteristics,
+               getImageSectionCharacteristicNames(),
+               COFF::SectionCharacteristics(0x00F00000));
+
+  W.printString("Name", Section.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           CoffGroupSym &CoffGroup) {
+  W.printNumber("Size", CoffGroup.Size);
+  W.printFlags("Characteristics", CoffGroup.Characteristics,
+               getImageSectionCharacteristicNames(),
+               COFF::SectionCharacteristics(0x00F00000));
+  W.printNumber("Offset", CoffGroup.Offset);
+  W.printNumber("Segment", CoffGroup.Segment);
+  W.printString("Name", CoffGroup.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           BPRelativeSym &BPRel) {
+  W.printNumber("Offset", BPRel.Offset);
+  printTypeIndex("Type", BPRel.Type);
+  W.printString("VarName", BPRel.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           BuildInfoSym &BuildInfo) {
+  printTypeIndex("BuildId", BuildInfo.BuildId);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           CallSiteInfoSym &CallSiteInfo) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset",
+                                     CallSiteInfo.getRelocationOffset(),
+                                     CallSiteInfo.CodeOffset, &LinkageName);
+  }
+  W.printHex("Segment", CallSiteInfo.Segment);
+  printTypeIndex("Type", CallSiteInfo.Type);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           EnvBlockSym &EnvBlock) {
+  ListScope L(W, "Entries");
+  for (auto Entry : EnvBlock.Fields) {
+    W.printString(Entry);
+  }
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FileStaticSym &FileStatic) {
+  printTypeIndex("Index", FileStatic.Index);
+  W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
+  W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
+  W.printString("Name", FileStatic.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+  W.printNumber("Ordinal", Export.Ordinal);
+  W.printFlags("Flags", uint16_t(Export.Flags), getExportSymFlagNames());
+  W.printString("Name", Export.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile2Sym &Compile2) {
+  W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames());
+  W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames());
+  W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
+  CompilationCPUType = Compile2.Machine;
+  std::string FrontendVersion;
+  {
+    raw_string_ostream Out(FrontendVersion);
+    Out << Compile2.VersionFrontendMajor << '.' << Compile2.VersionFrontendMinor
+        << '.' << Compile2.VersionFrontendBuild;
+  }
+  std::string BackendVersion;
+  {
+    raw_string_ostream Out(BackendVersion);
+    Out << Compile2.VersionBackendMajor << '.' << Compile2.VersionBackendMinor
+        << '.' << Compile2.VersionBackendBuild;
+  }
+  W.printString("FrontendVersion", FrontendVersion);
+  W.printString("BackendVersion", BackendVersion);
+  W.printString("VersionName", Compile2.Version);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile3Sym &Compile3) {
+  W.printEnum("Language", uint8_t(Compile3.getLanguage()), getSourceLanguageNames());
+  W.printFlags("Flags", uint32_t(Compile3.getFlags()),
+               getCompileSym3FlagNames());
+  W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
+  CompilationCPUType = Compile3.Machine;
+  std::string FrontendVersion;
+  {
+    raw_string_ostream Out(FrontendVersion);
+    Out << Compile3.VersionFrontendMajor << '.' << Compile3.VersionFrontendMinor
+        << '.' << Compile3.VersionFrontendBuild << '.'
+        << Compile3.VersionFrontendQFE;
+  }
+  std::string BackendVersion;
+  {
+    raw_string_ostream Out(BackendVersion);
+    Out << Compile3.VersionBackendMajor << '.' << Compile3.VersionBackendMinor
+        << '.' << Compile3.VersionBackendBuild << '.'
+        << Compile3.VersionBackendQFE;
+  }
+  W.printString("FrontendVersion", FrontendVersion);
+  W.printString("BackendVersion", BackendVersion);
+  W.printString("VersionName", Compile3.Version);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ConstantSym &Constant) {
+  printTypeIndex("Type", Constant.Type);
+  W.printNumber("Value", Constant.Value);
+  W.printString("Name", Constant.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
+                                     Data.DataOffset, &LinkageName);
+  }
+  printTypeIndex("Type", Data.Type);
+  W.printString("DisplayName", Data.Name);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR,
+    DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
+  W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+  W.printNumber("Offset", DefRangeFramePointerRel.Offset);
+  printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
+                              DefRangeFramePointerRel.getRelocationOffset());
+  printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+  W.printEnum("BaseRegister", uint16_t(DefRangeRegisterRel.Hdr.Register),
+              getRegisterNames());
+  W.printBoolean("HasSpilledUDTMember",
+                 DefRangeRegisterRel.hasSpilledUDTMember());
+  W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
+  W.printNumber("BasePointerOffset", DefRangeRegisterRel.Hdr.BasePointerOffset);
+  printLocalVariableAddrRange(DefRangeRegisterRel.Range,
+                              DefRangeRegisterRel.getRelocationOffset());
+  printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+  W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register),
+              getRegisterNames());
+  W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
+  printLocalVariableAddrRange(DefRangeRegister.Range,
+                              DefRangeRegister.getRelocationOffset());
+  printLocalVariableAddrGap(DefRangeRegister.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+  W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register),
+              getRegisterNames());
+  W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
+  W.printNumber("OffsetInParent", DefRangeSubfieldRegister.Hdr.OffsetInParent);
+  printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
+                              DefRangeSubfieldRegister.getRelocationOffset());
+  printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
+  if (ObjDelegate) {
+    DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
+    auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);
+    if (!ExpectedProgram) {
+      consumeError(ExpectedProgram.takeError());
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
+    }
+    W.printString("Program", *ExpectedProgram);
+  }
+  W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
+  printLocalVariableAddrRange(DefRangeSubfield.Range,
+                              DefRangeSubfield.getRelocationOffset());
+  printLocalVariableAddrGap(DefRangeSubfield.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           DefRangeSym &DefRange) {
+  if (ObjDelegate) {
+    DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
+    auto ExpectedProgram = Strings.getString(DefRange.Program);
+    if (!ExpectedProgram) {
+      consumeError(ExpectedProgram.takeError());
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
+    }
+    W.printString("Program", *ExpectedProgram);
+  }
+  printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
+  printLocalVariableAddrGap(DefRange.Gaps);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FrameCookieSym &FrameCookie) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset",
+                                     FrameCookie.getRelocationOffset(),
+                                     FrameCookie.CodeOffset, &LinkageName);
+  }
+  W.printEnum("Register", uint16_t(FrameCookie.Register), getRegisterNames());
+  W.printEnum("CookieKind", uint16_t(FrameCookie.CookieKind),
+              getFrameCookieKindNames());
+  W.printHex("Flags", FrameCookie.Flags);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FrameProcSym &FrameProc) {
+  W.printHex("TotalFrameBytes", FrameProc.TotalFrameBytes);
+  W.printHex("PaddingFrameBytes", FrameProc.PaddingFrameBytes);
+  W.printHex("OffsetToPadding", FrameProc.OffsetToPadding);
+  W.printHex("BytesOfCalleeSavedRegisters",
+             FrameProc.BytesOfCalleeSavedRegisters);
+  W.printHex("OffsetOfExceptionHandler", FrameProc.OffsetOfExceptionHandler);
+  W.printHex("SectionIdOfExceptionHandler",
+             FrameProc.SectionIdOfExceptionHandler);
+  W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags),
+               getFrameProcSymFlagNames());
+  W.printEnum("LocalFramePtrReg",
+              uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)),
+              getRegisterNames());
+  W.printEnum("ParamFramePtrReg",
+              uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)),
+              getRegisterNames());
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset",
+                                     HeapAllocSite.getRelocationOffset(),
+                                     HeapAllocSite.CodeOffset, &LinkageName);
+  }
+  W.printHex("Segment", HeapAllocSite.Segment);
+  W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
+  printTypeIndex("Type", HeapAllocSite.Type);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           InlineSiteSym &InlineSite) {
+  W.printHex("PtrParent", InlineSite.Parent);
+  W.printHex("PtrEnd", InlineSite.End);
+  printTypeIndex("Inlinee", InlineSite.Inlinee);
+
+  ListScope BinaryAnnotations(W, "BinaryAnnotations");
+  for (auto &Annotation : InlineSite.annotations()) {
+    switch (Annotation.OpCode) {
+    case BinaryAnnotationsOpCode::Invalid:
+      W.printString("(Annotation Padding)");
+      break;
+    case BinaryAnnotationsOpCode::CodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeOffset:
+    case BinaryAnnotationsOpCode::ChangeCodeLength:
+      W.printHex(Annotation.Name, Annotation.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
+    case BinaryAnnotationsOpCode::ChangeLineEndDelta:
+    case BinaryAnnotationsOpCode::ChangeRangeKind:
+    case BinaryAnnotationsOpCode::ChangeColumnStart:
+    case BinaryAnnotationsOpCode::ChangeColumnEnd:
+      W.printNumber(Annotation.Name, Annotation.U1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeLineOffset:
+    case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
+      W.printNumber(Annotation.Name, Annotation.S1);
+      break;
+    case BinaryAnnotationsOpCode::ChangeFile:
+      if (ObjDelegate) {
+        W.printHex("ChangeFile",
+                   ObjDelegate->getFileNameForFileOffset(Annotation.U1),
+                   Annotation.U1);
+      } else {
+        W.printHex("ChangeFile", Annotation.U1);
+      }
+
+      break;
+    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
+      W.startLine() << "ChangeCodeOffsetAndLineOffset: {CodeOffset: "
+                    << W.hex(Annotation.U1) << ", LineOffset: " << Annotation.S1
+                    << "}\n";
+      break;
+    }
+    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
+      W.startLine() << "ChangeCodeLengthAndCodeOffset: {CodeOffset: "
+                    << W.hex(Annotation.U2)
+                    << ", Length: " << W.hex(Annotation.U1) << "}\n";
+      break;
+    }
+    }
+  }
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegisterSym &Register) {
+  printTypeIndex("Type", Register.Index);
+  W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
+  W.printString("Name", Register.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
+  W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames());
+  W.printNumber("Seg", Public.Segment);
+  W.printNumber("Off", Public.Offset);
+  W.printString("Name", Public.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
+  W.printNumber("SumName", ProcRef.SumName);
+  W.printNumber("SymOffset", ProcRef.SymOffset);
+  W.printNumber("Mod", ProcRef.Module);
+  W.printString("Name", ProcRef.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset", Label.getRelocationOffset(),
+                                     Label.CodeOffset, &LinkageName);
+  }
+  W.printHex("Segment", Label.Segment);
+  W.printHex("Flags", uint8_t(Label.Flags));
+  W.printFlags("Flags", uint8_t(Label.Flags), getProcSymFlagNames());
+  W.printString("DisplayName", Label.Name);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+  printTypeIndex("Type", Local.Type);
+  W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
+  W.printString("VarName", Local.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
+  W.printHex("Signature", ObjName.Signature);
+  W.printString("ObjectName", ObjName.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+  if (InFunctionScope)
+    return llvm::make_error<CodeViewError>(
+        "Visiting a ProcSym while inside function scope!");
+
+  InFunctionScope = true;
+
+  StringRef LinkageName;
+  W.printHex("PtrParent", Proc.Parent);
+  W.printHex("PtrEnd", Proc.End);
+  W.printHex("PtrNext", Proc.Next);
+  W.printHex("CodeSize", Proc.CodeSize);
+  W.printHex("DbgStart", Proc.DbgStart);
+  W.printHex("DbgEnd", Proc.DbgEnd);
+  printTypeIndex("FunctionType", Proc.FunctionType);
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
+                                     Proc.CodeOffset, &LinkageName);
+  }
+  W.printHex("Segment", Proc.Segment);
+  W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
+               getProcSymFlagNames());
+  W.printString("DisplayName", Proc.Name);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ScopeEndSym &ScopeEnd) {
+  InFunctionScope = false;
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+  ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
+  for (auto FuncID : Caller.Indices)
+    printTypeIndex("FuncID", FuncID);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegRelativeSym &RegRel) {
+  W.printHex("Offset", RegRel.Offset);
+  printTypeIndex("Type", RegRel.Type);
+  W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames());
+  W.printString("VarName", RegRel.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ThreadLocalDataSym &Data) {
+  StringRef LinkageName;
+  if (ObjDelegate) {
+    ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
+                                     Data.DataOffset, &LinkageName);
+  }
+  printTypeIndex("Type", Data.Type);
+  W.printString("DisplayName", Data.Name);
+  if (!LinkageName.empty())
+    W.printString("LinkageName", LinkageName);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+  printTypeIndex("Type", UDT.Type);
+  W.printString("UDTName", UDT.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           UsingNamespaceSym &UN) {
+  W.printString("Namespace", UN.Name);
+  return Error::success();
+}
+
+Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
+  W.printNumber("Length", CVR.length());
+  return Error::success();
+}
+
+Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
+  CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType,
+                            PrintRecordBytes);
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  auto Err = Visitor.visitSymbolRecord(Record);
+  CompilationCPUType = Dumper.getCompilationCPUType();
+  return Err;
+}
+
+Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get(), Container);
+  CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType,
+                            PrintRecordBytes);
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  auto Err = Visitor.visitSymbolStream(Symbols);
+  CompilationCPUType = Dumper.getCompilationCPUType();
+  return Err;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
new file mode 100644
index 0000000..0174613
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
@@ -0,0 +1,94 @@
+//===- SymbolRecordHelpers.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
+  RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
+  cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
+  return record;
+}
+
+uint32_t llvm::codeview::getScopeEndOffset(const CVSymbol &Sym) {
+  assert(symbolOpensScope(Sym.kind()));
+  switch (Sym.kind()) {
+  case SymbolKind::S_GPROC32:
+  case SymbolKind::S_LPROC32:
+  case SymbolKind::S_GPROC32_ID:
+  case SymbolKind::S_LPROC32_ID:
+  case SymbolKind::S_LPROC32_DPC:
+  case SymbolKind::S_LPROC32_DPC_ID: {
+    ProcSym Proc = createRecord<ProcSym>(Sym);
+    return Proc.End;
+  }
+  case SymbolKind::S_BLOCK32: {
+    BlockSym Block = createRecord<BlockSym>(Sym);
+    return Block.End;
+  }
+  case SymbolKind::S_THUNK32: {
+    Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym);
+    return Thunk.End;
+  }
+  case SymbolKind::S_INLINESITE: {
+    InlineSiteSym Site = createRecord<InlineSiteSym>(Sym);
+    return Site.End;
+  }
+  default:
+    assert(false && "Unknown record type");
+    return 0;
+  }
+}
+
+uint32_t
+llvm::codeview::getScopeParentOffset(const llvm::codeview::CVSymbol &Sym) {
+  assert(symbolOpensScope(Sym.kind()));
+  switch (Sym.kind()) {
+  case SymbolKind::S_GPROC32:
+  case SymbolKind::S_LPROC32:
+  case SymbolKind::S_GPROC32_ID:
+  case SymbolKind::S_LPROC32_ID:
+  case SymbolKind::S_LPROC32_DPC:
+  case SymbolKind::S_LPROC32_DPC_ID: {
+    ProcSym Proc = createRecord<ProcSym>(Sym);
+    return Proc.Parent;
+  }
+  case SymbolKind::S_BLOCK32: {
+    BlockSym Block = createRecord<BlockSym>(Sym);
+    return Block.Parent;
+  }
+  case SymbolKind::S_THUNK32: {
+    Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym);
+    return Thunk.Parent;
+  }
+  case SymbolKind::S_INLINESITE: {
+    InlineSiteSym Site = createRecord<InlineSiteSym>(Sym);
+    return Site.Parent;
+  }
+  default:
+    assert(false && "Unknown record type");
+    return 0;
+  }
+}
+
+CVSymbolArray
+llvm::codeview::limitSymbolArrayToScope(const CVSymbolArray &Symbols,
+                                        uint32_t ScopeBegin) {
+  CVSymbol Opener = *Symbols.at(ScopeBegin);
+  assert(symbolOpensScope(Opener.kind()));
+  uint32_t EndOffset = getScopeEndOffset(Opener);
+  CVSymbol Closer = *Symbols.at(EndOffset);
+  EndOffset += Closer.RecordData.size();
+  return Symbols.substream(ScopeBegin, EndOffset);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
new file mode 100644
index 0000000..2af8205c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
@@ -0,0 +1,547 @@
+//===- SymbolRecordMapping.cpp -----------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X)                                                               \
+  if (auto EC = X)                                                             \
+    return EC;
+
+namespace {
+struct MapGap {
+  Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const {
+    error(IO.mapInteger(Gap.GapStartOffset));
+    error(IO.mapInteger(Gap.Range));
+    return Error::success();
+  }
+};
+}
+
+static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO,
+                                       LocalVariableAddrRange &Range) {
+  error(IO.mapInteger(Range.OffsetStart));
+  error(IO.mapInteger(Range.ISectStart));
+  error(IO.mapInteger(Range.Range));
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) {
+  error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix)));
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) {
+  error(IO.padToAlignment(alignOf(Container)));
+  error(IO.endRecord());
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+
+  error(IO.mapInteger(Block.Parent));
+  error(IO.mapInteger(Block.End));
+  error(IO.mapInteger(Block.CodeSize));
+  error(IO.mapInteger(Block.CodeOffset));
+  error(IO.mapInteger(Block.Segment));
+  error(IO.mapStringZ(Block.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+
+  error(IO.mapInteger(Thunk.Parent));
+  error(IO.mapInteger(Thunk.End));
+  error(IO.mapInteger(Thunk.Next));
+  error(IO.mapInteger(Thunk.Offset));
+  error(IO.mapInteger(Thunk.Segment));
+  error(IO.mapInteger(Thunk.Length));
+  error(IO.mapEnum(Thunk.Thunk));
+  error(IO.mapStringZ(Thunk.Name));
+  error(IO.mapByteVectorTail(Thunk.VariantData));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            TrampolineSym &Tramp) {
+
+  error(IO.mapEnum(Tramp.Type));
+  error(IO.mapInteger(Tramp.Size));
+  error(IO.mapInteger(Tramp.ThunkOffset));
+  error(IO.mapInteger(Tramp.TargetOffset));
+  error(IO.mapInteger(Tramp.ThunkSection));
+  error(IO.mapInteger(Tramp.TargetSection));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            SectionSym &Section) {
+  uint8_t Padding = 0;
+
+  error(IO.mapInteger(Section.SectionNumber));
+  error(IO.mapInteger(Section.Alignment));
+  error(IO.mapInteger(Padding));
+  error(IO.mapInteger(Section.Rva));
+  error(IO.mapInteger(Section.Length));
+  error(IO.mapInteger(Section.Characteristics));
+  error(IO.mapStringZ(Section.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            CoffGroupSym &CoffGroup) {
+
+  error(IO.mapInteger(CoffGroup.Size));
+  error(IO.mapInteger(CoffGroup.Characteristics));
+  error(IO.mapInteger(CoffGroup.Offset));
+  error(IO.mapInteger(CoffGroup.Segment));
+  error(IO.mapStringZ(CoffGroup.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            BPRelativeSym &BPRel) {
+
+  error(IO.mapInteger(BPRel.Offset));
+  error(IO.mapInteger(BPRel.Type));
+  error(IO.mapStringZ(BPRel.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            BuildInfoSym &BuildInfo) {
+
+  error(IO.mapInteger(BuildInfo.BuildId));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            CallSiteInfoSym &CallSiteInfo) {
+  uint16_t Padding = 0;
+
+  error(IO.mapInteger(CallSiteInfo.CodeOffset));
+  error(IO.mapInteger(CallSiteInfo.Segment));
+  error(IO.mapInteger(Padding));
+  error(IO.mapInteger(CallSiteInfo.Type));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            EnvBlockSym &EnvBlock) {
+
+  uint8_t Reserved = 0;
+  error(IO.mapInteger(Reserved));
+  error(IO.mapStringZVectorZ(EnvBlock.Fields));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            FileStaticSym &FileStatic) {
+
+  error(IO.mapInteger(FileStatic.Index));
+  error(IO.mapInteger(FileStatic.ModFilenameOffset));
+  error(IO.mapEnum(FileStatic.Flags));
+  error(IO.mapStringZ(FileStatic.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+
+  error(IO.mapInteger(Export.Ordinal));
+  error(IO.mapEnum(Export.Flags));
+  error(IO.mapStringZ(Export.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            Compile2Sym &Compile2) {
+
+  error(IO.mapEnum(Compile2.Flags));
+  error(IO.mapEnum(Compile2.Machine));
+  error(IO.mapInteger(Compile2.VersionFrontendMajor));
+  error(IO.mapInteger(Compile2.VersionFrontendMinor));
+  error(IO.mapInteger(Compile2.VersionFrontendBuild));
+  error(IO.mapInteger(Compile2.VersionBackendMajor));
+  error(IO.mapInteger(Compile2.VersionBackendMinor));
+  error(IO.mapInteger(Compile2.VersionBackendBuild));
+  error(IO.mapStringZ(Compile2.Version));
+  error(IO.mapStringZVectorZ(Compile2.ExtraStrings));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            Compile3Sym &Compile3) {
+
+  error(IO.mapEnum(Compile3.Flags));
+  error(IO.mapEnum(Compile3.Machine));
+  error(IO.mapInteger(Compile3.VersionFrontendMajor));
+  error(IO.mapInteger(Compile3.VersionFrontendMinor));
+  error(IO.mapInteger(Compile3.VersionFrontendBuild));
+  error(IO.mapInteger(Compile3.VersionFrontendQFE));
+  error(IO.mapInteger(Compile3.VersionBackendMajor));
+  error(IO.mapInteger(Compile3.VersionBackendMinor));
+  error(IO.mapInteger(Compile3.VersionBackendBuild));
+  error(IO.mapInteger(Compile3.VersionBackendQFE));
+  error(IO.mapStringZ(Compile3.Version));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            ConstantSym &Constant) {
+
+  error(IO.mapInteger(Constant.Type));
+  error(IO.mapEncodedInteger(Constant.Value));
+  error(IO.mapStringZ(Constant.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+
+  error(IO.mapInteger(Data.Type));
+  error(IO.mapInteger(Data.DataOffset));
+  error(IO.mapInteger(Data.Segment));
+  error(IO.mapStringZ(Data.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+
+  error(IO.mapInteger(DefRangeFramePointerRel.Offset));
+  error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range));
+  error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR,
+    DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
+
+  error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+
+  error(IO.mapObject(DefRangeRegisterRel.Hdr.Register));
+  error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags));
+  error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset));
+  error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range));
+  error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+
+  error(IO.mapObject(DefRangeRegister.Hdr.Register));
+  error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName));
+  error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range));
+  error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+
+  error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register));
+  error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName));
+  error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent));
+  error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range));
+  error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
+
+  error(IO.mapInteger(DefRangeSubfield.Program));
+  error(IO.mapInteger(DefRangeSubfield.OffsetInParent));
+  error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range));
+  error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            DefRangeSym &DefRange) {
+
+  error(IO.mapInteger(DefRange.Program));
+  error(mapLocalVariableAddrRange(IO, DefRange.Range));
+  error(IO.mapVectorTail(DefRange.Gaps, MapGap()));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            FrameCookieSym &FrameCookie) {
+
+  error(IO.mapInteger(FrameCookie.CodeOffset));
+  error(IO.mapInteger(FrameCookie.Register));
+  error(IO.mapEnum(FrameCookie.CookieKind));
+  error(IO.mapInteger(FrameCookie.Flags));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            FrameProcSym &FrameProc) {
+  error(IO.mapInteger(FrameProc.TotalFrameBytes));
+  error(IO.mapInteger(FrameProc.PaddingFrameBytes));
+  error(IO.mapInteger(FrameProc.OffsetToPadding));
+  error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters));
+  error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler));
+  error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler));
+  error(IO.mapEnum(FrameProc.Flags));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(
+    CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
+
+  error(IO.mapInteger(HeapAllocSite.CodeOffset));
+  error(IO.mapInteger(HeapAllocSite.Segment));
+  error(IO.mapInteger(HeapAllocSite.CallInstructionSize));
+  error(IO.mapInteger(HeapAllocSite.Type));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            InlineSiteSym &InlineSite) {
+
+  error(IO.mapInteger(InlineSite.Parent));
+  error(IO.mapInteger(InlineSite.End));
+  error(IO.mapInteger(InlineSite.Inlinee));
+  error(IO.mapByteVectorTail(InlineSite.AnnotationData));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            RegisterSym &Register) {
+
+  error(IO.mapInteger(Register.Index));
+  error(IO.mapEnum(Register.Register));
+  error(IO.mapStringZ(Register.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            PublicSym32 &Public) {
+
+  error(IO.mapEnum(Public.Flags));
+  error(IO.mapInteger(Public.Offset));
+  error(IO.mapInteger(Public.Segment));
+  error(IO.mapStringZ(Public.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            ProcRefSym &ProcRef) {
+
+  error(IO.mapInteger(ProcRef.SumName));
+  error(IO.mapInteger(ProcRef.SymOffset));
+  error(IO.mapInteger(ProcRef.Module));
+  error(IO.mapStringZ(ProcRef.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+
+  error(IO.mapInteger(Label.CodeOffset));
+  error(IO.mapInteger(Label.Segment));
+  error(IO.mapEnum(Label.Flags));
+  error(IO.mapStringZ(Label.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+  error(IO.mapInteger(Local.Type));
+  error(IO.mapEnum(Local.Flags));
+  error(IO.mapStringZ(Local.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            ObjNameSym &ObjName) {
+
+  error(IO.mapInteger(ObjName.Signature));
+  error(IO.mapStringZ(ObjName.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+  error(IO.mapInteger(Proc.Parent));
+  error(IO.mapInteger(Proc.End));
+  error(IO.mapInteger(Proc.Next));
+  error(IO.mapInteger(Proc.CodeSize));
+  error(IO.mapInteger(Proc.DbgStart));
+  error(IO.mapInteger(Proc.DbgEnd));
+  error(IO.mapInteger(Proc.FunctionType));
+  error(IO.mapInteger(Proc.CodeOffset));
+  error(IO.mapInteger(Proc.Segment));
+  error(IO.mapEnum(Proc.Flags));
+  error(IO.mapStringZ(Proc.Name));
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            ScopeEndSym &ScopeEnd) {
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+  error(IO.mapVectorN<uint32_t>(
+      Caller.Indices,
+      [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            RegRelativeSym &RegRel) {
+
+  error(IO.mapInteger(RegRel.Offset));
+  error(IO.mapInteger(RegRel.Type));
+  error(IO.mapEnum(RegRel.Register));
+  error(IO.mapStringZ(RegRel.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            ThreadLocalDataSym &Data) {
+
+  error(IO.mapInteger(Data.Type));
+  error(IO.mapInteger(Data.DataOffset));
+  error(IO.mapInteger(Data.Segment));
+  error(IO.mapStringZ(Data.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+
+  error(IO.mapInteger(UDT.Type));
+  error(IO.mapStringZ(UDT.Name));
+
+  return Error::success();
+}
+
+Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
+                                            UsingNamespaceSym &UN) {
+
+  error(IO.mapStringZ(UN.Name));
+
+  return Error::success();
+}
+
+RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg,
+                                       CPUType CPU) {
+  assert(unsigned(EncodedReg) < 4);
+  switch (CPU) {
+  // FIXME: Add ARM and AArch64 variants here.
+  default:
+    break;
+  case CPUType::Intel8080:
+  case CPUType::Intel8086:
+  case CPUType::Intel80286:
+  case CPUType::Intel80386:
+  case CPUType::Intel80486:
+  case CPUType::Pentium:
+  case CPUType::PentiumPro:
+  case CPUType::Pentium3:
+    switch (EncodedReg) {
+    case EncodedFramePtrReg::None:     return RegisterId::NONE;
+    case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME;
+    case EncodedFramePtrReg::FramePtr: return RegisterId::EBP;
+    case EncodedFramePtrReg::BasePtr:  return RegisterId::EBX;
+    }
+    llvm_unreachable("bad encoding");
+  case CPUType::X64:
+    switch (EncodedReg) {
+    case EncodedFramePtrReg::None:     return RegisterId::NONE;
+    case EncodedFramePtrReg::StackPtr: return RegisterId::RSP;
+    case EncodedFramePtrReg::FramePtr: return RegisterId::RBP;
+    case EncodedFramePtrReg::BasePtr:  return RegisterId::R13;
+    }
+    llvm_unreachable("bad encoding");
+  }
+  return RegisterId::NONE;
+}
+
+EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) {
+  switch (CPU) {
+  // FIXME: Add ARM and AArch64 variants here.
+  default:
+    break;
+  case CPUType::Intel8080:
+  case CPUType::Intel8086:
+  case CPUType::Intel80286:
+  case CPUType::Intel80386:
+  case CPUType::Intel80486:
+  case CPUType::Pentium:
+  case CPUType::PentiumPro:
+  case CPUType::Pentium3:
+    switch (Reg) {
+    case RegisterId::VFRAME:
+      return EncodedFramePtrReg::StackPtr;
+    case RegisterId::EBP:
+      return EncodedFramePtrReg::FramePtr;
+    case RegisterId::EBX:
+      return EncodedFramePtrReg::BasePtr;
+    default:
+      break;
+    }
+    break;
+  case CPUType::X64:
+    switch (Reg) {
+    case RegisterId::RSP:
+      return EncodedFramePtrReg::StackPtr;
+    case RegisterId::RBP:
+      return EncodedFramePtrReg::FramePtr;
+    case RegisterId::R13:
+      return EncodedFramePtrReg::BasePtr;
+    default:
+      break;
+    }
+    break;
+  }
+  return EncodedFramePtrReg::None;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp
new file mode 100644
index 0000000..0071ecc
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp
@@ -0,0 +1,60 @@
+//===- SymbolSerializer.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+SymbolSerializer::SymbolSerializer(BumpPtrAllocator &Allocator,
+                                   CodeViewContainer Container)
+    : Storage(Allocator), Stream(RecordBuffer, support::little), Writer(Stream),
+      Mapping(Writer, Container) {}
+
+Error SymbolSerializer::visitSymbolBegin(CVSymbol &Record) {
+  assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!");
+
+  Writer.setOffset(0);
+
+  if (auto EC = writeRecordPrefix(Record.kind()))
+    return EC;
+
+  CurrentSymbol = Record.kind();
+  if (auto EC = Mapping.visitSymbolBegin(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error SymbolSerializer::visitSymbolEnd(CVSymbol &Record) {
+  assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!");
+
+  if (auto EC = Mapping.visitSymbolEnd(Record))
+    return EC;
+
+  uint32_t RecordEnd = Writer.getOffset();
+  uint16_t Length = RecordEnd - 2;
+  Writer.setOffset(0);
+  if (auto EC = Writer.writeInteger(Length))
+    return EC;
+
+  uint8_t *StableStorage = Storage.Allocate<uint8_t>(RecordEnd);
+  ::memcpy(StableStorage, &RecordBuffer[0], RecordEnd);
+  Record.RecordData = ArrayRef<uint8_t>(StableStorage, RecordEnd);
+  CurrentSymbol.reset();
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
new file mode 100644
index 0000000..f5d3bea
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -0,0 +1,571 @@
+//===-- TypeDumpVisitor.cpp - CodeView type info dumper ----------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
+#define CV_TYPE(enum, val) {#enum, enum},
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+};
+
+#define ENUM_ENTRY(enum_class, enum)                                           \
+  { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
+
+static const EnumEntry<uint16_t> ClassOptionNames[] = {
+    ENUM_ENTRY(ClassOptions, Packed),
+    ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor),
+    ENUM_ENTRY(ClassOptions, HasOverloadedOperator),
+    ENUM_ENTRY(ClassOptions, Nested),
+    ENUM_ENTRY(ClassOptions, ContainsNestedClass),
+    ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator),
+    ENUM_ENTRY(ClassOptions, HasConversionOperator),
+    ENUM_ENTRY(ClassOptions, ForwardReference),
+    ENUM_ENTRY(ClassOptions, Scoped),
+    ENUM_ENTRY(ClassOptions, HasUniqueName),
+    ENUM_ENTRY(ClassOptions, Sealed),
+    ENUM_ENTRY(ClassOptions, Intrinsic),
+};
+
+static const EnumEntry<uint8_t> MemberAccessNames[] = {
+    ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
+    ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
+};
+
+static const EnumEntry<uint16_t> MethodOptionNames[] = {
+    ENUM_ENTRY(MethodOptions, Pseudo),
+    ENUM_ENTRY(MethodOptions, NoInherit),
+    ENUM_ENTRY(MethodOptions, NoConstruct),
+    ENUM_ENTRY(MethodOptions, CompilerGenerated),
+    ENUM_ENTRY(MethodOptions, Sealed),
+};
+
+static const EnumEntry<uint16_t> MemberKindNames[] = {
+    ENUM_ENTRY(MethodKind, Vanilla),
+    ENUM_ENTRY(MethodKind, Virtual),
+    ENUM_ENTRY(MethodKind, Static),
+    ENUM_ENTRY(MethodKind, Friend),
+    ENUM_ENTRY(MethodKind, IntroducingVirtual),
+    ENUM_ENTRY(MethodKind, PureVirtual),
+    ENUM_ENTRY(MethodKind, PureIntroducingVirtual),
+};
+
+static const EnumEntry<uint8_t> PtrKindNames[] = {
+    ENUM_ENTRY(PointerKind, Near16),
+    ENUM_ENTRY(PointerKind, Far16),
+    ENUM_ENTRY(PointerKind, Huge16),
+    ENUM_ENTRY(PointerKind, BasedOnSegment),
+    ENUM_ENTRY(PointerKind, BasedOnValue),
+    ENUM_ENTRY(PointerKind, BasedOnSegmentValue),
+    ENUM_ENTRY(PointerKind, BasedOnAddress),
+    ENUM_ENTRY(PointerKind, BasedOnSegmentAddress),
+    ENUM_ENTRY(PointerKind, BasedOnType),
+    ENUM_ENTRY(PointerKind, BasedOnSelf),
+    ENUM_ENTRY(PointerKind, Near32),
+    ENUM_ENTRY(PointerKind, Far32),
+    ENUM_ENTRY(PointerKind, Near64),
+};
+
+static const EnumEntry<uint8_t> PtrModeNames[] = {
+    ENUM_ENTRY(PointerMode, Pointer),
+    ENUM_ENTRY(PointerMode, LValueReference),
+    ENUM_ENTRY(PointerMode, PointerToDataMember),
+    ENUM_ENTRY(PointerMode, PointerToMemberFunction),
+    ENUM_ENTRY(PointerMode, RValueReference),
+};
+
+static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
+    ENUM_ENTRY(PointerToMemberRepresentation, Unknown),
+    ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData),
+    ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData),
+    ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData),
+    ENUM_ENTRY(PointerToMemberRepresentation, GeneralData),
+    ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction),
+    ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction),
+    ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction),
+    ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction),
+};
+
+static const EnumEntry<uint16_t> TypeModifierNames[] = {
+    ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
+    ENUM_ENTRY(ModifierOptions, Unaligned),
+};
+
+static const EnumEntry<uint8_t> CallingConventions[] = {
+    ENUM_ENTRY(CallingConvention, NearC),
+    ENUM_ENTRY(CallingConvention, FarC),
+    ENUM_ENTRY(CallingConvention, NearPascal),
+    ENUM_ENTRY(CallingConvention, FarPascal),
+    ENUM_ENTRY(CallingConvention, NearFast),
+    ENUM_ENTRY(CallingConvention, FarFast),
+    ENUM_ENTRY(CallingConvention, NearStdCall),
+    ENUM_ENTRY(CallingConvention, FarStdCall),
+    ENUM_ENTRY(CallingConvention, NearSysCall),
+    ENUM_ENTRY(CallingConvention, FarSysCall),
+    ENUM_ENTRY(CallingConvention, ThisCall),
+    ENUM_ENTRY(CallingConvention, MipsCall),
+    ENUM_ENTRY(CallingConvention, Generic),
+    ENUM_ENTRY(CallingConvention, AlphaCall),
+    ENUM_ENTRY(CallingConvention, PpcCall),
+    ENUM_ENTRY(CallingConvention, SHCall),
+    ENUM_ENTRY(CallingConvention, ArmCall),
+    ENUM_ENTRY(CallingConvention, AM33Call),
+    ENUM_ENTRY(CallingConvention, TriCall),
+    ENUM_ENTRY(CallingConvention, SH5Call),
+    ENUM_ENTRY(CallingConvention, M32RCall),
+    ENUM_ENTRY(CallingConvention, ClrCall),
+    ENUM_ENTRY(CallingConvention, Inline),
+    ENUM_ENTRY(CallingConvention, NearVector),
+};
+
+static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
+    ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
+    ENUM_ENTRY(FunctionOptions, Constructor),
+    ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
+};
+
+static const EnumEntry<uint16_t> LabelTypeEnum[] = {
+    ENUM_ENTRY(LabelType, Near), ENUM_ENTRY(LabelType, Far),
+};
+
+#undef ENUM_ENTRY
+
+static StringRef getLeafTypeName(TypeLeafKind LT) {
+  switch (LT) {
+#define TYPE_RECORD(ename, value, name)                                        \
+  case ename:                                                                  \
+    return #name;
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+  default:
+    break;
+  }
+  return "UnknownLeaf";
+}
+
+void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
+  codeview::printTypeIndex(*W, FieldName, TI, TpiTypes);
+}
+
+void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const {
+  codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes());
+}
+
+Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
+  return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size()));
+}
+
+Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
+  W->startLine() << getLeafTypeName(Record.Type);
+  W->getOStream() << " (" << HexNumber(Index.getIndex()) << ")";
+  W->getOStream() << " {\n";
+  W->indent();
+  W->printEnum("TypeLeafKind", unsigned(Record.Type),
+               makeArrayRef(LeafTypeNames));
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitTypeEnd(CVType &Record) {
+  if (PrintRecordBytes)
+    W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
+
+  W->unindent();
+  W->startLine() << "}\n";
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+  W->startLine() << getLeafTypeName(Record.Kind);
+  W->getOStream() << " {\n";
+  W->indent();
+  W->printEnum("TypeLeafKind", unsigned(Record.Kind),
+               makeArrayRef(LeafTypeNames));
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
+  if (PrintRecordBytes)
+    W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
+
+  W->unindent();
+  W->startLine() << "}\n";
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        FieldListRecord &FieldList) {
+  if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
+    return EC;
+
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) {
+  printItemIndex("Id", String.getId());
+  W->printString("StringData", String.getString());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
+  auto Indices = Args.getIndices();
+  uint32_t Size = Indices.size();
+  W->printNumber("NumArgs", Size);
+  ListScope Arguments(*W, "Arguments");
+  for (uint32_t I = 0; I < Size; ++I) {
+    printTypeIndex("ArgType", Indices[I]);
+  }
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) {
+  auto Indices = Strs.getIndices();
+  uint32_t Size = Indices.size();
+  W->printNumber("NumStrings", Size);
+  ListScope Arguments(*W, "Strings");
+  for (uint32_t I = 0; I < Size; ++I) {
+    printItemIndex("String", Indices[I]);
+  }
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
+  uint16_t Props = static_cast<uint16_t>(Class.getOptions());
+  W->printNumber("MemberCount", Class.getMemberCount());
+  W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+  printTypeIndex("FieldList", Class.getFieldList());
+  printTypeIndex("DerivedFrom", Class.getDerivationList());
+  printTypeIndex("VShape", Class.getVTableShape());
+  W->printNumber("SizeOf", Class.getSize());
+  W->printString("Name", Class.getName());
+  if (Props & uint16_t(ClassOptions::HasUniqueName))
+    W->printString("LinkageName", Class.getUniqueName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
+  uint16_t Props = static_cast<uint16_t>(Union.getOptions());
+  W->printNumber("MemberCount", Union.getMemberCount());
+  W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+  printTypeIndex("FieldList", Union.getFieldList());
+  W->printNumber("SizeOf", Union.getSize());
+  W->printString("Name", Union.getName());
+  if (Props & uint16_t(ClassOptions::HasUniqueName))
+    W->printString("LinkageName", Union.getUniqueName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+  uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
+  W->printNumber("NumEnumerators", Enum.getMemberCount());
+  W->printFlags("Properties", uint16_t(Enum.getOptions()),
+                makeArrayRef(ClassOptionNames));
+  printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
+  printTypeIndex("FieldListType", Enum.getFieldList());
+  W->printString("Name", Enum.getName());
+  if (Props & uint16_t(ClassOptions::HasUniqueName))
+    W->printString("LinkageName", Enum.getUniqueName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+  printTypeIndex("ElementType", AT.getElementType());
+  printTypeIndex("IndexType", AT.getIndexType());
+  W->printNumber("SizeOf", AT.getSize());
+  W->printString("Name", AT.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
+  printTypeIndex("CompleteClass", VFT.getCompleteClass());
+  printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
+  W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
+  W->printString("VFTableName", VFT.getName());
+  for (auto N : VFT.getMethodNames())
+    W->printString("MethodName", N);
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
+  printTypeIndex("ClassType", Id.getClassType());
+  printTypeIndex("FunctionType", Id.getFunctionType());
+  W->printString("Name", Id.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
+  printTypeIndex("ReturnType", Proc.getReturnType());
+  W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
+               makeArrayRef(CallingConventions));
+  W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
+                makeArrayRef(FunctionOptionEnum));
+  W->printNumber("NumParameters", Proc.getParameterCount());
+  printTypeIndex("ArgListType", Proc.getArgumentList());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
+  printTypeIndex("ReturnType", MF.getReturnType());
+  printTypeIndex("ClassType", MF.getClassType());
+  printTypeIndex("ThisType", MF.getThisType());
+  W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
+               makeArrayRef(CallingConventions));
+  W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
+                makeArrayRef(FunctionOptionEnum));
+  W->printNumber("NumParameters", MF.getParameterCount());
+  printTypeIndex("ArgListType", MF.getArgumentList());
+  W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        MethodOverloadListRecord &MethodList) {
+  for (auto &M : MethodList.getMethods()) {
+    ListScope S(*W, "Method");
+    printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
+    printTypeIndex("Type", M.getType());
+    if (M.isIntroducingVirtual())
+      W->printHex("VFTableOffset", M.getVFTableOffset());
+  }
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
+  printItemIndex("ParentScope", Func.getParentScope());
+  printTypeIndex("FunctionType", Func.getFunctionType());
+  W->printString("Name", Func.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
+  W->printString("Guid", formatv("{0}", TS.getGuid()).str());
+  W->printNumber("Age", TS.getAge());
+  W->printString("Name", TS.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
+  printTypeIndex("PointeeType", Ptr.getReferentType());
+  W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
+               makeArrayRef(PtrKindNames));
+  W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
+
+  W->printNumber("IsFlat", Ptr.isFlat());
+  W->printNumber("IsConst", Ptr.isConst());
+  W->printNumber("IsVolatile", Ptr.isVolatile());
+  W->printNumber("IsUnaligned", Ptr.isUnaligned());
+  W->printNumber("IsRestrict", Ptr.isRestrict());
+  W->printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr());
+  W->printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr());
+  W->printNumber("SizeOf", Ptr.getSize());
+
+  if (Ptr.isPointerToMember()) {
+    const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+    printTypeIndex("ClassType", MI.getContainingType());
+    W->printEnum("Representation", uint16_t(MI.getRepresentation()),
+                 makeArrayRef(PtrMemberRepNames));
+  }
+
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
+  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+  printTypeIndex("ModifiedType", Mod.getModifiedType());
+  W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
+
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
+  printTypeIndex("Type", BitField.getType());
+  W->printNumber("BitSize", BitField.getBitSize());
+  W->printNumber("BitOffset", BitField.getBitOffset());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        VFTableShapeRecord &Shape) {
+  W->printNumber("VFEntryCount", Shape.getEntryCount());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        UdtSourceLineRecord &Line) {
+  printTypeIndex("UDT", Line.getUDT());
+  printItemIndex("SourceFile", Line.getSourceFile());
+  W->printNumber("LineNumber", Line.getLineNumber());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        UdtModSourceLineRecord &Line) {
+  printTypeIndex("UDT", Line.getUDT());
+  printItemIndex("SourceFile", Line.getSourceFile());
+  W->printNumber("LineNumber", Line.getLineNumber());
+  W->printNumber("Module", Line.getModule());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
+  W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
+
+  ListScope Arguments(*W, "Arguments");
+  for (auto Arg : Args.getArgs()) {
+    printItemIndex("ArgType", Arg);
+  }
+  return Error::success();
+}
+
+void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
+  return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
+                               Attrs.getFlags());
+}
+
+void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
+                                            MethodKind Kind,
+                                            MethodOptions Options) {
+  W->printEnum("AccessSpecifier", uint8_t(Access),
+               makeArrayRef(MemberAccessNames));
+  // Data members will be vanilla. Don't try to print a method kind for them.
+  if (Kind != MethodKind::Vanilla)
+    W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
+  if (Options != MethodOptions::None) {
+    W->printFlags("MethodOptions", unsigned(Options),
+                  makeArrayRef(MethodOptionNames));
+  }
+}
+
+Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
+  W->printHex("UnknownMember", unsigned(Record.Kind));
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
+  W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
+  W->printNumber("Length", uint32_t(Record.content().size()));
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        NestedTypeRecord &Nested) {
+  printTypeIndex("Type", Nested.getNestedType());
+  W->printString("Name", Nested.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        OneMethodRecord &Method) {
+  MethodKind K = Method.getMethodKind();
+  printMemberAttributes(Method.getAccess(), K, Method.getOptions());
+  printTypeIndex("Type", Method.getType());
+  // If virtual, then read the vftable offset.
+  if (Method.isIntroducingVirtual())
+    W->printHex("VFTableOffset", Method.getVFTableOffset());
+  W->printString("Name", Method.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        OverloadedMethodRecord &Method) {
+  W->printHex("MethodCount", Method.getNumOverloads());
+  printTypeIndex("MethodListIndex", Method.getMethodList());
+  W->printString("Name", Method.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        DataMemberRecord &Field) {
+  printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+                        MethodOptions::None);
+  printTypeIndex("Type", Field.getType());
+  W->printHex("FieldOffset", Field.getFieldOffset());
+  W->printString("Name", Field.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        StaticDataMemberRecord &Field) {
+  printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+                        MethodOptions::None);
+  printTypeIndex("Type", Field.getType());
+  W->printString("Name", Field.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        VFPtrRecord &VFTable) {
+  printTypeIndex("Type", VFTable.getType());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        EnumeratorRecord &Enum) {
+  printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
+                        MethodOptions::None);
+  W->printNumber("EnumValue", Enum.getValue());
+  W->printString("Name", Enum.getName());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        BaseClassRecord &Base) {
+  printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+                        MethodOptions::None);
+  printTypeIndex("BaseType", Base.getBaseType());
+  W->printHex("BaseOffset", Base.getBaseOffset());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        VirtualBaseClassRecord &Base) {
+  printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+                        MethodOptions::None);
+  printTypeIndex("BaseType", Base.getBaseType());
+  printTypeIndex("VBPtrType", Base.getVBPtrType());
+  W->printHex("VBPtrOffset", Base.getVBPtrOffset());
+  W->printHex("VBTableIndex", Base.getVTableIndex());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+                                        ListContinuationRecord &Cont) {
+  printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &LR) {
+  W->printEnum("Mode", uint16_t(LR.Mode), makeArrayRef(LabelTypeEnum));
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        PrecompRecord &Precomp) {
+  W->printHex("StartIndex", Precomp.getStartTypeIndex());
+  W->printHex("Count", Precomp.getTypesCount());
+  W->printHex("Signature", Precomp.getSignature());
+  W->printString("PrecompFile", Precomp.getPrecompFilePath());
+  return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+                                        EndPrecompRecord &EndPrecomp) {
+  W->printHex("Signature", EndPrecomp.getSignature());
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp
new file mode 100644
index 0000000..826faef
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp
@@ -0,0 +1,75 @@
+//===- TypeHashing.cpp -------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/Support/SHA1.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+LocallyHashedType DenseMapInfo<LocallyHashedType>::Empty{0, {}};
+LocallyHashedType DenseMapInfo<LocallyHashedType>::Tombstone{hash_code(-1), {}};
+
+static std::array<uint8_t, 8> EmptyHash = {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+static std::array<uint8_t, 8> TombstoneHash = {
+    {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+GloballyHashedType DenseMapInfo<GloballyHashedType>::Empty{EmptyHash};
+GloballyHashedType DenseMapInfo<GloballyHashedType>::Tombstone{TombstoneHash};
+
+LocallyHashedType LocallyHashedType::hashType(ArrayRef<uint8_t> RecordData) {
+  return {llvm::hash_value(RecordData), RecordData};
+}
+
+GloballyHashedType
+GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData,
+                             ArrayRef<GloballyHashedType> PreviousTypes,
+                             ArrayRef<GloballyHashedType> PreviousIds) {
+  SmallVector<TiReference, 4> Refs;
+  discoverTypeIndices(RecordData, Refs);
+  SHA1 S;
+  S.init();
+  uint32_t Off = 0;
+  S.update(RecordData.take_front(sizeof(RecordPrefix)));
+  RecordData = RecordData.drop_front(sizeof(RecordPrefix));
+  for (const auto &Ref : Refs) {
+    // Hash any data that comes before this TiRef.
+    uint32_t PreLen = Ref.Offset - Off;
+    ArrayRef<uint8_t> PreData = RecordData.slice(Off, PreLen);
+    S.update(PreData);
+    auto Prev = (Ref.Kind == TiRefKind::IndexRef) ? PreviousIds : PreviousTypes;
+
+    auto RefData = RecordData.slice(Ref.Offset, Ref.Count * sizeof(TypeIndex));
+    // For each type index referenced, add in the previously computed hash
+    // value of that type.
+    ArrayRef<TypeIndex> Indices(
+        reinterpret_cast<const TypeIndex *>(RefData.data()), Ref.Count);
+    for (TypeIndex TI : Indices) {
+      ArrayRef<uint8_t> BytesToHash;
+      if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) {
+        const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);
+        BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));
+      } else {
+        BytesToHash = Prev[TI.toArrayIndex()].Hash;
+      }
+      S.update(BytesToHash);
+    }
+
+    Off = Ref.Offset + Ref.Count * sizeof(TypeIndex);
+  }
+
+  // Don't forget to add in any trailing bytes.
+  auto TrailingBytes = RecordData.drop_front(Off);
+  S.update(TrailingBytes);
+
+  return {S.final().take_back(8)};
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp
new file mode 100644
index 0000000..332d674
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp
@@ -0,0 +1,107 @@
+//===-- TypeIndex.cpp - CodeView type index ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+namespace {
+struct SimpleTypeEntry {
+  StringRef Name;
+  SimpleTypeKind Kind;
+};
+
+/// The names here all end in "*". If the simple type is a pointer type, we
+/// return the whole name. Otherwise we lop off the last character in our
+/// StringRef.
+static const SimpleTypeEntry SimpleTypeNames[] = {
+    {"void*", SimpleTypeKind::Void},
+    {"<not translated>*", SimpleTypeKind::NotTranslated},
+    {"HRESULT*", SimpleTypeKind::HResult},
+    {"signed char*", SimpleTypeKind::SignedCharacter},
+    {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
+    {"char*", SimpleTypeKind::NarrowCharacter},
+    {"wchar_t*", SimpleTypeKind::WideCharacter},
+    {"char16_t*", SimpleTypeKind::Character16},
+    {"char32_t*", SimpleTypeKind::Character32},
+    {"__int8*", SimpleTypeKind::SByte},
+    {"unsigned __int8*", SimpleTypeKind::Byte},
+    {"short*", SimpleTypeKind::Int16Short},
+    {"unsigned short*", SimpleTypeKind::UInt16Short},
+    {"__int16*", SimpleTypeKind::Int16},
+    {"unsigned __int16*", SimpleTypeKind::UInt16},
+    {"long*", SimpleTypeKind::Int32Long},
+    {"unsigned long*", SimpleTypeKind::UInt32Long},
+    {"int*", SimpleTypeKind::Int32},
+    {"unsigned*", SimpleTypeKind::UInt32},
+    {"__int64*", SimpleTypeKind::Int64Quad},
+    {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
+    {"__int64*", SimpleTypeKind::Int64},
+    {"unsigned __int64*", SimpleTypeKind::UInt64},
+    {"__int128*", SimpleTypeKind::Int128},
+    {"unsigned __int128*", SimpleTypeKind::UInt128},
+    {"__half*", SimpleTypeKind::Float16},
+    {"float*", SimpleTypeKind::Float32},
+    {"float*", SimpleTypeKind::Float32PartialPrecision},
+    {"__float48*", SimpleTypeKind::Float48},
+    {"double*", SimpleTypeKind::Float64},
+    {"long double*", SimpleTypeKind::Float80},
+    {"__float128*", SimpleTypeKind::Float128},
+    {"_Complex float*", SimpleTypeKind::Complex32},
+    {"_Complex double*", SimpleTypeKind::Complex64},
+    {"_Complex long double*", SimpleTypeKind::Complex80},
+    {"_Complex __float128*", SimpleTypeKind::Complex128},
+    {"bool*", SimpleTypeKind::Boolean8},
+    {"__bool16*", SimpleTypeKind::Boolean16},
+    {"__bool32*", SimpleTypeKind::Boolean32},
+    {"__bool64*", SimpleTypeKind::Boolean64},
+};
+} // namespace
+
+StringRef TypeIndex::simpleTypeName(TypeIndex TI) {
+  assert(TI.isNoneType() || TI.isSimple());
+
+  if (TI.isNoneType())
+    return "<no type>";
+
+  if (TI == TypeIndex::NullptrT())
+    return "std::nullptr_t";
+
+  // This is a simple type.
+  for (const auto &SimpleTypeName : SimpleTypeNames) {
+    if (SimpleTypeName.Kind == TI.getSimpleKind()) {
+      if (TI.getSimpleMode() == SimpleTypeMode::Direct)
+        return SimpleTypeName.Name.drop_back(1);
+      // Otherwise, this is a pointer type. We gloss over the distinction
+      // between near, far, 64, 32, etc, and just give a pointer type.
+      return SimpleTypeName.Name;
+    }
+  }
+  return "<unknown simple type>";
+}
+
+void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+                                    TypeIndex TI, TypeCollection &Types) {
+  StringRef TypeName;
+  if (!TI.isNoneType()) {
+    if (TI.isSimple())
+      TypeName = TypeIndex::simpleTypeName(TI);
+    else
+      TypeName = Types.getTypeName(TI);
+  }
+
+  if (!TypeName.empty())
+    Printer.printHex(FieldName, TypeName, TI.getIndex());
+  else
+    Printer.printHex(FieldName, TI.getIndex());
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
new file mode 100644
index 0000000..839ab6f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
@@ -0,0 +1,521 @@
+//===- TypeIndexDiscovery.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static inline MethodKind getMethodKind(uint16_t Attrs) {
+  Attrs &= uint16_t(MethodOptions::MethodKindMask);
+  Attrs >>= 2;
+  return MethodKind(Attrs);
+}
+
+static inline bool isIntroVirtual(uint16_t Attrs) {
+  MethodKind MK = getMethodKind(Attrs);
+  return MK == MethodKind::IntroducingVirtual ||
+         MK == MethodKind::PureIntroducingVirtual;
+}
+
+static inline PointerMode getPointerMode(uint32_t Attrs) {
+  return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
+                                  PointerRecord::PointerModeMask);
+}
+
+static inline bool isMemberPointer(uint32_t Attrs) {
+  PointerMode Mode = getPointerMode(Attrs);
+  return Mode == PointerMode::PointerToDataMember ||
+         Mode == PointerMode::PointerToMemberFunction;
+}
+
+static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
+  uint16_t N = support::endian::read16le(Data.data());
+  if (N < LF_NUMERIC)
+    return 2;
+
+  assert(N <= LF_UQUADWORD);
+
+  constexpr uint32_t Sizes[] = {
+      1,  // LF_CHAR
+      2,  // LF_SHORT
+      2,  // LF_USHORT
+      4,  // LF_LONG
+      4,  // LF_ULONG
+      4,  // LF_REAL32
+      8,  // LF_REAL64
+      10, // LF_REAL80
+      16, // LF_REAL128
+      8,  // LF_QUADWORD
+      8,  // LF_UQUADWORD
+  };
+
+  return 2 + Sizes[N - LF_NUMERIC];
+}
+
+static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
+  const char *S = reinterpret_cast<const char *>(Data.data());
+  return strlen(S) + 1;
+}
+
+static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
+                                     SmallVectorImpl<TiReference> &Refs) {
+  uint32_t Offset = 0;
+
+  while (!Content.empty()) {
+    // Array of:
+    //   0: Attrs
+    //   2: Padding
+    //   4: TypeIndex
+    //   if (isIntroVirtual())
+    //     8: VFTableOffset
+
+    // At least 8 bytes are guaranteed.  4 extra bytes come iff function is an
+    // intro virtual.
+    uint32_t Len = 8;
+
+    uint16_t Attrs = support::endian::read16le(Content.data());
+    Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+
+    if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
+      Len += 4;
+    Offset += Len;
+    Content = Content.drop_front(Len);
+  }
+}
+
+static uint32_t handleBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  // 8: Encoded Integer
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8 + getEncodedIntegerLength(Data.drop_front(8));
+}
+
+static uint32_t handleEnumerator(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                 SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: Encoded Integer
+  // <next>: Name
+  uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
+  return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                 SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  // 8: Encoded Integer
+  // <next>: Name
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
+  return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleOverloadedMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                       SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  // 8: Name
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleOneMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Attributes
+  // 4: Type
+  // if (isIntroVirtual)
+  //   8: VFTableOffset
+  // <next>: Name
+  uint32_t Size = 8;
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+
+  uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
+  if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
+    Size += 4;
+
+  return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleNestedType(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                 SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  // 8: Name
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleStaticDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                       SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  // 8: Name
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleVirtualBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                       bool IsIndirect,
+                                       SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Attrs
+  // 4: TypeIndex
+  // 8: TypeIndex
+  // 12: Encoded Integer
+  // <next>: Encoded Integer
+  uint32_t Size = 12;
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
+  Size += getEncodedIntegerLength(Data.drop_front(Size));
+  Size += getEncodedIntegerLength(Data.drop_front(Size));
+  return Size;
+}
+
+static uint32_t handleVFPtr(ArrayRef<uint8_t> Data, uint32_t Offset,
+                            SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8;
+}
+
+static uint32_t handleListContinuation(ArrayRef<uint8_t> Data, uint32_t Offset,
+                                       SmallVectorImpl<TiReference> &Refs) {
+  // 0: Kind
+  // 2: Padding
+  // 4: TypeIndex
+  Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+  return 8;
+}
+
+static void handleFieldList(ArrayRef<uint8_t> Content,
+                            SmallVectorImpl<TiReference> &Refs) {
+  uint32_t Offset = 0;
+  uint32_t ThisLen = 0;
+  while (!Content.empty()) {
+    TypeLeafKind Kind =
+        static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
+    switch (Kind) {
+    case LF_BCLASS:
+      ThisLen = handleBaseClass(Content, Offset, Refs);
+      break;
+    case LF_ENUMERATE:
+      ThisLen = handleEnumerator(Content, Offset, Refs);
+      break;
+    case LF_MEMBER:
+      ThisLen = handleDataMember(Content, Offset, Refs);
+      break;
+    case LF_METHOD:
+      ThisLen = handleOverloadedMethod(Content, Offset, Refs);
+      break;
+    case LF_ONEMETHOD:
+      ThisLen = handleOneMethod(Content, Offset, Refs);
+      break;
+    case LF_NESTTYPE:
+      ThisLen = handleNestedType(Content, Offset, Refs);
+      break;
+    case LF_STMEMBER:
+      ThisLen = handleStaticDataMember(Content, Offset, Refs);
+      break;
+    case LF_VBCLASS:
+    case LF_IVBCLASS:
+      ThisLen =
+          handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
+      break;
+    case LF_VFUNCTAB:
+      ThisLen = handleVFPtr(Content, Offset, Refs);
+      break;
+    case LF_INDEX:
+      ThisLen = handleListContinuation(Content, Offset, Refs);
+      break;
+    default:
+      return;
+    }
+    Content = Content.drop_front(ThisLen);
+    Offset += ThisLen;
+    if (!Content.empty()) {
+      uint8_t Pad = Content.front();
+      if (Pad >= LF_PAD0) {
+        uint32_t Skip = Pad & 0x0F;
+        Content = Content.drop_front(Skip);
+        Offset += Skip;
+      }
+    }
+  }
+}
+
+static void handlePointer(ArrayRef<uint8_t> Content,
+                          SmallVectorImpl<TiReference> &Refs) {
+  Refs.push_back({TiRefKind::TypeRef, 0, 1});
+
+  uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
+  if (isMemberPointer(Attrs))
+    Refs.push_back({TiRefKind::TypeRef, 8, 1});
+}
+
+static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
+                                SmallVectorImpl<TiReference> &Refs) {
+  uint32_t Count;
+  // FIXME: In the future it would be nice if we could avoid hardcoding these
+  // values.  One idea is to define some structures representing these types
+  // that would allow the use of offsetof().
+  switch (Kind) {
+  case TypeLeafKind::LF_FUNC_ID:
+    Refs.push_back({TiRefKind::IndexRef, 0, 1});
+    Refs.push_back({TiRefKind::TypeRef, 4, 1});
+    break;
+  case TypeLeafKind::LF_MFUNC_ID:
+    Refs.push_back({TiRefKind::TypeRef, 0, 2});
+    break;
+  case TypeLeafKind::LF_STRING_ID:
+    Refs.push_back({TiRefKind::IndexRef, 0, 1});
+    break;
+  case TypeLeafKind::LF_SUBSTR_LIST:
+    Count = support::endian::read32le(Content.data());
+    if (Count > 0)
+      Refs.push_back({TiRefKind::IndexRef, 4, Count});
+    break;
+  case TypeLeafKind::LF_BUILDINFO:
+    Count = support::endian::read16le(Content.data());
+    if (Count > 0)
+      Refs.push_back({TiRefKind::IndexRef, 2, Count});
+    break;
+  case TypeLeafKind::LF_UDT_SRC_LINE:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1});
+    Refs.push_back({TiRefKind::IndexRef, 4, 1});
+    break;
+  case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1});
+    break;
+  case TypeLeafKind::LF_MODIFIER:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1});
+    break;
+  case TypeLeafKind::LF_PROCEDURE:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1});
+    Refs.push_back({TiRefKind::TypeRef, 8, 1});
+    break;
+  case TypeLeafKind::LF_MFUNCTION:
+    Refs.push_back({TiRefKind::TypeRef, 0, 3});
+    Refs.push_back({TiRefKind::TypeRef, 16, 1});
+    break;
+  case TypeLeafKind::LF_ARGLIST:
+    Count = support::endian::read32le(Content.data());
+    if (Count > 0)
+      Refs.push_back({TiRefKind::TypeRef, 4, Count});
+    break;
+  case TypeLeafKind::LF_ARRAY:
+    Refs.push_back({TiRefKind::TypeRef, 0, 2});
+    break;
+  case TypeLeafKind::LF_CLASS:
+  case TypeLeafKind::LF_STRUCTURE:
+  case TypeLeafKind::LF_INTERFACE:
+    Refs.push_back({TiRefKind::TypeRef, 4, 3});
+    break;
+  case TypeLeafKind::LF_UNION:
+    Refs.push_back({TiRefKind::TypeRef, 4, 1});
+    break;
+  case TypeLeafKind::LF_ENUM:
+    Refs.push_back({TiRefKind::TypeRef, 4, 2});
+    break;
+  case TypeLeafKind::LF_BITFIELD:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1});
+    break;
+  case TypeLeafKind::LF_VFTABLE:
+    Refs.push_back({TiRefKind::TypeRef, 0, 2});
+    break;
+  case TypeLeafKind::LF_VTSHAPE:
+    break;
+  case TypeLeafKind::LF_METHODLIST:
+    handleMethodOverloadList(Content, Refs);
+    break;
+  case TypeLeafKind::LF_FIELDLIST:
+    handleFieldList(Content, Refs);
+    break;
+  case TypeLeafKind::LF_POINTER:
+    handlePointer(Content, Refs);
+    break;
+  default:
+    break;
+  }
+}
+
+static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind,
+                                SmallVectorImpl<TiReference> &Refs) {
+  uint32_t Count;
+  // FIXME: In the future it would be nice if we could avoid hardcoding these
+  // values.  One idea is to define some structures representing these types
+  // that would allow the use of offsetof().
+  switch (Kind) {
+  case SymbolKind::S_GPROC32:
+  case SymbolKind::S_LPROC32:
+  case SymbolKind::S_GPROC32_ID:
+  case SymbolKind::S_LPROC32_ID:
+  case SymbolKind::S_LPROC32_DPC:
+  case SymbolKind::S_LPROC32_DPC_ID:
+    Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
+    break;
+  case SymbolKind::S_UDT:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
+    break;
+  case SymbolKind::S_GDATA32:
+  case SymbolKind::S_LDATA32:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_BUILDINFO:
+    Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
+    break;
+  case SymbolKind::S_LTHREAD32:
+  case SymbolKind::S_GTHREAD32:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_FILESTATIC:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_LOCAL:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_REGISTER:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_CONSTANT:
+    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
+    break;
+  case SymbolKind::S_BPREL32:
+  case SymbolKind::S_REGREL32:
+    Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
+    break;
+  case SymbolKind::S_CALLSITEINFO:
+    Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
+    break;
+  case SymbolKind::S_CALLERS:
+  case SymbolKind::S_CALLEES:
+  case SymbolKind::S_INLINEES:
+    // The record is a count followed by an array of type indices.
+    Count = *reinterpret_cast<const ulittle32_t *>(Content.data());
+    Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
+    break;
+  case SymbolKind::S_INLINESITE:
+    Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
+    break;
+  case SymbolKind::S_HEAPALLOCSITE:
+    Refs.push_back({TiRefKind::TypeRef, 8, 1}); // UDT allocated
+    break;
+
+  // Defranges don't have types, just registers and code offsets.
+  case SymbolKind::S_DEFRANGE_REGISTER:
+  case SymbolKind::S_DEFRANGE_REGISTER_REL:
+  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
+  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
+  case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
+  case SymbolKind::S_DEFRANGE_SUBFIELD:
+    break;
+
+  // No type references.
+  case SymbolKind::S_LABEL32:
+  case SymbolKind::S_OBJNAME:
+  case SymbolKind::S_COMPILE:
+  case SymbolKind::S_COMPILE2:
+  case SymbolKind::S_COMPILE3:
+  case SymbolKind::S_ENVBLOCK:
+  case SymbolKind::S_BLOCK32:
+  case SymbolKind::S_FRAMEPROC:
+  case SymbolKind::S_THUNK32:
+  case SymbolKind::S_FRAMECOOKIE:
+  case SymbolKind::S_UNAMESPACE:
+    break;
+  // Scope ending symbols.
+  case SymbolKind::S_END:
+  case SymbolKind::S_INLINESITE_END:
+  case SymbolKind::S_PROC_ID_END:
+    break;
+  default:
+    return false; // Unknown symbol.
+  }
+  return true;
+}
+
+void llvm::codeview::discoverTypeIndices(const CVType &Type,
+                                         SmallVectorImpl<TiReference> &Refs) {
+  ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
+}
+
+static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
+                                       ArrayRef<TiReference> Refs,
+                                       SmallVectorImpl<TypeIndex> &Indices) {
+  Indices.clear();
+
+  if (Refs.empty())
+    return;
+
+  RecordData = RecordData.drop_front(sizeof(RecordPrefix));
+
+  BinaryStreamReader Reader(RecordData, support::little);
+  for (const auto &Ref : Refs) {
+    Reader.setOffset(Ref.Offset);
+    FixedStreamArray<TypeIndex> Run;
+    cantFail(Reader.readArray(Run, Ref.Count));
+    Indices.append(Run.begin(), Run.end());
+  }
+}
+
+void llvm::codeview::discoverTypeIndices(const CVType &Type,
+                                         SmallVectorImpl<TypeIndex> &Indices) {
+  return discoverTypeIndices(Type.RecordData, Indices);
+}
+
+void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+                                         SmallVectorImpl<TypeIndex> &Indices) {
+  SmallVector<TiReference, 4> Refs;
+  discoverTypeIndices(RecordData, Refs);
+  resolveTypeIndexReferences(RecordData, Refs, Indices);
+}
+
+void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+                                         SmallVectorImpl<TiReference> &Refs) {
+  const RecordPrefix *P =
+      reinterpret_cast<const RecordPrefix *>(RecordData.data());
+  TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+  ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
+}
+
+bool llvm::codeview::discoverTypeIndicesInSymbol(
+    const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
+  SymbolKind K = Sym.kind();
+  return ::discoverTypeIndices(Sym.content(), K, Refs);
+}
+
+bool llvm::codeview::discoverTypeIndicesInSymbol(
+    ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
+  const RecordPrefix *P =
+      reinterpret_cast<const RecordPrefix *>(RecordData.data());
+  SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
+  return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
+                               Refs);
+}
+
+bool llvm::codeview::discoverTypeIndicesInSymbol(
+    ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
+  SmallVector<TiReference, 2> Refs;
+  if (!discoverTypeIndicesInSymbol(RecordData, Refs))
+    return false;
+  resolveTypeIndexReferences(RecordData, Refs, Indices);
+  return true;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
new file mode 100644
index 0000000..2a66474
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
@@ -0,0 +1,53 @@
+//===- TypeRecordHelpers.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
+  RecordT Record;
+  if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
+    consumeError(std::move(EC));
+    return ClassOptions::None;
+  }
+  return Record.getOptions();
+}
+
+bool llvm::codeview::isUdtForwardRef(CVType CVT) {
+  ClassOptions UdtOptions = ClassOptions::None;
+  switch (CVT.kind()) {
+  case LF_STRUCTURE:
+  case LF_CLASS:
+  case LF_INTERFACE:
+    UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
+    break;
+  case LF_ENUM:
+    UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
+    break;
+  case LF_UNION:
+    UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
+    break;
+  default:
+    return false;
+  }
+  return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
+}
+
+TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) {
+  assert(CVT.kind() == LF_MODIFIER);
+  SmallVector<TypeIndex, 1> Refs;
+  discoverTypeIndices(CVT, Refs);
+  return Refs.front();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
new file mode 100644
index 0000000..3203ff6
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -0,0 +1,497 @@
+//===- TypeRecordMapping.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+#define error(X)                                                               \
+  if (auto EC = X)                                                             \
+    return EC;
+
+namespace {
+struct MapOneMethodRecord {
+  explicit MapOneMethodRecord(bool IsFromOverloadList)
+      : IsFromOverloadList(IsFromOverloadList) {}
+
+  Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
+    error(IO.mapInteger(Method.Attrs.Attrs));
+    if (IsFromOverloadList) {
+      uint16_t Padding = 0;
+      error(IO.mapInteger(Padding));
+    }
+    error(IO.mapInteger(Method.Type));
+    if (Method.isIntroducingVirtual()) {
+      error(IO.mapInteger(Method.VFTableOffset));
+    } else if (!IO.isWriting())
+      Method.VFTableOffset = -1;
+
+    if (!IsFromOverloadList)
+      error(IO.mapStringZ(Method.Name));
+
+    return Error::success();
+  }
+
+private:
+  bool IsFromOverloadList;
+};
+}
+
+static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
+                                  StringRef &UniqueName, bool HasUniqueName) {
+  if (IO.isWriting()) {
+    // Try to be smart about what we write here.  We can't write anything too
+    // large, so if we're going to go over the limit, truncate both the name
+    // and unique name by the same amount.
+    size_t BytesLeft = IO.maxFieldLength();
+    if (HasUniqueName) {
+      size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
+      StringRef N = Name;
+      StringRef U = UniqueName;
+      if (BytesNeeded > BytesLeft) {
+        size_t BytesToDrop = (BytesNeeded - BytesLeft);
+        size_t DropN = std::min(N.size(), BytesToDrop / 2);
+        size_t DropU = std::min(U.size(), BytesToDrop - DropN);
+
+        N = N.drop_back(DropN);
+        U = U.drop_back(DropU);
+      }
+
+      error(IO.mapStringZ(N));
+      error(IO.mapStringZ(U));
+    } else {
+      // Cap the length of the string at however many bytes we have available,
+      // plus one for the required null terminator.
+      auto N = StringRef(Name).take_front(BytesLeft - 1);
+      error(IO.mapStringZ(N));
+    }
+  } else {
+    error(IO.mapStringZ(Name));
+    if (HasUniqueName)
+      error(IO.mapStringZ(UniqueName));
+  }
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
+  assert(!TypeKind.hasValue() && "Already in a type mapping!");
+  assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+  // FieldList and MethodList records can be any length because they can be
+  // split with continuation records.  All other record types cannot be
+  // longer than the maximum record length.
+  Optional<uint32_t> MaxLen;
+  if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
+      CVR.Type != TypeLeafKind::LF_METHODLIST)
+    MaxLen = MaxRecordLength - sizeof(RecordPrefix);
+  error(IO.beginRecord(MaxLen));
+  TypeKind = CVR.Type;
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
+  assert(TypeKind.hasValue() && "Not in a type mapping!");
+  assert(!MemberKind.hasValue() && "Still in a member mapping!");
+
+  error(IO.endRecord());
+
+  TypeKind.reset();
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
+  assert(TypeKind.hasValue() && "Not in a type mapping!");
+  assert(!MemberKind.hasValue() && "Already in a member mapping!");
+
+  // The largest possible subrecord is one in which there is a record prefix,
+  // followed by the subrecord, followed by a continuation, and that entire
+  // sequence spaws `MaxRecordLength` bytes.  So the record's length is
+  // calculated as follows.
+  constexpr uint32_t ContinuationLength = 8;
+  error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
+                       ContinuationLength));
+
+  MemberKind = Record.Kind;
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
+  assert(TypeKind.hasValue() && "Not in a type mapping!");
+  assert(MemberKind.hasValue() && "Not in a member mapping!");
+
+  if (!IO.isWriting()) {
+    if (auto EC = IO.skipPadding())
+      return EC;
+  }
+
+  MemberKind.reset();
+  error(IO.endRecord());
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
+  error(IO.mapInteger(Record.ModifiedType));
+  error(IO.mapEnum(Record.Modifiers));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          ProcedureRecord &Record) {
+  error(IO.mapInteger(Record.ReturnType));
+  error(IO.mapEnum(Record.CallConv));
+  error(IO.mapEnum(Record.Options));
+  error(IO.mapInteger(Record.ParameterCount));
+  error(IO.mapInteger(Record.ArgumentList));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          MemberFunctionRecord &Record) {
+  error(IO.mapInteger(Record.ReturnType));
+  error(IO.mapInteger(Record.ClassType));
+  error(IO.mapInteger(Record.ThisType));
+  error(IO.mapEnum(Record.CallConv));
+  error(IO.mapEnum(Record.Options));
+  error(IO.mapInteger(Record.ParameterCount));
+  error(IO.mapInteger(Record.ArgumentList));
+  error(IO.mapInteger(Record.ThisPointerAdjustment));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
+  error(IO.mapVectorN<uint32_t>(
+      Record.ArgIndices,
+      [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          StringListRecord &Record) {
+  error(IO.mapVectorN<uint32_t>(
+      Record.StringIndices,
+      [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
+  error(IO.mapInteger(Record.ReferentType));
+  error(IO.mapInteger(Record.Attrs));
+
+  if (Record.isPointerToMember()) {
+    if (!IO.isWriting())
+      Record.MemberInfo.emplace();
+
+    MemberPointerInfo &M = *Record.MemberInfo;
+    error(IO.mapInteger(M.ContainingType));
+    error(IO.mapEnum(M.Representation));
+  }
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
+  error(IO.mapInteger(Record.ElementType));
+  error(IO.mapInteger(Record.IndexType));
+  error(IO.mapEncodedInteger(Record.Size));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
+  assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
+         (CVR.Type == TypeLeafKind::LF_CLASS) ||
+         (CVR.Type == TypeLeafKind::LF_INTERFACE));
+
+  error(IO.mapInteger(Record.MemberCount));
+  error(IO.mapEnum(Record.Options));
+  error(IO.mapInteger(Record.FieldList));
+  error(IO.mapInteger(Record.DerivationList));
+  error(IO.mapInteger(Record.VTableShape));
+  error(IO.mapEncodedInteger(Record.Size));
+  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+                             Record.hasUniqueName()));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
+  error(IO.mapInteger(Record.MemberCount));
+  error(IO.mapEnum(Record.Options));
+  error(IO.mapInteger(Record.FieldList));
+  error(IO.mapEncodedInteger(Record.Size));
+  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+                             Record.hasUniqueName()));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
+  error(IO.mapInteger(Record.MemberCount));
+  error(IO.mapEnum(Record.Options));
+  error(IO.mapInteger(Record.UnderlyingType));
+  error(IO.mapInteger(Record.FieldList));
+  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
+                             Record.hasUniqueName()));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
+  error(IO.mapInteger(Record.Type));
+  error(IO.mapInteger(Record.BitSize));
+  error(IO.mapInteger(Record.BitOffset));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          VFTableShapeRecord &Record) {
+  uint16_t Size;
+  if (IO.isWriting()) {
+    ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
+    Size = Slots.size();
+    error(IO.mapInteger(Size));
+
+    for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
+      uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
+      if ((SlotIndex + 1) < Slots.size()) {
+        Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
+      }
+      error(IO.mapInteger(Byte));
+    }
+  } else {
+    error(IO.mapInteger(Size));
+    for (uint16_t I = 0; I < Size; I += 2) {
+      uint8_t Byte;
+      error(IO.mapInteger(Byte));
+      Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
+      if ((I + 1) < Size)
+        Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
+    }
+  }
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
+  error(IO.mapInteger(Record.CompleteClass));
+  error(IO.mapInteger(Record.OverriddenVFTable));
+  error(IO.mapInteger(Record.VFPtrOffset));
+  uint32_t NamesLen = 0;
+  if (IO.isWriting()) {
+    for (auto Name : Record.MethodNames)
+      NamesLen += Name.size() + 1;
+  }
+  error(IO.mapInteger(NamesLen));
+  error(IO.mapVectorTail(
+      Record.MethodNames,
+      [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
+  error(IO.mapInteger(Record.Id));
+  error(IO.mapStringZ(Record.String));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          UdtSourceLineRecord &Record) {
+  error(IO.mapInteger(Record.UDT));
+  error(IO.mapInteger(Record.SourceFile));
+  error(IO.mapInteger(Record.LineNumber));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          UdtModSourceLineRecord &Record) {
+  error(IO.mapInteger(Record.UDT));
+  error(IO.mapInteger(Record.SourceFile));
+  error(IO.mapInteger(Record.LineNumber));
+  error(IO.mapInteger(Record.Module));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
+  error(IO.mapInteger(Record.ParentScope));
+  error(IO.mapInteger(Record.FunctionType));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          MemberFuncIdRecord &Record) {
+  error(IO.mapInteger(Record.ClassType));
+  error(IO.mapInteger(Record.FunctionType));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          BuildInfoRecord &Record) {
+  error(IO.mapVectorN<uint16_t>(
+      Record.ArgIndices,
+      [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          MethodOverloadListRecord &Record) {
+  // TODO: Split the list into multiple records if it's longer than 64KB, using
+  // a subrecord of TypeRecordKind::Index to chain the records together.
+  error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          FieldListRecord &Record) {
+  error(IO.mapByteVectorTail(Record.Data));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          TypeServer2Record &Record) {
+  error(IO.mapGuid(Record.Guid));
+  error(IO.mapInteger(Record.Age));
+  error(IO.mapStringZ(Record.Name));
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
+  error(IO.mapEnum(Record.Mode));
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          BaseClassRecord &Record) {
+  error(IO.mapInteger(Record.Attrs.Attrs));
+  error(IO.mapInteger(Record.Type));
+  error(IO.mapEncodedInteger(Record.Offset));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          EnumeratorRecord &Record) {
+  error(IO.mapInteger(Record.Attrs.Attrs));
+
+  // FIXME: Handle full APInt such as __int128.
+  error(IO.mapEncodedInteger(Record.Value));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          DataMemberRecord &Record) {
+  error(IO.mapInteger(Record.Attrs.Attrs));
+  error(IO.mapInteger(Record.Type));
+  error(IO.mapEncodedInteger(Record.FieldOffset));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          OverloadedMethodRecord &Record) {
+  error(IO.mapInteger(Record.NumOverloads));
+  error(IO.mapInteger(Record.MethodList));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          OneMethodRecord &Record) {
+  const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
+  MapOneMethodRecord Mapper(IsFromOverloadList);
+  return Mapper(IO, Record);
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          NestedTypeRecord &Record) {
+  uint16_t Padding = 0;
+  error(IO.mapInteger(Padding));
+  error(IO.mapInteger(Record.Type));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          StaticDataMemberRecord &Record) {
+
+  error(IO.mapInteger(Record.Attrs.Attrs));
+  error(IO.mapInteger(Record.Type));
+  error(IO.mapStringZ(Record.Name));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          VirtualBaseClassRecord &Record) {
+
+  error(IO.mapInteger(Record.Attrs.Attrs));
+  error(IO.mapInteger(Record.BaseType));
+  error(IO.mapInteger(Record.VBPtrType));
+  error(IO.mapEncodedInteger(Record.VBPtrOffset));
+  error(IO.mapEncodedInteger(Record.VTableIndex));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          VFPtrRecord &Record) {
+  uint16_t Padding = 0;
+  error(IO.mapInteger(Padding));
+  error(IO.mapInteger(Record.Type));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
+                                          ListContinuationRecord &Record) {
+  uint16_t Padding = 0;
+  error(IO.mapInteger(Padding));
+  error(IO.mapInteger(Record.ContinuationIndex));
+
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          PrecompRecord &Precomp) {
+  error(IO.mapInteger(Precomp.StartTypeIndex));
+  error(IO.mapInteger(Precomp.TypesCount));
+  error(IO.mapInteger(Precomp.Signature));
+  error(IO.mapStringZ(Precomp.PrecompFilePath));
+  return Error::success();
+}
+
+Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
+                                          EndPrecompRecord &EndPrecomp) {
+  error(IO.mapInteger(EndPrecomp.Signature));
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
new file mode 100644
index 0000000..bae11ce
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -0,0 +1,494 @@
+//===-- TypeStreamMerger.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static inline size_t slotForIndex(TypeIndex Idx) {
+  assert(!Idx.isSimple() && "simple type indices have no slots");
+  return Idx.getIndex() - TypeIndex::FirstNonSimpleIndex;
+}
+
+namespace {
+
+/// Implementation of CodeView type stream merging.
+///
+/// A CodeView type stream is a series of records that reference each other
+/// through type indices. A type index is either "simple", meaning it is less
+/// than 0x1000 and refers to a builtin type, or it is complex, meaning it
+/// refers to a prior type record in the current stream. The type index of a
+/// record is equal to the number of records before it in the stream plus
+/// 0x1000.
+///
+/// Type records are only allowed to use type indices smaller than their own, so
+/// a type stream is effectively a topologically sorted DAG. Cycles occuring in
+/// the type graph of the source program are resolved with forward declarations
+/// of composite types. This class implements the following type stream merging
+/// algorithm, which relies on this DAG structure:
+///
+/// - Begin with a new empty stream, and a new empty hash table that maps from
+///   type record contents to new type index.
+/// - For each new type stream, maintain a map from source type index to
+///   destination type index.
+/// - For each record, copy it and rewrite its type indices to be valid in the
+///   destination type stream.
+/// - If the new type record is not already present in the destination stream
+///   hash table, append it to the destination type stream, assign it the next
+///   type index, and update the two hash tables.
+/// - If the type record already exists in the destination stream, discard it
+///   and update the type index map to forward the source type index to the
+///   existing destination type index.
+///
+/// As an additional complication, type stream merging actually produces two
+/// streams: an item (or IPI) stream and a type stream, as this is what is
+/// actually stored in the final PDB. We choose which records go where by
+/// looking at the record kind.
+class TypeStreamMerger {
+public:
+  explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest)
+      : IndexMap(SourceToDest) {
+    // When dealing with precompiled headers objects, all data in SourceToDest
+    // belongs to the precompiled headers object, and is assumed to be already
+    // remapped to the target PDB. Any forthcoming type that will be merged in
+    // might potentially back-reference this data. We also don't want to resolve
+    // twice the types in the precompiled object.
+    CurIndex += SourceToDest.size();
+  }
+
+  static const TypeIndex Untranslated;
+
+  // Local hashing entry points
+  Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
+                         MergingTypeTableBuilder &DestTypes,
+                         const CVTypeArray &IdsAndTypes, Optional<uint32_t> &S);
+  Error mergeIdRecords(MergingTypeTableBuilder &Dest,
+                       ArrayRef<TypeIndex> TypeSourceToDest,
+                       const CVTypeArray &Ids);
+  Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
+                         const CVTypeArray &Types);
+
+  // Global hashing entry points
+  Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+                         GlobalTypeTableBuilder &DestTypes,
+                         const CVTypeArray &IdsAndTypes,
+                         ArrayRef<GloballyHashedType> Hashes,
+                         Optional<uint32_t> &S);
+  Error mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                       ArrayRef<TypeIndex> TypeSourceToDest,
+                       const CVTypeArray &Ids,
+                       ArrayRef<GloballyHashedType> Hashes);
+  Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,
+                         ArrayRef<GloballyHashedType> Hashes,
+                         Optional<uint32_t> &S);
+
+private:
+  Error doit(const CVTypeArray &Types);
+
+  Error remapAllTypes(const CVTypeArray &Types);
+
+  Error remapType(const CVType &Type);
+
+  void addMapping(TypeIndex Idx);
+
+  inline bool remapTypeIndex(TypeIndex &Idx) {
+    // If we're mapping a pure index stream, then IndexMap only contains
+    // mappings from OldIdStream -> NewIdStream, in which case we will need to
+    // use the special mapping from OldTypeStream -> NewTypeStream which was
+    // computed externally.  Regardless, we use this special map if and only if
+    // we are doing an id-only mapping.
+    if (!hasTypeStream())
+      return remapIndex(Idx, TypeLookup);
+
+    assert(TypeLookup.empty());
+    return remapIndex(Idx, IndexMap);
+  }
+  inline bool remapItemIndex(TypeIndex &Idx) {
+    assert(hasIdStream());
+    return remapIndex(Idx, IndexMap);
+  }
+
+  bool hasTypeStream() const {
+    return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
+  }
+
+  bool hasIdStream() const {
+    return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
+  }
+
+  ArrayRef<uint8_t> remapIndices(const CVType &OriginalType,
+                                 MutableArrayRef<uint8_t> Storage);
+
+  inline bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) {
+    if (LLVM_LIKELY(remapIndexSimple(Idx, Map)))
+      return true;
+
+    return remapIndexFallback(Idx, Map);
+  }
+
+  inline bool remapIndexSimple(TypeIndex &Idx, ArrayRef<TypeIndex> Map) const {
+    // Simple types are unchanged.
+    if (Idx.isSimple())
+      return true;
+
+    // Check if this type index refers to a record we've already translated
+    // successfully. If it refers to a type later in the stream or a record we
+    // had to defer, defer it until later pass.
+    unsigned MapPos = slotForIndex(Idx);
+    if (LLVM_UNLIKELY(MapPos >= Map.size() || Map[MapPos] == Untranslated))
+      return false;
+
+    Idx = Map[MapPos];
+    return true;
+  }
+
+  bool remapIndexFallback(TypeIndex &Idx, ArrayRef<TypeIndex> Map);
+
+  Error errorCorruptRecord() const {
+    return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
+  }
+
+  Expected<bool> shouldRemapType(const CVType &Type);
+
+  Optional<Error> LastError;
+
+  bool UseGlobalHashes = false;
+
+  bool IsSecondPass = false;
+
+  unsigned NumBadIndices = 0;
+
+  TypeIndex CurIndex{TypeIndex::FirstNonSimpleIndex};
+
+  MergingTypeTableBuilder *DestIdStream = nullptr;
+  MergingTypeTableBuilder *DestTypeStream = nullptr;
+
+  GlobalTypeTableBuilder *DestGlobalIdStream = nullptr;
+  GlobalTypeTableBuilder *DestGlobalTypeStream = nullptr;
+
+  ArrayRef<GloballyHashedType> GlobalHashes;
+
+  // If we're only mapping id records, this array contains the mapping for
+  // type records.
+  ArrayRef<TypeIndex> TypeLookup;
+
+  /// Map from source type index to destination type index. Indexed by source
+  /// type index minus 0x1000.
+  SmallVectorImpl<TypeIndex> &IndexMap;
+
+  /// Temporary storage that we use to copy a record's data while re-writing
+  /// its type indices.
+  SmallVector<uint8_t, 256> RemapStorage;
+
+  Optional<uint32_t> PCHSignature;
+};
+
+} // end anonymous namespace
+
+const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
+
+static bool isIdRecord(TypeLeafKind K) {
+  switch (K) {
+  case TypeLeafKind::LF_FUNC_ID:
+  case TypeLeafKind::LF_MFUNC_ID:
+  case TypeLeafKind::LF_STRING_ID:
+  case TypeLeafKind::LF_SUBSTR_LIST:
+  case TypeLeafKind::LF_BUILDINFO:
+  case TypeLeafKind::LF_UDT_SRC_LINE:
+  case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
+    return true;
+  default:
+    return false;
+  }
+}
+
+void TypeStreamMerger::addMapping(TypeIndex Idx) {
+  if (!IsSecondPass) {
+    assert(IndexMap.size() == slotForIndex(CurIndex) &&
+           "visitKnownRecord should add one index map entry");
+    IndexMap.push_back(Idx);
+  } else {
+    assert(slotForIndex(CurIndex) < IndexMap.size());
+    IndexMap[slotForIndex(CurIndex)] = Idx;
+  }
+}
+
+bool TypeStreamMerger::remapIndexFallback(TypeIndex &Idx,
+                                          ArrayRef<TypeIndex> Map) {
+  size_t MapPos = slotForIndex(Idx);
+
+  // If this is the second pass and this index isn't in the map, then it points
+  // outside the current type stream, and this is a corrupt record.
+  if (IsSecondPass && MapPos >= Map.size()) {
+    // FIXME: Print a more useful error. We can give the current record and the
+    // index that we think its pointing to.
+    if (LastError)
+      LastError = joinErrors(std::move(*LastError), errorCorruptRecord());
+    else
+      LastError = errorCorruptRecord();
+  }
+
+  ++NumBadIndices;
+
+  // This type index is invalid. Remap this to "not translated by cvpack",
+  // and return failure.
+  Idx = Untranslated;
+  return false;
+}
+
+// Local hashing entry points
+Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest,
+                                         const CVTypeArray &Types) {
+  DestTypeStream = &Dest;
+  UseGlobalHashes = false;
+
+  return doit(Types);
+}
+
+Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest,
+                                       ArrayRef<TypeIndex> TypeSourceToDest,
+                                       const CVTypeArray &Ids) {
+  DestIdStream = &Dest;
+  TypeLookup = TypeSourceToDest;
+  UseGlobalHashes = false;
+
+  return doit(Ids);
+}
+
+Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
+                                         MergingTypeTableBuilder &DestTypes,
+                                         const CVTypeArray &IdsAndTypes,
+                                         Optional<uint32_t> &S) {
+  DestIdStream = &DestIds;
+  DestTypeStream = &DestTypes;
+  UseGlobalHashes = false;
+  auto Err = doit(IdsAndTypes);
+  S = PCHSignature;
+  return Err;
+}
+
+// Global hashing entry points
+Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+                                         const CVTypeArray &Types,
+                                         ArrayRef<GloballyHashedType> Hashes,
+                                         Optional<uint32_t> &S) {
+  DestGlobalTypeStream = &Dest;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
+  auto Err = doit(Types);
+  S = PCHSignature;
+  return Err;
+}
+
+Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                                       ArrayRef<TypeIndex> TypeSourceToDest,
+                                       const CVTypeArray &Ids,
+                                       ArrayRef<GloballyHashedType> Hashes) {
+  DestGlobalIdStream = &Dest;
+  TypeLookup = TypeSourceToDest;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
+
+  return doit(Ids);
+}
+
+Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+                                         GlobalTypeTableBuilder &DestTypes,
+                                         const CVTypeArray &IdsAndTypes,
+                                         ArrayRef<GloballyHashedType> Hashes,
+                                         Optional<uint32_t> &S) {
+  DestGlobalIdStream = &DestIds;
+  DestGlobalTypeStream = &DestTypes;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
+  auto Err = doit(IdsAndTypes);
+  S = PCHSignature;
+  return Err;
+}
+
+Error TypeStreamMerger::doit(const CVTypeArray &Types) {
+  if (auto EC = remapAllTypes(Types))
+    return EC;
+
+  // If we found bad indices but no other errors, try doing another pass and see
+  // if we can resolve the indices that weren't in the map on the first pass.
+  // This may require multiple passes, but we should always make progress. MASM
+  // is the only known CodeView producer that makes type streams that aren't
+  // topologically sorted. The standard library contains MASM-produced objects,
+  // so this is important to handle correctly, but we don't have to be too
+  // efficient. MASM type streams are usually very small.
+  while (!LastError && NumBadIndices > 0) {
+    unsigned BadIndicesRemaining = NumBadIndices;
+    IsSecondPass = true;
+    NumBadIndices = 0;
+    CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
+
+    if (auto EC = remapAllTypes(Types))
+      return EC;
+
+    assert(NumBadIndices <= BadIndicesRemaining &&
+           "second pass found more bad indices");
+    if (!LastError && NumBadIndices == BadIndicesRemaining) {
+      return llvm::make_error<CodeViewError>(
+          cv_error_code::corrupt_record, "Input type graph contains cycles");
+    }
+  }
+
+  if (LastError)
+    return std::move(*LastError);
+  return Error::success();
+}
+
+Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) {
+  BinaryStreamRef Stream = Types.getUnderlyingStream();
+  ArrayRef<uint8_t> Buffer;
+  cantFail(Stream.readBytes(0, Stream.getLength(), Buffer));
+
+  return forEachCodeViewRecord<CVType>(
+      Buffer, [this](const CVType &T) { return remapType(T); });
+}
+
+Error TypeStreamMerger::remapType(const CVType &Type) {
+  auto R = shouldRemapType(Type);
+  if (!R)
+    return R.takeError();
+
+  TypeIndex DestIdx = Untranslated;
+  if (*R) {
+    auto DoSerialize =
+        [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> {
+      return remapIndices(Type, Storage);
+    };
+    if (LLVM_LIKELY(UseGlobalHashes)) {
+      GlobalTypeTableBuilder &Dest =
+          isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
+      GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
+      DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize);
+    } else {
+      MergingTypeTableBuilder &Dest =
+          isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
+
+      RemapStorage.resize(Type.RecordData.size());
+      ArrayRef<uint8_t> Result = DoSerialize(RemapStorage);
+      if (!Result.empty())
+        DestIdx = Dest.insertRecordBytes(Result);
+    }
+  }
+  addMapping(DestIdx);
+
+  ++CurIndex;
+  assert((IsSecondPass || IndexMap.size() == slotForIndex(CurIndex)) &&
+         "visitKnownRecord should add one index map entry");
+  return Error::success();
+}
+
+ArrayRef<uint8_t>
+TypeStreamMerger::remapIndices(const CVType &OriginalType,
+                               MutableArrayRef<uint8_t> Storage) {
+  SmallVector<TiReference, 4> Refs;
+  discoverTypeIndices(OriginalType.RecordData, Refs);
+  if (Refs.empty())
+    return OriginalType.RecordData;
+
+  ::memcpy(Storage.data(), OriginalType.RecordData.data(),
+           OriginalType.RecordData.size());
+
+  uint8_t *DestContent = Storage.data() + sizeof(RecordPrefix);
+
+  for (auto &Ref : Refs) {
+    TypeIndex *DestTIs =
+        reinterpret_cast<TypeIndex *>(DestContent + Ref.Offset);
+
+    for (size_t I = 0; I < Ref.Count; ++I) {
+      TypeIndex &TI = DestTIs[I];
+      bool Success = (Ref.Kind == TiRefKind::IndexRef) ? remapItemIndex(TI)
+                                                       : remapTypeIndex(TI);
+      if (LLVM_UNLIKELY(!Success))
+        return {};
+    }
+  }
+  return Storage;
+}
+
+Error llvm::codeview::mergeTypeRecords(MergingTypeTableBuilder &Dest,
+                                       SmallVectorImpl<TypeIndex> &SourceToDest,
+                                       const CVTypeArray &Types) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypeRecords(Dest, Types);
+}
+
+Error llvm::codeview::mergeIdRecords(MergingTypeTableBuilder &Dest,
+                                     ArrayRef<TypeIndex> TypeSourceToDest,
+                                     SmallVectorImpl<TypeIndex> &SourceToDest,
+                                     const CVTypeArray &Ids) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
+}
+
+Error llvm::codeview::mergeTypeAndIdRecords(
+    MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes,
+    SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
+    Optional<uint32_t> &PCHSignature) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHSignature);
+}
+
+Error llvm::codeview::mergeTypeAndIdRecords(
+    GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
+    SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
+    ArrayRef<GloballyHashedType> Hashes, Optional<uint32_t> &PCHSignature) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes,
+                            PCHSignature);
+}
+
+Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+                                       SmallVectorImpl<TypeIndex> &SourceToDest,
+                                       const CVTypeArray &Types,
+                                       ArrayRef<GloballyHashedType> Hashes,
+                                       Optional<uint32_t> &PCHSignature) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypeRecords(Dest, Types, Hashes, PCHSignature);
+}
+
+Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                                     ArrayRef<TypeIndex> Types,
+                                     SmallVectorImpl<TypeIndex> &SourceToDest,
+                                     const CVTypeArray &Ids,
+                                     ArrayRef<GloballyHashedType> Hashes) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeIdRecords(Dest, Types, Ids, Hashes);
+}
+
+Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) {
+  // For object files containing precompiled types, we need to extract the
+  // signature, through EndPrecompRecord. This is done here for performance
+  // reasons, to avoid re-parsing the Types stream.
+  if (Type.kind() == LF_ENDPRECOMP) {
+    EndPrecompRecord EP;
+    if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type),
+                                                  EP))
+      return joinErrors(std::move(EC), errorCorruptRecord());
+    if (PCHSignature.hasValue())
+      return errorCorruptRecord();
+    PCHSignature.emplace(EP.getSignature());
+    return false;
+  }
+  return true;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp
new file mode 100644
index 0000000..cf951ba
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp
@@ -0,0 +1,65 @@
+//===- TypeTableCollection.cpp -------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records)
+    : NameStorage(Allocator), Records(Records) {
+  Names.resize(Records.size());
+}
+
+Optional<TypeIndex> TypeTableCollection::getFirst() {
+  if (empty())
+    return None;
+  return TypeIndex::fromArrayIndex(0);
+}
+
+Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
+  assert(contains(Prev));
+  ++Prev;
+  if (Prev.toArrayIndex() == size())
+    return None;
+  return Prev;
+}
+
+CVType TypeTableCollection::getType(TypeIndex Index) {
+  assert(Index.toArrayIndex() < Records.size());
+  ArrayRef<uint8_t> Bytes = Records[Index.toArrayIndex()];
+  const RecordPrefix *Prefix =
+      reinterpret_cast<const RecordPrefix *>(Bytes.data());
+  TypeLeafKind Kind = static_cast<TypeLeafKind>(uint16_t(Prefix->RecordKind));
+  return CVType(Kind, Bytes);
+}
+
+StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
+  if (Index.isNoneType() || Index.isSimple())
+    return TypeIndex::simpleTypeName(Index);
+
+  uint32_t I = Index.toArrayIndex();
+  if (Names[I].data() == nullptr) {
+    StringRef Result = NameStorage.save(computeTypeName(*this, Index));
+    Names[I] = Result;
+  }
+  return Names[I];
+}
+
+bool TypeTableCollection::contains(TypeIndex Index) {
+  return Index.toArrayIndex() <= size();
+}
+
+uint32_t TypeTableCollection::size() { return Records.size(); }
+
+uint32_t TypeTableCollection::capacity() { return Records.size(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
new file mode 100644
index 0000000..b4770e5
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -0,0 +1,33 @@
+add_llvm_library(LLVMDebugInfoDWARF
+  DWARFAbbreviationDeclaration.cpp
+  DWARFAddressRange.cpp
+  DWARFAcceleratorTable.cpp
+  DWARFCompileUnit.cpp
+  DWARFContext.cpp
+  DWARFDataExtractor.cpp
+  DWARFDebugAbbrev.cpp
+  DWARFDebugAddr.cpp
+  DWARFDebugArangeSet.cpp
+  DWARFDebugAranges.cpp
+  DWARFDebugFrame.cpp
+  DWARFDebugInfoEntry.cpp
+  DWARFDebugLine.cpp
+  DWARFDebugLoc.cpp
+  DWARFDebugMacro.cpp
+  DWARFDebugPubTable.cpp
+  DWARFDebugRangeList.cpp
+  DWARFDebugRnglists.cpp
+  DWARFDie.cpp
+  DWARFExpression.cpp
+  DWARFFormValue.cpp
+  DWARFGdbIndex.cpp
+  DWARFListTable.cpp
+  DWARFTypeUnit.cpp
+  DWARFUnitIndex.cpp
+  DWARFUnit.cpp
+  DWARFVerifier.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/DWARF
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo
+  )
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 0000000..f49ab40
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -0,0 +1,216 @@
+//===- DWARFAbbreviationDeclaration.cpp -----------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace dwarf;
+
+void DWARFAbbreviationDeclaration::clear() {
+  Code = 0;
+  Tag = DW_TAG_null;
+  CodeByteSize = 0;
+  HasChildren = false;
+  AttributeSpecs.clear();
+  FixedAttributeSize.reset();
+}
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
+  clear();
+}
+
+bool
+DWARFAbbreviationDeclaration::extract(DataExtractor Data,
+                                      uint32_t* OffsetPtr) {
+  clear();
+  const uint32_t Offset = *OffsetPtr;
+  Code = Data.getULEB128(OffsetPtr);
+  if (Code == 0) {
+    return false;
+  }
+  CodeByteSize = *OffsetPtr - Offset;
+  Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr));
+  if (Tag == DW_TAG_null) {
+    clear();
+    return false;
+  }
+  uint8_t ChildrenByte = Data.getU8(OffsetPtr);
+  HasChildren = (ChildrenByte == DW_CHILDREN_yes);
+  // Assign a value to our optional FixedAttributeSize member variable. If
+  // this member variable still has a value after the while loop below, then
+  // all attribute data in this abbreviation declaration has a fixed byte size.
+  FixedAttributeSize = FixedSizeInfo();
+
+  // Read all of the abbreviation attributes and forms.
+  while (true) {
+    auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr));
+    auto F = static_cast<Form>(Data.getULEB128(OffsetPtr));
+    if (A && F) {
+      bool IsImplicitConst = (F == DW_FORM_implicit_const);
+      if (IsImplicitConst) {
+        int64_t V = Data.getSLEB128(OffsetPtr);
+        AttributeSpecs.push_back(AttributeSpec(A, F, V));
+        continue;
+      }
+      Optional<uint8_t> ByteSize;
+      // If this abbrevation still has a fixed byte size, then update the
+      // FixedAttributeSize as needed.
+      switch (F) {
+      case DW_FORM_addr:
+        if (FixedAttributeSize)
+          ++FixedAttributeSize->NumAddrs;
+        break;
+
+      case DW_FORM_ref_addr:
+        if (FixedAttributeSize)
+          ++FixedAttributeSize->NumRefAddrs;
+        break;
+
+      case DW_FORM_strp:
+      case DW_FORM_GNU_ref_alt:
+      case DW_FORM_GNU_strp_alt:
+      case DW_FORM_line_strp:
+      case DW_FORM_sec_offset:
+      case DW_FORM_strp_sup:
+        if (FixedAttributeSize)
+          ++FixedAttributeSize->NumDwarfOffsets;
+        break;
+
+      default:
+        // The form has a byte size that doesn't depend on Params.
+        // If it's a fixed size, keep track of it.
+        if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) {
+          if (FixedAttributeSize)
+            FixedAttributeSize->NumBytes += *ByteSize;
+          break;
+        }
+        // Indicate we no longer have a fixed byte size for this
+        // abbreviation by clearing the FixedAttributeSize optional value
+        // so it doesn't have a value.
+        FixedAttributeSize.reset();
+        break;
+      }
+      // Record this attribute and its fixed size if it has one.
+      AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize));
+    } else if (A == 0 && F == 0) {
+      // We successfully reached the end of this abbreviation declaration
+      // since both attribute and form are zero.
+      break;
+    } else {
+      // Attribute and form pairs must either both be non-zero, in which case
+      // they are added to the abbreviation declaration, or both be zero to
+      // terminate the abbrevation declaration. In this case only one was
+      // zero which is an error.
+      clear();
+      return false;
+    }
+  }
+  return true;
+}
+
+void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
+  OS << '[' << getCode() << "] ";
+  OS << formatv("{0}", getTag());
+  OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
+  for (const AttributeSpec &Spec : AttributeSpecs) {
+    OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
+    if (Spec.isImplicitConst())
+      OS << '\t' << Spec.getImplicitConstValue();
+    OS << '\n';
+  }
+  OS << '\n';
+}
+
+Optional<uint32_t>
+DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const {
+  for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
+    if (AttributeSpecs[i].Attr == Attr)
+      return i;
+  }
+  return None;
+}
+
+Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(
+    const uint32_t DIEOffset, const dwarf::Attribute Attr,
+    const DWARFUnit &U) const {
+  Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr);
+  if (!MatchAttrIndex)
+    return None;
+
+  auto DebugInfoData = U.getDebugInfoExtractor();
+
+  // Add the byte size of ULEB that for the abbrev Code so we can start
+  // skipping the attribute data.
+  uint32_t Offset = DIEOffset + CodeByteSize;
+  uint32_t AttrIndex = 0;
+  for (const auto &Spec : AttributeSpecs) {
+    if (*MatchAttrIndex == AttrIndex) {
+      // We have arrived at the attribute to extract, extract if from Offset.
+      DWARFFormValue FormValue(Spec.Form);
+      if (Spec.isImplicitConst()) {
+        FormValue.setSValue(Spec.getImplicitConstValue());
+        return FormValue;
+      }
+      if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U))
+        return FormValue;
+    }
+    // March Offset along until we get to the attribute we want.
+    if (auto FixedSize = Spec.getByteSize(U))
+      Offset += *FixedSize;
+    else
+      DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset,
+                                U.getFormParams());
+    ++AttrIndex;
+  }
+  return None;
+}
+
+size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize(
+    const DWARFUnit &U) const {
+  size_t ByteSize = NumBytes;
+  if (NumAddrs)
+    ByteSize += NumAddrs * U.getAddressByteSize();
+  if (NumRefAddrs)
+    ByteSize += NumRefAddrs * U.getRefAddrByteSize();
+  if (NumDwarfOffsets)
+    ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize();
+  return ByteSize;
+}
+
+Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(
+    const DWARFUnit &U) const {
+  if (isImplicitConst())
+    return 0;
+  if (ByteSize.HasByteSize)
+    return ByteSize.ByteSize;
+  Optional<int64_t> S;
+  auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams());
+  if (FixedByteSize)
+    S = *FixedByteSize;
+  return S;
+}
+
+Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize(
+    const DWARFUnit &U) const {
+  if (FixedAttributeSize)
+    return FixedAttributeSize->getByteSize(U);
+  return None;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
new file mode 100644
index 0000000..54daf34
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -0,0 +1,887 @@
+//===- DWARFAcceleratorTable.cpp ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+struct Atom {
+  unsigned Value;
+};
+
+static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
+  StringRef Str = dwarf::AtomTypeString(A.Value);
+  if (!Str.empty())
+    return OS << Str;
+  return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
+}
+} // namespace
+
+static Atom formatAtom(unsigned Atom) { return {Atom}; }
+
+DWARFAcceleratorTable::~DWARFAcceleratorTable() = default;
+
+llvm::Error AppleAcceleratorTable::extract() {
+  uint32_t Offset = 0;
+
+  // Check that we can at least read the header.
+  if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4))
+    return createStringError(errc::illegal_byte_sequence,
+                             "Section too small: cannot read header.");
+
+  Hdr.Magic = AccelSection.getU32(&Offset);
+  Hdr.Version = AccelSection.getU16(&Offset);
+  Hdr.HashFunction = AccelSection.getU16(&Offset);
+  Hdr.BucketCount = AccelSection.getU32(&Offset);
+  Hdr.HashCount = AccelSection.getU32(&Offset);
+  Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
+
+  // Check that we can read all the hashes and offsets from the
+  // section (see SourceLevelDebugging.rst for the structure of the index).
+  // We need to substract one because we're checking for an *offset* which is
+  // equal to the size for an empty table and hence pointer after the section.
+  if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
+                                  Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1))
+    return createStringError(
+        errc::illegal_byte_sequence,
+        "Section too small: cannot read buckets and hashes.");
+
+  HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
+  uint32_t NumAtoms = AccelSection.getU32(&Offset);
+
+  for (unsigned i = 0; i < NumAtoms; ++i) {
+    uint16_t AtomType = AccelSection.getU16(&Offset);
+    auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset));
+    HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
+  }
+
+  IsValid = true;
+  return Error::success();
+}
+
+uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; }
+uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; }
+uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); }
+uint32_t AppleAcceleratorTable::getHeaderDataLength() {
+  return Hdr.HeaderDataLength;
+}
+
+ArrayRef<std::pair<AppleAcceleratorTable::HeaderData::AtomType,
+                   AppleAcceleratorTable::HeaderData::Form>>
+AppleAcceleratorTable::getAtomsDesc() {
+  return HdrData.Atoms;
+}
+
+bool AppleAcceleratorTable::validateForms() {
+  for (auto Atom : getAtomsDesc()) {
+    DWARFFormValue FormValue(Atom.second);
+    switch (Atom.first) {
+    case dwarf::DW_ATOM_die_offset:
+    case dwarf::DW_ATOM_die_tag:
+    case dwarf::DW_ATOM_type_flags:
+      if ((!FormValue.isFormClass(DWARFFormValue::FC_Constant) &&
+           !FormValue.isFormClass(DWARFFormValue::FC_Flag)) ||
+          FormValue.getForm() == dwarf::DW_FORM_sdata)
+        return false;
+      break;
+    default:
+      break;
+    }
+  }
+  return true;
+}
+
+std::pair<uint32_t, dwarf::Tag>
+AppleAcceleratorTable::readAtoms(uint32_t &HashDataOffset) {
+  uint32_t DieOffset = dwarf::DW_INVALID_OFFSET;
+  dwarf::Tag DieTag = dwarf::DW_TAG_null;
+  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
+
+  for (auto Atom : getAtomsDesc()) {
+    DWARFFormValue FormValue(Atom.second);
+    FormValue.extractValue(AccelSection, &HashDataOffset, FormParams);
+    switch (Atom.first) {
+    case dwarf::DW_ATOM_die_offset:
+      DieOffset = *FormValue.getAsUnsignedConstant();
+      break;
+    case dwarf::DW_ATOM_die_tag:
+      DieTag = (dwarf::Tag)*FormValue.getAsUnsignedConstant();
+      break;
+    default:
+      break;
+    }
+  }
+  return {DieOffset, DieTag};
+}
+
+void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const {
+  DictScope HeaderScope(W, "Header");
+  W.printHex("Magic", Magic);
+  W.printHex("Version", Version);
+  W.printHex("Hash function", HashFunction);
+  W.printNumber("Bucket count", BucketCount);
+  W.printNumber("Hashes count", HashCount);
+  W.printNumber("HeaderData length", HeaderDataLength);
+}
+
+Optional<uint64_t> AppleAcceleratorTable::HeaderData::extractOffset(
+    Optional<DWARFFormValue> Value) const {
+  if (!Value)
+    return None;
+
+  switch (Value->getForm()) {
+  case dwarf::DW_FORM_ref1:
+  case dwarf::DW_FORM_ref2:
+  case dwarf::DW_FORM_ref4:
+  case dwarf::DW_FORM_ref8:
+  case dwarf::DW_FORM_ref_udata:
+    return Value->getRawUValue() + DIEOffsetBase;
+  default:
+    return Value->getAsSectionOffset();
+  }
+}
+
+bool AppleAcceleratorTable::dumpName(ScopedPrinter &W,
+                                     SmallVectorImpl<DWARFFormValue> &AtomForms,
+                                     uint32_t *DataOffset) const {
+  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
+  uint32_t NameOffset = *DataOffset;
+  if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) {
+    W.printString("Incorrectly terminated list.");
+    return false;
+  }
+  unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset);
+  if (!StringOffset)
+    return false; // End of list
+
+  DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str());
+  W.startLine() << format("String: 0x%08x", StringOffset);
+  W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n";
+
+  unsigned NumData = AccelSection.getU32(DataOffset);
+  for (unsigned Data = 0; Data < NumData; ++Data) {
+    ListScope DataScope(W, ("Data " + Twine(Data)).str());
+    unsigned i = 0;
+    for (auto &Atom : AtomForms) {
+      W.startLine() << format("Atom[%d]: ", i);
+      if (Atom.extractValue(AccelSection, DataOffset, FormParams)) {
+        Atom.dump(W.getOStream());
+        if (Optional<uint64_t> Val = Atom.getAsUnsignedConstant()) {
+          StringRef Str = dwarf::AtomValueString(HdrData.Atoms[i].first, *Val);
+          if (!Str.empty())
+            W.getOStream() << " (" << Str << ")";
+        }
+      } else
+        W.getOStream() << "Error extracting the value";
+      W.getOStream() << "\n";
+      i++;
+    }
+  }
+  return true; // more entries follow
+}
+
+LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const {
+  if (!IsValid)
+    return;
+
+  ScopedPrinter W(OS);
+
+  Hdr.dump(W);
+
+  W.printNumber("DIE offset base", HdrData.DIEOffsetBase);
+  W.printNumber("Number of atoms", uint64_t(HdrData.Atoms.size()));
+  SmallVector<DWARFFormValue, 3> AtomForms;
+  {
+    ListScope AtomsScope(W, "Atoms");
+    unsigned i = 0;
+    for (const auto &Atom : HdrData.Atoms) {
+      DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
+      W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
+      W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
+      AtomForms.push_back(DWARFFormValue(Atom.second));
+    }
+  }
+
+  // Now go through the actual tables and dump them.
+  uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
+  unsigned HashesBase = Offset + Hdr.BucketCount * 4;
+  unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;
+
+  for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) {
+    unsigned Index = AccelSection.getU32(&Offset);
+
+    ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
+    if (Index == UINT32_MAX) {
+      W.printString("EMPTY");
+      continue;
+    }
+
+    for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
+      unsigned HashOffset = HashesBase + HashIdx*4;
+      unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
+      uint32_t Hash = AccelSection.getU32(&HashOffset);
+
+      if (Hash % Hdr.BucketCount != Bucket)
+        break;
+
+      unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
+      ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str());
+      if (!AccelSection.isValidOffset(DataOffset)) {
+        W.printString("Invalid section offset");
+        continue;
+      }
+      while (dumpName(W, AtomForms, &DataOffset))
+        /*empty*/;
+    }
+  }
+}
+
+AppleAcceleratorTable::Entry::Entry(
+    const AppleAcceleratorTable::HeaderData &HdrData)
+    : HdrData(&HdrData) {
+  Values.reserve(HdrData.Atoms.size());
+  for (const auto &Atom : HdrData.Atoms)
+    Values.push_back(DWARFFormValue(Atom.second));
+}
+
+void AppleAcceleratorTable::Entry::extract(
+    const AppleAcceleratorTable &AccelTable, uint32_t *Offset) {
+
+  dwarf::FormParams FormParams = {AccelTable.Hdr.Version, 0,
+                                  dwarf::DwarfFormat::DWARF32};
+  for (auto &Atom : Values)
+    Atom.extractValue(AccelTable.AccelSection, Offset, FormParams);
+}
+
+Optional<DWARFFormValue>
+AppleAcceleratorTable::Entry::lookup(HeaderData::AtomType Atom) const {
+  assert(HdrData && "Dereferencing end iterator?");
+  assert(HdrData->Atoms.size() == Values.size());
+  for (const auto &Tuple : zip_first(HdrData->Atoms, Values)) {
+    if (std::get<0>(Tuple).first == Atom)
+      return std::get<1>(Tuple);
+  }
+  return None;
+}
+
+Optional<uint64_t> AppleAcceleratorTable::Entry::getDIESectionOffset() const {
+  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_die_offset));
+}
+
+Optional<uint64_t> AppleAcceleratorTable::Entry::getCUOffset() const {
+  return HdrData->extractOffset(lookup(dwarf::DW_ATOM_cu_offset));
+}
+
+Optional<dwarf::Tag> AppleAcceleratorTable::Entry::getTag() const {
+  Optional<DWARFFormValue> Tag = lookup(dwarf::DW_ATOM_die_tag);
+  if (!Tag)
+    return None;
+  if (Optional<uint64_t> Value = Tag->getAsUnsignedConstant())
+    return dwarf::Tag(*Value);
+  return None;
+}
+
+AppleAcceleratorTable::ValueIterator::ValueIterator(
+    const AppleAcceleratorTable &AccelTable, unsigned Offset)
+    : AccelTable(&AccelTable), Current(AccelTable.HdrData), DataOffset(Offset) {
+  if (!AccelTable.AccelSection.isValidOffsetForDataOfSize(DataOffset, 4))
+    return;
+
+  // Read the first entry.
+  NumData = AccelTable.AccelSection.getU32(&DataOffset);
+  Next();
+}
+
+void AppleAcceleratorTable::ValueIterator::Next() {
+  assert(NumData > 0 && "attempted to increment iterator past the end");
+  auto &AccelSection = AccelTable->AccelSection;
+  if (Data >= NumData ||
+      !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
+    NumData = 0;
+    DataOffset = 0;
+    return;
+  }
+  Current.extract(*AccelTable, &DataOffset);
+  ++Data;
+}
+
+iterator_range<AppleAcceleratorTable::ValueIterator>
+AppleAcceleratorTable::equal_range(StringRef Key) const {
+  if (!IsValid)
+    return make_range(ValueIterator(), ValueIterator());
+
+  // Find the bucket.
+  unsigned HashValue = djbHash(Key);
+  unsigned Bucket = HashValue % Hdr.BucketCount;
+  unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength;
+  unsigned HashesBase = BucketBase + Hdr.BucketCount * 4;
+  unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4;
+
+  unsigned BucketOffset = BucketBase + Bucket * 4;
+  unsigned Index = AccelSection.getU32(&BucketOffset);
+
+  // Search through all hashes in the bucket.
+  for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) {
+    unsigned HashOffset = HashesBase + HashIdx * 4;
+    unsigned OffsetsOffset = OffsetsBase + HashIdx * 4;
+    uint32_t Hash = AccelSection.getU32(&HashOffset);
+
+    if (Hash % Hdr.BucketCount != Bucket)
+      // We are already in the next bucket.
+      break;
+
+    unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
+    unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset);
+    if (!StringOffset)
+      break;
+
+    // Finally, compare the key.
+    if (Key == StringSection.getCStr(&StringOffset))
+      return make_range({*this, DataOffset}, ValueIterator());
+  }
+  return make_range(ValueIterator(), ValueIterator());
+}
+
+void DWARFDebugNames::Header::dump(ScopedPrinter &W) const {
+  DictScope HeaderScope(W, "Header");
+  W.printHex("Length", UnitLength);
+  W.printNumber("Version", Version);
+  W.printHex("Padding", Padding);
+  W.printNumber("CU count", CompUnitCount);
+  W.printNumber("Local TU count", LocalTypeUnitCount);
+  W.printNumber("Foreign TU count", ForeignTypeUnitCount);
+  W.printNumber("Bucket count", BucketCount);
+  W.printNumber("Name count", NameCount);
+  W.printHex("Abbreviations table size", AbbrevTableSize);
+  W.startLine() << "Augmentation: '" << AugmentationString << "'\n";
+}
+
+llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
+                                             uint32_t *Offset) {
+  // Check that we can read the fixed-size part.
+  if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1))
+    return createStringError(errc::illegal_byte_sequence,
+                             "Section too small: cannot read header.");
+
+  UnitLength = AS.getU32(Offset);
+  Version = AS.getU16(Offset);
+  Padding = AS.getU16(Offset);
+  CompUnitCount = AS.getU32(Offset);
+  LocalTypeUnitCount = AS.getU32(Offset);
+  ForeignTypeUnitCount = AS.getU32(Offset);
+  BucketCount = AS.getU32(Offset);
+  NameCount = AS.getU32(Offset);
+  AbbrevTableSize = AS.getU32(Offset);
+  AugmentationStringSize = alignTo(AS.getU32(Offset), 4);
+
+  if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize))
+    return createStringError(
+        errc::illegal_byte_sequence,
+        "Section too small: cannot read header augmentation.");
+  AugmentationString.resize(AugmentationStringSize);
+  AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()),
+           AugmentationStringSize);
+  return Error::success();
+}
+
+void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const {
+  DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str());
+  W.startLine() << formatv("Tag: {0}\n", Tag);
+
+  for (const auto &Attr : Attributes)
+    W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
+}
+
+static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() {
+  return {dwarf::Index(0), dwarf::Form(0)};
+}
+
+static bool isSentinel(const DWARFDebugNames::AttributeEncoding &AE) {
+  return AE == sentinelAttrEnc();
+}
+
+static DWARFDebugNames::Abbrev sentinelAbbrev() {
+  return DWARFDebugNames::Abbrev(0, dwarf::Tag(0), {});
+}
+
+static bool isSentinel(const DWARFDebugNames::Abbrev &Abbr) {
+  return Abbr.Code == 0;
+}
+
+DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getEmptyKey() {
+  return sentinelAbbrev();
+}
+
+DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() {
+  return DWARFDebugNames::Abbrev(~0, dwarf::Tag(0), {});
+}
+
+Expected<DWARFDebugNames::AttributeEncoding>
+DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) {
+  if (*Offset >= EntriesBase) {
+    return createStringError(errc::illegal_byte_sequence,
+                             "Incorrectly terminated abbreviation table.");
+  }
+
+  uint32_t Index = Section.AccelSection.getULEB128(Offset);
+  uint32_t Form = Section.AccelSection.getULEB128(Offset);
+  return AttributeEncoding(dwarf::Index(Index), dwarf::Form(Form));
+}
+
+Expected<std::vector<DWARFDebugNames::AttributeEncoding>>
+DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) {
+  std::vector<AttributeEncoding> Result;
+  for (;;) {
+    auto AttrEncOr = extractAttributeEncoding(Offset);
+    if (!AttrEncOr)
+      return AttrEncOr.takeError();
+    if (isSentinel(*AttrEncOr))
+      return std::move(Result);
+
+    Result.emplace_back(*AttrEncOr);
+  }
+}
+
+Expected<DWARFDebugNames::Abbrev>
+DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) {
+  if (*Offset >= EntriesBase) {
+    return createStringError(errc::illegal_byte_sequence,
+                             "Incorrectly terminated abbreviation table.");
+  }
+
+  uint32_t Code = Section.AccelSection.getULEB128(Offset);
+  if (Code == 0)
+    return sentinelAbbrev();
+
+  uint32_t Tag = Section.AccelSection.getULEB128(Offset);
+  auto AttrEncOr = extractAttributeEncodings(Offset);
+  if (!AttrEncOr)
+    return AttrEncOr.takeError();
+  return Abbrev(Code, dwarf::Tag(Tag), std::move(*AttrEncOr));
+}
+
+Error DWARFDebugNames::NameIndex::extract() {
+  const DWARFDataExtractor &AS = Section.AccelSection;
+  uint32_t Offset = Base;
+  if (Error E = Hdr.extract(AS, &Offset))
+    return E;
+
+  CUsBase = Offset;
+  Offset += Hdr.CompUnitCount * 4;
+  Offset += Hdr.LocalTypeUnitCount * 4;
+  Offset += Hdr.ForeignTypeUnitCount * 8;
+  BucketsBase = Offset;
+  Offset += Hdr.BucketCount * 4;
+  HashesBase = Offset;
+  if (Hdr.BucketCount > 0)
+    Offset += Hdr.NameCount * 4;
+  StringOffsetsBase = Offset;
+  Offset += Hdr.NameCount * 4;
+  EntryOffsetsBase = Offset;
+  Offset += Hdr.NameCount * 4;
+
+  if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize))
+    return createStringError(errc::illegal_byte_sequence,
+                             "Section too small: cannot read abbreviations.");
+
+  EntriesBase = Offset + Hdr.AbbrevTableSize;
+
+  for (;;) {
+    auto AbbrevOr = extractAbbrev(&Offset);
+    if (!AbbrevOr)
+      return AbbrevOr.takeError();
+    if (isSentinel(*AbbrevOr))
+      return Error::success();
+
+    if (!Abbrevs.insert(std::move(*AbbrevOr)).second)
+      return createStringError(errc::invalid_argument,
+                               "Duplicate abbreviation code.");
+  }
+}
+DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr)
+    : NameIdx(&NameIdx), Abbr(&Abbr) {
+  // This merely creates form values. It is up to the caller
+  // (NameIndex::getEntry) to populate them.
+  Values.reserve(Abbr.Attributes.size());
+  for (const auto &Attr : Abbr.Attributes)
+    Values.emplace_back(Attr.Form);
+}
+
+Optional<DWARFFormValue>
+DWARFDebugNames::Entry::lookup(dwarf::Index Index) const {
+  assert(Abbr->Attributes.size() == Values.size());
+  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
+    if (std::get<0>(Tuple).Index == Index)
+      return std::get<1>(Tuple);
+  }
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getDIEUnitOffset() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_die_offset))
+    return Off->getAsReferenceUVal();
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getCUIndex() const {
+  if (Optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
+    return Off->getAsUnsignedConstant();
+  // In a per-CU index, the entries without a DW_IDX_compile_unit attribute
+  // implicitly refer to the single CU.
+  if (NameIdx->getCUCount() == 1)
+    return 0;
+  return None;
+}
+
+Optional<uint64_t> DWARFDebugNames::Entry::getCUOffset() const {
+  Optional<uint64_t> Index = getCUIndex();
+  if (!Index || *Index >= NameIdx->getCUCount())
+    return None;
+  return NameIdx->getCUOffset(*Index);
+}
+
+void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const {
+  W.printHex("Abbrev", Abbr->Code);
+  W.startLine() << formatv("Tag: {0}\n", Abbr->Tag);
+  assert(Abbr->Attributes.size() == Values.size());
+  for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) {
+    W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
+    std::get<1>(Tuple).dump(W.getOStream());
+    W.getOStream() << '\n';
+  }
+}
+
+char DWARFDebugNames::SentinelError::ID;
+std::error_code DWARFDebugNames::SentinelError::convertToErrorCode() const {
+  return inconvertibleErrorCode();
+}
+
+uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const {
+  assert(CU < Hdr.CompUnitCount);
+  uint32_t Offset = CUsBase + 4 * CU;
+  return Section.AccelSection.getRelocatedValue(4, &Offset);
+}
+
+uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const {
+  assert(TU < Hdr.LocalTypeUnitCount);
+  uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4;
+  return Section.AccelSection.getRelocatedValue(4, &Offset);
+}
+
+uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const {
+  assert(TU < Hdr.ForeignTypeUnitCount);
+  uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4;
+  return Section.AccelSection.getU64(&Offset);
+}
+
+Expected<DWARFDebugNames::Entry>
+DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const {
+  const DWARFDataExtractor &AS = Section.AccelSection;
+  if (!AS.isValidOffset(*Offset))
+    return createStringError(errc::illegal_byte_sequence,
+                             "Incorrectly terminated entry list.");
+
+  uint32_t AbbrevCode = AS.getULEB128(Offset);
+  if (AbbrevCode == 0)
+    return make_error<SentinelError>();
+
+  const auto AbbrevIt = Abbrevs.find_as(AbbrevCode);
+  if (AbbrevIt == Abbrevs.end())
+    return createStringError(errc::invalid_argument, "Invalid abbreviation.");
+
+  Entry E(*this, *AbbrevIt);
+
+  dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32};
+  for (auto &Value : E.Values) {
+    if (!Value.extractValue(AS, Offset, FormParams))
+      return createStringError(errc::io_error,
+                               "Error extracting index attribute values.");
+  }
+  return std::move(E);
+}
+
+DWARFDebugNames::NameTableEntry
+DWARFDebugNames::NameIndex::getNameTableEntry(uint32_t Index) const {
+  assert(0 < Index && Index <= Hdr.NameCount);
+  uint32_t StringOffsetOffset = StringOffsetsBase + 4 * (Index - 1);
+  uint32_t EntryOffsetOffset = EntryOffsetsBase + 4 * (Index - 1);
+  const DWARFDataExtractor &AS = Section.AccelSection;
+
+  uint32_t StringOffset = AS.getRelocatedValue(4, &StringOffsetOffset);
+  uint32_t EntryOffset = AS.getU32(&EntryOffsetOffset);
+  EntryOffset += EntriesBase;
+  return {Section.StringSection, Index, StringOffset, EntryOffset};
+}
+
+uint32_t
+DWARFDebugNames::NameIndex::getBucketArrayEntry(uint32_t Bucket) const {
+  assert(Bucket < Hdr.BucketCount);
+  uint32_t BucketOffset = BucketsBase + 4 * Bucket;
+  return Section.AccelSection.getU32(&BucketOffset);
+}
+
+uint32_t DWARFDebugNames::NameIndex::getHashArrayEntry(uint32_t Index) const {
+  assert(0 < Index && Index <= Hdr.NameCount);
+  uint32_t HashOffset = HashesBase + 4 * (Index - 1);
+  return Section.AccelSection.getU32(&HashOffset);
+}
+
+// Returns true if we should continue scanning for entries, false if this is the
+// last (sentinel) entry). In case of a parsing error we also return false, as
+// it's not possible to recover this entry list (but the other lists may still
+// parse OK).
+bool DWARFDebugNames::NameIndex::dumpEntry(ScopedPrinter &W,
+                                           uint32_t *Offset) const {
+  uint32_t EntryId = *Offset;
+  auto EntryOr = getEntry(Offset);
+  if (!EntryOr) {
+    handleAllErrors(EntryOr.takeError(), [](const SentinelError &) {},
+                    [&W](const ErrorInfoBase &EI) { EI.log(W.startLine()); });
+    return false;
+  }
+
+  DictScope EntryScope(W, ("Entry @ 0x" + Twine::utohexstr(EntryId)).str());
+  EntryOr->dump(W);
+  return true;
+}
+
+void DWARFDebugNames::NameIndex::dumpName(ScopedPrinter &W,
+                                          const NameTableEntry &NTE,
+                                          Optional<uint32_t> Hash) const {
+  DictScope NameScope(W, ("Name " + Twine(NTE.getIndex())).str());
+  if (Hash)
+    W.printHex("Hash", *Hash);
+
+  W.startLine() << format("String: 0x%08x", NTE.getStringOffset());
+  W.getOStream() << " \"" << NTE.getString() << "\"\n";
+
+  uint32_t EntryOffset = NTE.getEntryOffset();
+  while (dumpEntry(W, &EntryOffset))
+    /*empty*/;
+}
+
+void DWARFDebugNames::NameIndex::dumpCUs(ScopedPrinter &W) const {
+  ListScope CUScope(W, "Compilation Unit offsets");
+  for (uint32_t CU = 0; CU < Hdr.CompUnitCount; ++CU)
+    W.startLine() << format("CU[%u]: 0x%08x\n", CU, getCUOffset(CU));
+}
+
+void DWARFDebugNames::NameIndex::dumpLocalTUs(ScopedPrinter &W) const {
+  if (Hdr.LocalTypeUnitCount == 0)
+    return;
+
+  ListScope TUScope(W, "Local Type Unit offsets");
+  for (uint32_t TU = 0; TU < Hdr.LocalTypeUnitCount; ++TU)
+    W.startLine() << format("LocalTU[%u]: 0x%08x\n", TU, getLocalTUOffset(TU));
+}
+
+void DWARFDebugNames::NameIndex::dumpForeignTUs(ScopedPrinter &W) const {
+  if (Hdr.ForeignTypeUnitCount == 0)
+    return;
+
+  ListScope TUScope(W, "Foreign Type Unit signatures");
+  for (uint32_t TU = 0; TU < Hdr.ForeignTypeUnitCount; ++TU) {
+    W.startLine() << format("ForeignTU[%u]: 0x%016" PRIx64 "\n", TU,
+                            getForeignTUSignature(TU));
+  }
+}
+
+void DWARFDebugNames::NameIndex::dumpAbbreviations(ScopedPrinter &W) const {
+  ListScope AbbrevsScope(W, "Abbreviations");
+  for (const auto &Abbr : Abbrevs)
+    Abbr.dump(W);
+}
+
+void DWARFDebugNames::NameIndex::dumpBucket(ScopedPrinter &W,
+                                            uint32_t Bucket) const {
+  ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str());
+  uint32_t Index = getBucketArrayEntry(Bucket);
+  if (Index == 0) {
+    W.printString("EMPTY");
+    return;
+  }
+  if (Index > Hdr.NameCount) {
+    W.printString("Name index is invalid");
+    return;
+  }
+
+  for (; Index <= Hdr.NameCount; ++Index) {
+    uint32_t Hash = getHashArrayEntry(Index);
+    if (Hash % Hdr.BucketCount != Bucket)
+      break;
+
+    dumpName(W, getNameTableEntry(Index), Hash);
+  }
+}
+
+LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const {
+  DictScope UnitScope(W, ("Name Index @ 0x" + Twine::utohexstr(Base)).str());
+  Hdr.dump(W);
+  dumpCUs(W);
+  dumpLocalTUs(W);
+  dumpForeignTUs(W);
+  dumpAbbreviations(W);
+
+  if (Hdr.BucketCount > 0) {
+    for (uint32_t Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket)
+      dumpBucket(W, Bucket);
+    return;
+  }
+
+  W.startLine() << "Hash table not present\n";
+  for (NameTableEntry NTE : *this)
+    dumpName(W, NTE, None);
+}
+
+llvm::Error DWARFDebugNames::extract() {
+  uint32_t Offset = 0;
+  while (AccelSection.isValidOffset(Offset)) {
+    NameIndex Next(*this, Offset);
+    if (llvm::Error E = Next.extract())
+      return E;
+    Offset = Next.getNextUnitOffset();
+    NameIndices.push_back(std::move(Next));
+  }
+  return Error::success();
+}
+
+iterator_range<DWARFDebugNames::ValueIterator>
+DWARFDebugNames::NameIndex::equal_range(StringRef Key) const {
+  return make_range(ValueIterator(*this, Key), ValueIterator());
+}
+
+LLVM_DUMP_METHOD void DWARFDebugNames::dump(raw_ostream &OS) const {
+  ScopedPrinter W(OS);
+  for (const NameIndex &NI : NameIndices)
+    NI.dump(W);
+}
+
+Optional<uint32_t>
+DWARFDebugNames::ValueIterator::findEntryOffsetInCurrentIndex() {
+  const Header &Hdr = CurrentIndex->Hdr;
+  if (Hdr.BucketCount == 0) {
+    // No Hash Table, We need to search through all names in the Name Index.
+    for (NameTableEntry NTE : *CurrentIndex) {
+      if (NTE.getString() == Key)
+        return NTE.getEntryOffset();
+    }
+    return None;
+  }
+
+  // The Name Index has a Hash Table, so use that to speed up the search.
+  // Compute the Key Hash, if it has not been done already.
+  if (!Hash)
+    Hash = caseFoldingDjbHash(Key);
+  uint32_t Bucket = *Hash % Hdr.BucketCount;
+  uint32_t Index = CurrentIndex->getBucketArrayEntry(Bucket);
+  if (Index == 0)
+    return None; // Empty bucket
+
+  for (; Index <= Hdr.NameCount; ++Index) {
+    uint32_t Hash = CurrentIndex->getHashArrayEntry(Index);
+    if (Hash % Hdr.BucketCount != Bucket)
+      return None; // End of bucket
+
+    NameTableEntry NTE = CurrentIndex->getNameTableEntry(Index);
+    if (NTE.getString() == Key)
+      return NTE.getEntryOffset();
+  }
+  return None;
+}
+
+bool DWARFDebugNames::ValueIterator::getEntryAtCurrentOffset() {
+  auto EntryOr = CurrentIndex->getEntry(&DataOffset);
+  if (!EntryOr) {
+    consumeError(EntryOr.takeError());
+    return false;
+  }
+  CurrentEntry = std::move(*EntryOr);
+  return true;
+}
+
+bool DWARFDebugNames::ValueIterator::findInCurrentIndex() {
+  Optional<uint32_t> Offset = findEntryOffsetInCurrentIndex();
+  if (!Offset)
+    return false;
+  DataOffset = *Offset;
+  return getEntryAtCurrentOffset();
+}
+
+void DWARFDebugNames::ValueIterator::searchFromStartOfCurrentIndex() {
+  for (const NameIndex *End = CurrentIndex->Section.NameIndices.end();
+       CurrentIndex != End; ++CurrentIndex) {
+    if (findInCurrentIndex())
+      return;
+  }
+  setEnd();
+}
+
+void DWARFDebugNames::ValueIterator::next() {
+  assert(CurrentIndex && "Incrementing an end() iterator?");
+
+  // First try the next entry in the current Index.
+  if (getEntryAtCurrentOffset())
+    return;
+
+  // If we're a local iterator or we have reached the last Index, we're done.
+  if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) {
+    setEnd();
+    return;
+  }
+
+  // Otherwise, try the next index.
+  ++CurrentIndex;
+  searchFromStartOfCurrentIndex();
+}
+
+DWARFDebugNames::ValueIterator::ValueIterator(const DWARFDebugNames &AccelTable,
+                                              StringRef Key)
+    : CurrentIndex(AccelTable.NameIndices.begin()), IsLocal(false), Key(Key) {
+  searchFromStartOfCurrentIndex();
+}
+
+DWARFDebugNames::ValueIterator::ValueIterator(
+    const DWARFDebugNames::NameIndex &NI, StringRef Key)
+    : CurrentIndex(&NI), IsLocal(true), Key(Key) {
+  if (!findInCurrentIndex())
+    setEnd();
+}
+
+iterator_range<DWARFDebugNames::ValueIterator>
+DWARFDebugNames::equal_range(StringRef Key) const {
+  if (NameIndices.empty())
+    return make_range(ValueIterator(), ValueIterator());
+  return make_range(ValueIterator(*this, Key), ValueIterator());
+}
+
+const DWARFDebugNames::NameIndex *
+DWARFDebugNames::getCUNameIndex(uint32_t CUOffset) {
+  if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
+    for (const auto &NI : *this) {
+      for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
+        CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
+    }
+  }
+  return CUToNameIndex.lookup(CUOffset);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp
new file mode 100644
index 0000000..86c8d19
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp
@@ -0,0 +1,29 @@
+//===- DWARFDebugAranges.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFAddressRange::dump(raw_ostream &OS, uint32_t AddressSize,
+                             DIDumpOptions DumpOpts) const {
+
+  OS << (DumpOpts.DisplayRawContents ? " " : "[");
+  OS << format("0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, LowPC)
+     << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2, HighPC);
+  OS << (DumpOpts.DisplayRawContents ? "" : ")");
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const DWARFAddressRange &R) {
+  R.dump(OS, /* AddressSize */ 8);
+  return OS;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
new file mode 100644
index 0000000..00a23b38
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
@@ -0,0 +1,37 @@
+//===-- DWARFCompileUnit.cpp ----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
+  OS << format("0x%08x", getOffset()) << ": Compile Unit:"
+     << " length = " << format("0x%08x", getLength())
+     << " version = " << format("0x%04x", getVersion());
+  if (getVersion() >= 5)
+    OS << " unit_type = " << dwarf::UnitTypeString(getUnitType());
+  OS << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+     << " addr_size = " << format("0x%02x", getAddressByteSize());
+  if (getVersion() >= 5 && getUnitType() != dwarf::DW_UT_compile)
+    OS << " DWO_id = " << format("0x%016" PRIx64, *getDWOId());
+  OS << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
+
+  if (DWARFDie CUDie = getUnitDIE(false))
+    CUDie.dump(OS, 0, DumpOpts);
+  else
+    OS << "<compile unit can't be parsed!>\n\n";
+}
+
+// VTable anchor.
+DWARFCompileUnit::~DWARFCompileUnit() = default;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
new file mode 100644
index 0000000..e6620ee
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -0,0 +1,1693 @@
+//===- DWARFContext.cpp ---------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Object/Decompressor.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/RelocVisitor.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdint>
+#include <deque>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+#define DEBUG_TYPE "dwarf"
+
+using DWARFLineTable = DWARFDebugLine::LineTable;
+using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
+using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
+
+DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
+                           std::string DWPName)
+    : DIContext(CK_DWARF), DWPName(std::move(DWPName)), DObj(std::move(DObj)) {}
+
+DWARFContext::~DWARFContext() = default;
+
+/// Dump the UUID load command.
+static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
+  auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
+  if (!MachO)
+    return;
+  for (auto LC : MachO->load_commands()) {
+    raw_ostream::uuid_t UUID;
+    if (LC.C.cmd == MachO::LC_UUID) {
+      if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
+        OS << "error: UUID load command is too short.\n";
+        return;
+      }
+      OS << "UUID: ";
+      memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
+      OS.write_uuid(UUID);
+      Triple T = MachO->getArchTriple();
+      OS << " (" << T.getArchName() << ')';
+      OS << ' ' << MachO->getFileName() << '\n';
+    }
+  }
+}
+
+using ContributionCollection =
+    std::vector<Optional<StrOffsetsContributionDescriptor>>;
+
+// Collect all the contributions to the string offsets table from all units,
+// sort them by their starting offsets and remove duplicates.
+static ContributionCollection
+collectContributionData(DWARFContext::unit_iterator_range Units) {
+  ContributionCollection Contributions;
+  for (const auto &U : Units)
+    Contributions.push_back(U->getStringOffsetsTableContribution());
+  // Sort the contributions so that any invalid ones are placed at
+  // the start of the contributions vector. This way they are reported
+  // first.
+  llvm::sort(Contributions,
+             [](const Optional<StrOffsetsContributionDescriptor> &L,
+                const Optional<StrOffsetsContributionDescriptor> &R) {
+               if (L && R)
+                 return L->Base < R->Base;
+               return R.hasValue();
+             });
+
+  // Uniquify contributions, as it is possible that units (specifically
+  // type units in dwo or dwp files) share contributions. We don't want
+  // to report them more than once.
+  Contributions.erase(
+      std::unique(Contributions.begin(), Contributions.end(),
+                  [](const Optional<StrOffsetsContributionDescriptor> &L,
+                     const Optional<StrOffsetsContributionDescriptor> &R) {
+                    if (L && R)
+                      return L->Base == R->Base && L->Size == R->Size;
+                    return false;
+                  }),
+      Contributions.end());
+  return Contributions;
+}
+
+static void dumpDWARFv5StringOffsetsSection(
+    raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj,
+    const DWARFSection &StringOffsetsSection, StringRef StringSection,
+    DWARFContext::unit_iterator_range Units, bool LittleEndian) {
+  auto Contributions = collectContributionData(Units);
+  DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
+  DataExtractor StrData(StringSection, LittleEndian, 0);
+  uint64_t SectionSize = StringOffsetsSection.Data.size();
+  uint32_t Offset = 0;
+  for (auto &Contribution : Contributions) {
+    // Report an ill-formed contribution.
+    if (!Contribution) {
+      OS << "error: invalid contribution to string offsets table in section ."
+         << SectionName << ".\n";
+      return;
+    }
+
+    dwarf::DwarfFormat Format = Contribution->getFormat();
+    uint16_t Version = Contribution->getVersion();
+    uint64_t ContributionHeader = Contribution->Base;
+    // In DWARF v5 there is a contribution header that immediately precedes
+    // the string offsets base (the location we have previously retrieved from
+    // the CU DIE's DW_AT_str_offsets attribute). The header is located either
+    // 8 or 16 bytes before the base, depending on the contribution's format.
+    if (Version >= 5)
+      ContributionHeader -= Format == DWARF32 ? 8 : 16;
+
+    // Detect overlapping contributions.
+    if (Offset > ContributionHeader) {
+      OS << "error: overlapping contributions to string offsets table in "
+            "section ."
+         << SectionName << ".\n";
+      return;
+    }
+    // Report a gap in the table.
+    if (Offset < ContributionHeader) {
+      OS << format("0x%8.8x: Gap, length = ", Offset);
+      OS << (ContributionHeader - Offset) << "\n";
+    }
+    OS << format("0x%8.8x: ", (uint32_t)ContributionHeader);
+    // In DWARF v5 the contribution size in the descriptor does not equal
+    // the originally encoded length (it does not contain the length of the
+    // version field and the padding, a total of 4 bytes). Add them back in
+    // for reporting.
+    OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
+       << ", Format = " << (Format == DWARF32 ? "DWARF32" : "DWARF64")
+       << ", Version = " << Version << "\n";
+
+    Offset = Contribution->Base;
+    unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
+    while (Offset - Contribution->Base < Contribution->Size) {
+      OS << format("0x%8.8x: ", Offset);
+      // FIXME: We can only extract strings if the offset fits in 32 bits.
+      uint64_t StringOffset =
+          StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
+      // Extract the string if we can and display it. Otherwise just report
+      // the offset.
+      if (StringOffset <= std::numeric_limits<uint32_t>::max()) {
+        uint32_t StringOffset32 = (uint32_t)StringOffset;
+        OS << format("%8.8x ", StringOffset32);
+        const char *S = StrData.getCStr(&StringOffset32);
+        if (S)
+          OS << format("\"%s\"", S);
+      } else
+        OS << format("%16.16" PRIx64 " ", StringOffset);
+      OS << "\n";
+    }
+  }
+  // Report a gap at the end of the table.
+  if (Offset < SectionSize) {
+    OS << format("0x%8.8x: Gap, length = ", Offset);
+    OS << (SectionSize - Offset) << "\n";
+  }
+}
+
+// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
+// string offsets section, where each compile or type unit contributes a
+// number of entries (string offsets), with each contribution preceded by
+// a header containing size and version number. Alternatively, it may be a
+// monolithic series of string offsets, as generated by the pre-DWARF v5
+// implementation of split DWARF.
+static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
+                                     const DWARFObject &Obj,
+                                     const DWARFSection &StringOffsetsSection,
+                                     StringRef StringSection,
+                                     DWARFContext::unit_iterator_range Units,
+                                     bool LittleEndian, unsigned MaxVersion) {
+  // If we have at least one (compile or type) unit with DWARF v5 or greater,
+  // we assume that the section is formatted like a DWARF v5 string offsets
+  // section.
+  if (MaxVersion >= 5)
+    dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection,
+                                    StringSection, Units, LittleEndian);
+  else {
+    DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
+    uint32_t offset = 0;
+    uint64_t size = StringOffsetsSection.Data.size();
+    // Ensure that size is a multiple of the size of an entry.
+    if (size & ((uint64_t)(sizeof(uint32_t) - 1))) {
+      OS << "error: size of ." << SectionName << " is not a multiple of "
+         << sizeof(uint32_t) << ".\n";
+      size &= -(uint64_t)sizeof(uint32_t);
+    }
+    DataExtractor StrData(StringSection, LittleEndian, 0);
+    while (offset < size) {
+      OS << format("0x%8.8x: ", offset);
+      uint32_t StringOffset = strOffsetExt.getU32(&offset);
+      OS << format("%8.8x  ", StringOffset);
+      const char *S = StrData.getCStr(&StringOffset);
+      if (S)
+        OS << format("\"%s\"", S);
+      OS << "\n";
+    }
+  }
+}
+
+// Dump the .debug_addr section.
+static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
+                            DIDumpOptions DumpOpts, uint16_t Version,
+                            uint8_t AddrSize) {
+  uint32_t Offset = 0;
+  while (AddrData.isValidOffset(Offset)) {
+    DWARFDebugAddrTable AddrTable;
+    uint32_t TableOffset = Offset;
+    if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
+                                      DWARFContext::dumpWarning)) {
+      WithColor::error() << toString(std::move(Err)) << '\n';
+      // Keep going after an error, if we can, assuming that the length field
+      // could be read. If it couldn't, stop reading the section.
+      if (!AddrTable.hasValidLength())
+        break;
+      uint64_t Length = AddrTable.getLength();
+      Offset = TableOffset + Length;
+    } else {
+      AddrTable.dump(OS, DumpOpts);
+    }
+  }
+}
+
+// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
+static void
+dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData,
+                    llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
+                        LookupPooledAddress,
+                    DIDumpOptions DumpOpts) {
+  uint32_t Offset = 0;
+  while (rnglistData.isValidOffset(Offset)) {
+    llvm::DWARFDebugRnglistTable Rnglists;
+    uint32_t TableOffset = Offset;
+    if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
+      WithColor::error() << toString(std::move(Err)) << '\n';
+      uint64_t Length = Rnglists.length();
+      // Keep going after an error, if we can, assuming that the length field
+      // could be read. If it couldn't, stop reading the section.
+      if (Length == 0)
+        break;
+      Offset = TableOffset + Length;
+    } else {
+      Rnglists.dump(OS, LookupPooledAddress, DumpOpts);
+    }
+  }
+}
+
+static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
+                                DWARFDataExtractor Data,
+                                const MCRegisterInfo *MRI,
+                                Optional<uint64_t> DumpOffset) {
+  uint32_t Offset = 0;
+  DWARFDebugLoclists Loclists;
+
+  DWARFListTableHeader Header(".debug_loclists", "locations");
+  if (Error E = Header.extract(Data, &Offset)) {
+    WithColor::error() << toString(std::move(E)) << '\n';
+    return;
+  }
+
+  Header.dump(OS, DumpOpts);
+  DataExtractor LocData(Data.getData().drop_front(Offset),
+                        Data.isLittleEndian(), Header.getAddrSize());
+
+  Loclists.parse(LocData, Header.getVersion());
+  Loclists.dump(OS, 0, MRI, DumpOffset);
+}
+
+void DWARFContext::dump(
+    raw_ostream &OS, DIDumpOptions DumpOpts,
+    std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
+
+  uint64_t DumpType = DumpOpts.DumpType;
+
+  StringRef Extension = sys::path::extension(DObj->getFileName());
+  bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
+
+  // Print UUID header.
+  const auto *ObjFile = DObj->getFile();
+  if (DumpType & DIDT_UUID)
+    dumpUUID(OS, *ObjFile);
+
+  // Print a header for each explicitly-requested section.
+  // Otherwise just print one for non-empty sections.
+  // Only print empty .dwo section headers when dumping a .dwo file.
+  bool Explicit = DumpType != DIDT_All && !IsDWO;
+  bool ExplicitDWO = Explicit && IsDWO;
+  auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
+                        StringRef Section) -> Optional<uint64_t> * {
+    unsigned Mask = 1U << ID;
+    bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
+    if (!Should)
+      return nullptr;
+    OS << "\n" << Name << " contents:\n";
+    return &DumpOffsets[ID];
+  };
+
+  // Dump individual sections.
+  if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
+                 DObj->getAbbrevSection()))
+    getDebugAbbrev()->dump(OS);
+  if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
+                 DObj->getAbbrevDWOSection()))
+    getDebugAbbrevDWO()->dump(OS);
+
+  auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
+    OS << '\n' << Name << " contents:\n";
+    if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
+      for (const auto &U : Units)
+        U->getDIEForOffset(DumpOffset.getValue())
+            .dump(OS, 0, DumpOpts.noImplicitRecursion());
+    else
+      for (const auto &U : Units)
+        U->dump(OS, DumpOpts);
+  };
+  if ((DumpType & DIDT_DebugInfo)) {
+    if (Explicit || getNumCompileUnits())
+      dumpDebugInfo(".debug_info", info_section_units());
+    if (ExplicitDWO || getNumDWOCompileUnits())
+      dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
+  }
+
+  auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
+    OS << '\n' << Name << " contents:\n";
+    for (const auto &U : Units)
+      if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
+        U->getDIEForOffset(*DumpOffset)
+            .dump(OS, 0, DumpOpts.noImplicitRecursion());
+      else
+        U->dump(OS, DumpOpts);
+  };
+  if ((DumpType & DIDT_DebugTypes)) {
+    if (Explicit || getNumTypeUnits())
+      dumpDebugType(".debug_types", types_section_units());
+    if (ExplicitDWO || getNumDWOTypeUnits())
+      dumpDebugType(".debug_types.dwo", dwo_types_section_units());
+  }
+
+  if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
+                                   DObj->getLocSection().Data)) {
+    getDebugLoc()->dump(OS, getRegisterInfo(), *Off);
+  }
+  if (const auto *Off =
+          shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
+                     DObj->getLoclistsSection().Data)) {
+    DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
+                            0);
+    dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off);
+  }
+  if (const auto *Off =
+          shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
+                     DObj->getLocDWOSection().Data)) {
+    getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), *Off);
+  }
+
+  if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
+                                   DObj->getDebugFrameSection()))
+    getDebugFrame()->dump(OS, getRegisterInfo(), *Off);
+
+  if (const auto *Off = shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
+                                   DObj->getEHFrameSection()))
+    getEHFrame()->dump(OS, getRegisterInfo(), *Off);
+
+  if (DumpType & DIDT_DebugMacro) {
+    if (Explicit || !getDebugMacro()->empty()) {
+      OS << "\n.debug_macinfo contents:\n";
+      getDebugMacro()->dump(OS);
+    }
+  }
+
+  if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
+                 DObj->getARangeSection())) {
+    uint32_t offset = 0;
+    DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0);
+    DWARFDebugArangeSet set;
+    while (set.extract(arangesData, &offset))
+      set.dump(OS);
+  }
+
+  auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
+                             DIDumpOptions DumpOpts,
+                             Optional<uint64_t> DumpOffset) {
+    while (!Parser.done()) {
+      if (DumpOffset && Parser.getOffset() != *DumpOffset) {
+        Parser.skip(dumpWarning);
+        continue;
+      }
+      OS << "debug_line[" << format("0x%8.8x", Parser.getOffset()) << "]\n";
+      if (DumpOpts.Verbose) {
+        Parser.parseNext(dumpWarning, dumpWarning, &OS);
+      } else {
+        DWARFDebugLine::LineTable LineTable =
+            Parser.parseNext(dumpWarning, dumpWarning);
+        LineTable.dump(OS, DumpOpts);
+      }
+    }
+  };
+
+  if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
+                                   DObj->getLineSection().Data)) {
+    DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
+                                0);
+    DWARFDebugLine::SectionParser Parser(LineData, *this, compile_units(),
+                                         type_units());
+    DumpLineSection(Parser, DumpOpts, *Off);
+  }
+
+  if (const auto *Off =
+          shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
+                     DObj->getLineDWOSection().Data)) {
+    DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
+                                isLittleEndian(), 0);
+    DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_compile_units(),
+                                         dwo_type_units());
+    DumpLineSection(Parser, DumpOpts, *Off);
+  }
+
+  if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
+                 DObj->getCUIndexSection())) {
+    getCUIndex().dump(OS);
+  }
+
+  if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
+                 DObj->getTUIndexSection())) {
+    getTUIndex().dump(OS);
+  }
+
+  if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
+                 DObj->getStringSection())) {
+    DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0);
+    uint32_t offset = 0;
+    uint32_t strOffset = 0;
+    while (const char *s = strData.getCStr(&offset)) {
+      OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
+      strOffset = offset;
+    }
+  }
+  if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
+                 DObj->getStringDWOSection())) {
+    DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0);
+    uint32_t offset = 0;
+    uint32_t strDWOOffset = 0;
+    while (const char *s = strDWOData.getCStr(&offset)) {
+      OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
+      strDWOOffset = offset;
+    }
+  }
+  if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
+                 DObj->getLineStringSection())) {
+    DataExtractor strData(DObj->getLineStringSection(), isLittleEndian(), 0);
+    uint32_t offset = 0;
+    uint32_t strOffset = 0;
+    while (const char *s = strData.getCStr(&offset)) {
+      OS << format("0x%8.8x: \"", strOffset);
+      OS.write_escaped(s);
+      OS << "\"\n";
+      strOffset = offset;
+    }
+  }
+
+  if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
+                 DObj->getAddrSection().Data)) {
+    DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
+                                   isLittleEndian(), 0);
+    dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
+  }
+
+  if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
+                 DObj->getRangeSection().Data)) {
+    uint8_t savedAddressByteSize = getCUAddrSize();
+    DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
+                                  isLittleEndian(), savedAddressByteSize);
+    uint32_t offset = 0;
+    DWARFDebugRangeList rangeList;
+    while (rangesData.isValidOffset(offset)) {
+      if (Error E = rangeList.extract(rangesData, &offset)) {
+        WithColor::error() << toString(std::move(E)) << '\n';
+        break;
+      }
+      rangeList.dump(OS);
+    }
+  }
+
+  auto LookupPooledAddress = [&](uint32_t Index) -> Optional<SectionedAddress> {
+    const auto &CUs = compile_units();
+    auto I = CUs.begin();
+    if (I == CUs.end())
+      return None;
+    return (*I)->getAddrOffsetSectionItem(Index);
+  };
+
+  if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
+                 DObj->getRnglistsSection().Data)) {
+    DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
+                                   isLittleEndian(), 0);
+    dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
+  }
+
+  if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
+                 DObj->getRnglistsDWOSection().Data)) {
+    DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
+                                   isLittleEndian(), 0);
+    dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
+  }
+
+  if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
+                 DObj->getPubNamesSection().Data))
+    DWARFDebugPubTable(*DObj, DObj->getPubNamesSection(), isLittleEndian(), false)
+        .dump(OS);
+
+  if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
+                 DObj->getPubTypesSection().Data))
+    DWARFDebugPubTable(*DObj, DObj->getPubTypesSection(), isLittleEndian(), false)
+        .dump(OS);
+
+  if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
+                 DObj->getGnuPubNamesSection().Data))
+    DWARFDebugPubTable(*DObj, DObj->getGnuPubNamesSection(), isLittleEndian(),
+                       true /* GnuStyle */)
+        .dump(OS);
+
+  if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
+                 DObj->getGnuPubTypesSection().Data))
+    DWARFDebugPubTable(*DObj, DObj->getGnuPubTypesSection(), isLittleEndian(),
+                       true /* GnuStyle */)
+        .dump(OS);
+
+  if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
+                 DObj->getStringOffsetSection().Data))
+    dumpStringOffsetsSection(OS, "debug_str_offsets", *DObj,
+                             DObj->getStringOffsetSection(),
+                             DObj->getStringSection(), normal_units(),
+                             isLittleEndian(), getMaxVersion());
+  if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
+                 DObj->getStringOffsetDWOSection().Data))
+    dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", *DObj,
+                             DObj->getStringOffsetDWOSection(),
+                             DObj->getStringDWOSection(), dwo_units(),
+                             isLittleEndian(), getMaxDWOVersion());
+
+  if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
+                 DObj->getGdbIndexSection())) {
+    getGdbIndex().dump(OS);
+  }
+
+  if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
+                 DObj->getAppleNamesSection().Data))
+    getAppleNames().dump(OS);
+
+  if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
+                 DObj->getAppleTypesSection().Data))
+    getAppleTypes().dump(OS);
+
+  if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
+                 DObj->getAppleNamespacesSection().Data))
+    getAppleNamespaces().dump(OS);
+
+  if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
+                 DObj->getAppleObjCSection().Data))
+    getAppleObjC().dump(OS);
+  if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
+                 DObj->getDebugNamesSection().Data))
+    getDebugNames().dump(OS);
+}
+
+DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
+  parseDWOUnits(LazyParse);
+
+  if (const auto &CUI = getCUIndex()) {
+    if (const auto *R = CUI.getFromHash(Hash))
+      return dyn_cast_or_null<DWARFCompileUnit>(
+          DWOUnits.getUnitForIndexEntry(*R));
+    return nullptr;
+  }
+
+  // If there's no index, just search through the CUs in the DWO - there's
+  // probably only one unless this is something like LTO - though an in-process
+  // built/cached lookup table could be used in that case to improve repeated
+  // lookups of different CUs in the DWO.
+  for (const auto &DWOCU : dwo_compile_units()) {
+    // Might not have parsed DWO ID yet.
+    if (!DWOCU->getDWOId()) {
+      if (Optional<uint64_t> DWOId =
+          toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
+        DWOCU->setDWOId(*DWOId);
+      else
+        // No DWO ID?
+        continue;
+    }
+    if (DWOCU->getDWOId() == Hash)
+      return dyn_cast<DWARFCompileUnit>(DWOCU.get());
+  }
+  return nullptr;
+}
+
+DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) {
+  parseNormalUnits();
+  if (auto *CU = NormalUnits.getUnitForOffset(Offset))
+    return CU->getDIEForOffset(Offset);
+  return DWARFDie();
+}
+
+bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
+  bool Success = true;
+  DWARFVerifier verifier(OS, *this, DumpOpts);
+
+  Success &= verifier.handleDebugAbbrev();
+  if (DumpOpts.DumpType & DIDT_DebugInfo)
+    Success &= verifier.handleDebugInfo();
+  if (DumpOpts.DumpType & DIDT_DebugLine)
+    Success &= verifier.handleDebugLine();
+  Success &= verifier.handleAccelTables();
+  return Success;
+}
+
+const DWARFUnitIndex &DWARFContext::getCUIndex() {
+  if (CUIndex)
+    return *CUIndex;
+
+  DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
+
+  CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
+  CUIndex->parse(CUIndexData);
+  return *CUIndex;
+}
+
+const DWARFUnitIndex &DWARFContext::getTUIndex() {
+  if (TUIndex)
+    return *TUIndex;
+
+  DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0);
+
+  TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES);
+  TUIndex->parse(TUIndexData);
+  return *TUIndex;
+}
+
+DWARFGdbIndex &DWARFContext::getGdbIndex() {
+  if (GdbIndex)
+    return *GdbIndex;
+
+  DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0);
+  GdbIndex = llvm::make_unique<DWARFGdbIndex>();
+  GdbIndex->parse(GdbIndexData);
+  return *GdbIndex;
+}
+
+const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
+  if (Abbrev)
+    return Abbrev.get();
+
+  DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
+
+  Abbrev.reset(new DWARFDebugAbbrev());
+  Abbrev->extract(abbrData);
+  return Abbrev.get();
+}
+
+const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
+  if (AbbrevDWO)
+    return AbbrevDWO.get();
+
+  DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0);
+  AbbrevDWO.reset(new DWARFDebugAbbrev());
+  AbbrevDWO->extract(abbrData);
+  return AbbrevDWO.get();
+}
+
+const DWARFDebugLoc *DWARFContext::getDebugLoc() {
+  if (Loc)
+    return Loc.get();
+
+  Loc.reset(new DWARFDebugLoc);
+  // Assume all units have the same address byte size.
+  if (getNumCompileUnits()) {
+    DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(),
+                               getUnitAtIndex(0)->getAddressByteSize());
+    Loc->parse(LocData);
+  }
+  return Loc.get();
+}
+
+const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() {
+  if (LocDWO)
+    return LocDWO.get();
+
+  LocDWO.reset(new DWARFDebugLoclists());
+  // Assume all compile units have the same address byte size.
+  // FIXME: We don't need AddressSize for split DWARF since relocatable
+  // addresses cannot appear there. At the moment DWARFExpression requires it.
+  DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4);
+  // Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and
+  // that means we are parsing the new style .debug_loc (pre-standatized version
+  // of the .debug_loclists).
+  LocDWO->parse(LocData, 4 /* Version */);
+  return LocDWO.get();
+}
+
+const DWARFDebugAranges *DWARFContext::getDebugAranges() {
+  if (Aranges)
+    return Aranges.get();
+
+  Aranges.reset(new DWARFDebugAranges());
+  Aranges->generate(this);
+  return Aranges.get();
+}
+
+const DWARFDebugFrame *DWARFContext::getDebugFrame() {
+  if (DebugFrame)
+    return DebugFrame.get();
+
+  // There's a "bug" in the DWARFv3 standard with respect to the target address
+  // size within debug frame sections. While DWARF is supposed to be independent
+  // of its container, FDEs have fields with size being "target address size",
+  // which isn't specified in DWARF in general. It's only specified for CUs, but
+  // .eh_frame can appear without a .debug_info section. Follow the example of
+  // other tools (libdwarf) and extract this from the container (ObjectFile
+  // provides this information). This problem is fixed in DWARFv4
+  // See this dwarf-discuss discussion for more details:
+  // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
+  DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(),
+                                    isLittleEndian(), DObj->getAddressSize());
+  DebugFrame.reset(new DWARFDebugFrame(getArch(), false /* IsEH */));
+  DebugFrame->parse(debugFrameData);
+  return DebugFrame.get();
+}
+
+const DWARFDebugFrame *DWARFContext::getEHFrame() {
+  if (EHFrame)
+    return EHFrame.get();
+
+  DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
+                                    DObj->getAddressSize());
+  DebugFrame.reset(new DWARFDebugFrame(getArch(), true /* IsEH */));
+  DebugFrame->parse(debugFrameData);
+  return DebugFrame.get();
+}
+
+const DWARFDebugMacro *DWARFContext::getDebugMacro() {
+  if (Macro)
+    return Macro.get();
+
+  DataExtractor MacinfoData(DObj->getMacinfoSection(), isLittleEndian(), 0);
+  Macro.reset(new DWARFDebugMacro());
+  Macro->parse(MacinfoData);
+  return Macro.get();
+}
+
+template <typename T>
+static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
+                        const DWARFSection &Section, StringRef StringSection,
+                        bool IsLittleEndian) {
+  if (Cache)
+    return *Cache;
+  DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
+  DataExtractor StrData(StringSection, IsLittleEndian, 0);
+  Cache.reset(new T(AccelSection, StrData));
+  if (Error E = Cache->extract())
+    llvm::consumeError(std::move(E));
+  return *Cache;
+}
+
+const DWARFDebugNames &DWARFContext::getDebugNames() {
+  return getAccelTable(Names, *DObj, DObj->getDebugNamesSection(),
+                       DObj->getStringSection(), isLittleEndian());
+}
+
+const AppleAcceleratorTable &DWARFContext::getAppleNames() {
+  return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(),
+                       DObj->getStringSection(), isLittleEndian());
+}
+
+const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
+  return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(),
+                       DObj->getStringSection(), isLittleEndian());
+}
+
+const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
+  return getAccelTable(AppleNamespaces, *DObj,
+                       DObj->getAppleNamespacesSection(),
+                       DObj->getStringSection(), isLittleEndian());
+}
+
+const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
+  return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(),
+                       DObj->getStringSection(), isLittleEndian());
+}
+
+const DWARFDebugLine::LineTable *
+DWARFContext::getLineTableForUnit(DWARFUnit *U) {
+  Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =
+      getLineTableForUnit(U, dumpWarning);
+  if (!ExpectedLineTable) {
+    dumpWarning(ExpectedLineTable.takeError());
+    return nullptr;
+  }
+  return *ExpectedLineTable;
+}
+
+Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
+    DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) {
+  if (!Line)
+    Line.reset(new DWARFDebugLine);
+
+  auto UnitDIE = U->getUnitDIE();
+  if (!UnitDIE)
+    return nullptr;
+
+  auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
+  if (!Offset)
+    return nullptr; // No line table for this compile unit.
+
+  uint32_t stmtOffset = *Offset + U->getLineTableOffset();
+  // See if the line table is cached.
+  if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
+    return lt;
+
+  // Make sure the offset is good before we try to parse.
+  if (stmtOffset >= U->getLineSection().Data.size())
+    return nullptr;
+
+  // We have to parse it first.
+  DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
+                              U->getAddressByteSize());
+  return Line->getOrParseLineTable(lineData, stmtOffset, *this, U,
+                                   RecoverableErrorCallback);
+}
+
+void DWARFContext::parseNormalUnits() {
+  if (!NormalUnits.empty())
+    return;
+  DObj->forEachInfoSections([&](const DWARFSection &S) {
+    NormalUnits.addUnitsForSection(*this, S, DW_SECT_INFO);
+  });
+  NormalUnits.finishedInfoUnits();
+  DObj->forEachTypesSections([&](const DWARFSection &S) {
+    NormalUnits.addUnitsForSection(*this, S, DW_SECT_TYPES);
+  });
+}
+
+void DWARFContext::parseDWOUnits(bool Lazy) {
+  if (!DWOUnits.empty())
+    return;
+  DObj->forEachInfoDWOSections([&](const DWARFSection &S) {
+    DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_INFO, Lazy);
+  });
+  DWOUnits.finishedInfoUnits();
+  DObj->forEachTypesDWOSections([&](const DWARFSection &S) {
+    DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_TYPES, Lazy);
+  });
+}
+
+DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
+  parseNormalUnits();
+  return dyn_cast_or_null<DWARFCompileUnit>(
+      NormalUnits.getUnitForOffset(Offset));
+}
+
+DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
+  // First, get the offset of the compile unit.
+  uint32_t CUOffset = getDebugAranges()->findAddress(Address);
+  // Retrieve the compile unit.
+  return getCompileUnitForOffset(CUOffset);
+}
+
+DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
+  DIEsForAddress Result;
+
+  DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+  if (!CU)
+    return Result;
+
+  Result.CompileUnit = CU;
+  Result.FunctionDIE = CU->getSubroutineForAddress(Address);
+
+  std::vector<DWARFDie> Worklist;
+  Worklist.push_back(Result.FunctionDIE);
+  while (!Worklist.empty()) {
+    DWARFDie DIE = Worklist.back();
+    Worklist.pop_back();
+
+    if (DIE.getTag() == DW_TAG_lexical_block &&
+        DIE.addressRangeContainsAddress(Address)) {
+      Result.BlockDIE = DIE;
+      break;
+    }
+
+    for (auto Child : DIE)
+      Worklist.push_back(Child);
+  }
+
+  return Result;
+}
+
+static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
+                                                  uint64_t Address,
+                                                  FunctionNameKind Kind,
+                                                  std::string &FunctionName,
+                                                  uint32_t &StartLine) {
+  // The address may correspond to instruction in some inlined function,
+  // so we have to build the chain of inlined functions and take the
+  // name of the topmost function in it.
+  SmallVector<DWARFDie, 4> InlinedChain;
+  CU->getInlinedChainForAddress(Address, InlinedChain);
+  if (InlinedChain.empty())
+    return false;
+
+  const DWARFDie &DIE = InlinedChain[0];
+  bool FoundResult = false;
+  const char *Name = nullptr;
+  if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
+    FunctionName = Name;
+    FoundResult = true;
+  }
+  if (auto DeclLineResult = DIE.getDeclLine()) {
+    StartLine = DeclLineResult;
+    FoundResult = true;
+  }
+
+  return FoundResult;
+}
+
+DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
+                                               DILineInfoSpecifier Spec) {
+  DILineInfo Result;
+
+  DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+  if (!CU)
+    return Result;
+  getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
+                                        Result.FunctionName,
+                                        Result.StartLine);
+  if (Spec.FLIKind != FileLineInfoKind::None) {
+    if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
+      LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+                                           Spec.FLIKind, Result);
+  }
+  return Result;
+}
+
+DILineInfoTable
+DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+                                         DILineInfoSpecifier Spec) {
+  DILineInfoTable  Lines;
+  DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+  if (!CU)
+    return Lines;
+
+  std::string FunctionName = "<invalid>";
+  uint32_t StartLine = 0;
+  getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName,
+                                        StartLine);
+
+  // If the Specifier says we don't need FileLineInfo, just
+  // return the top-most function at the starting address.
+  if (Spec.FLIKind == FileLineInfoKind::None) {
+    DILineInfo Result;
+    Result.FunctionName = FunctionName;
+    Result.StartLine = StartLine;
+    Lines.push_back(std::make_pair(Address, Result));
+    return Lines;
+  }
+
+  const DWARFLineTable *LineTable = getLineTableForUnit(CU);
+
+  // Get the index of row we're looking for in the line table.
+  std::vector<uint32_t> RowVector;
+  if (!LineTable->lookupAddressRange(Address, Size, RowVector))
+    return Lines;
+
+  for (uint32_t RowIndex : RowVector) {
+    // Take file number and line/column from the row.
+    const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
+    DILineInfo Result;
+    LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
+                                  Spec.FLIKind, Result.FileName);
+    Result.FunctionName = FunctionName;
+    Result.Line = Row.Line;
+    Result.Column = Row.Column;
+    Result.StartLine = StartLine;
+    Lines.push_back(std::make_pair(Row.Address, Result));
+  }
+
+  return Lines;
+}
+
+DIInliningInfo
+DWARFContext::getInliningInfoForAddress(uint64_t Address,
+                                        DILineInfoSpecifier Spec) {
+  DIInliningInfo InliningInfo;
+
+  DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+  if (!CU)
+    return InliningInfo;
+
+  const DWARFLineTable *LineTable = nullptr;
+  SmallVector<DWARFDie, 4> InlinedChain;
+  CU->getInlinedChainForAddress(Address, InlinedChain);
+  if (InlinedChain.size() == 0) {
+    // If there is no DIE for address (e.g. it is in unavailable .dwo file),
+    // try to at least get file/line info from symbol table.
+    if (Spec.FLIKind != FileLineInfoKind::None) {
+      DILineInfo Frame;
+      LineTable = getLineTableForUnit(CU);
+      if (LineTable &&
+          LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+                                               Spec.FLIKind, Frame))
+        InliningInfo.addFrame(Frame);
+    }
+    return InliningInfo;
+  }
+
+  uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
+  for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
+    DWARFDie &FunctionDIE = InlinedChain[i];
+    DILineInfo Frame;
+    // Get function name if necessary.
+    if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
+      Frame.FunctionName = Name;
+    if (auto DeclLineResult = FunctionDIE.getDeclLine())
+      Frame.StartLine = DeclLineResult;
+    if (Spec.FLIKind != FileLineInfoKind::None) {
+      if (i == 0) {
+        // For the topmost frame, initialize the line table of this
+        // compile unit and fetch file/line info from it.
+        LineTable = getLineTableForUnit(CU);
+        // For the topmost routine, get file/line info from line table.
+        if (LineTable)
+          LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+                                               Spec.FLIKind, Frame);
+      } else {
+        // Otherwise, use call file, call line and call column from
+        // previous DIE in inlined chain.
+        if (LineTable)
+          LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
+                                        Spec.FLIKind, Frame.FileName);
+        Frame.Line = CallLine;
+        Frame.Column = CallColumn;
+        Frame.Discriminator = CallDiscriminator;
+      }
+      // Get call file/line/column of a current DIE.
+      if (i + 1 < n) {
+        FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
+                                   CallDiscriminator);
+      }
+    }
+    InliningInfo.addFrame(Frame);
+  }
+  return InliningInfo;
+}
+
+std::shared_ptr<DWARFContext>
+DWARFContext::getDWOContext(StringRef AbsolutePath) {
+  if (auto S = DWP.lock()) {
+    DWARFContext *Ctxt = S->Context.get();
+    return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+  }
+
+  std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
+
+  if (auto S = Entry->lock()) {
+    DWARFContext *Ctxt = S->Context.get();
+    return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+  }
+
+  Expected<OwningBinary<ObjectFile>> Obj = [&] {
+    if (!CheckedForDWP) {
+      SmallString<128> DWPName;
+      auto Obj = object::ObjectFile::createObjectFile(
+          this->DWPName.empty()
+              ? (DObj->getFileName() + ".dwp").toStringRef(DWPName)
+              : StringRef(this->DWPName));
+      if (Obj) {
+        Entry = &DWP;
+        return Obj;
+      } else {
+        CheckedForDWP = true;
+        // TODO: Should this error be handled (maybe in a high verbosity mode)
+        // before falling back to .dwo files?
+        consumeError(Obj.takeError());
+      }
+    }
+
+    return object::ObjectFile::createObjectFile(AbsolutePath);
+  }();
+
+  if (!Obj) {
+    // TODO: Actually report errors helpfully.
+    consumeError(Obj.takeError());
+    return nullptr;
+  }
+
+  auto S = std::make_shared<DWOFile>();
+  S->File = std::move(Obj.get());
+  S->Context = DWARFContext::create(*S->File.getBinary());
+  *Entry = S;
+  auto *Ctxt = S->Context.get();
+  return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+}
+
+static Error createError(const Twine &Reason, llvm::Error E) {
+  return make_error<StringError>(Reason + toString(std::move(E)),
+                                 inconvertibleErrorCode());
+}
+
+/// SymInfo contains information about symbol: it's address
+/// and section index which is -1LL for absolute symbols.
+struct SymInfo {
+  uint64_t Address;
+  uint64_t SectionIndex;
+};
+
+/// Returns the address of symbol relocation used against and a section index.
+/// Used for futher relocations computation. Symbol's section load address is
+static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
+                                       const RelocationRef &Reloc,
+                                       const LoadedObjectInfo *L,
+                                       std::map<SymbolRef, SymInfo> &Cache) {
+  SymInfo Ret = {0, (uint64_t)-1LL};
+  object::section_iterator RSec = Obj.section_end();
+  object::symbol_iterator Sym = Reloc.getSymbol();
+
+  std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
+  // First calculate the address of the symbol or section as it appears
+  // in the object file
+  if (Sym != Obj.symbol_end()) {
+    bool New;
+    std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});
+    if (!New)
+      return CacheIt->second;
+
+    Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
+    if (!SymAddrOrErr)
+      return createError("failed to compute symbol address: ",
+                         SymAddrOrErr.takeError());
+
+    // Also remember what section this symbol is in for later
+    auto SectOrErr = Sym->getSection();
+    if (!SectOrErr)
+      return createError("failed to get symbol section: ",
+                         SectOrErr.takeError());
+
+    RSec = *SectOrErr;
+    Ret.Address = *SymAddrOrErr;
+  } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
+    RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
+    Ret.Address = RSec->getAddress();
+  }
+
+  if (RSec != Obj.section_end())
+    Ret.SectionIndex = RSec->getIndex();
+
+  // If we are given load addresses for the sections, we need to adjust:
+  // SymAddr = (Address of Symbol Or Section in File) -
+  //           (Address of Section in File) +
+  //           (Load Address of Section)
+  // RSec is now either the section being targeted or the section
+  // containing the symbol being targeted. In either case,
+  // we need to perform the same computation.
+  if (L && RSec != Obj.section_end())
+    if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
+      Ret.Address += SectionLoadAddress - RSec->getAddress();
+
+  if (CacheIt != Cache.end())
+    CacheIt->second = Ret;
+
+  return Ret;
+}
+
+static bool isRelocScattered(const object::ObjectFile &Obj,
+                             const RelocationRef &Reloc) {
+  const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
+  if (!MachObj)
+    return false;
+  // MachO also has relocations that point to sections and
+  // scattered relocations.
+  auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
+  return MachObj->isRelocationScattered(RelocInfo);
+}
+
+ErrorPolicy DWARFContext::defaultErrorHandler(Error E) {
+  WithColor::error() << toString(std::move(E)) << '\n';
+  return ErrorPolicy::Continue;
+}
+
+namespace {
+struct DWARFSectionMap final : public DWARFSection {
+  RelocAddrMap Relocs;
+};
+
+class DWARFObjInMemory final : public DWARFObject {
+  bool IsLittleEndian;
+  uint8_t AddressSize;
+  StringRef FileName;
+  const object::ObjectFile *Obj = nullptr;
+  std::vector<SectionName> SectionNames;
+
+  using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
+                                   std::map<object::SectionRef, unsigned>>;
+
+  InfoSectionMap InfoSections;
+  InfoSectionMap TypesSections;
+  InfoSectionMap InfoDWOSections;
+  InfoSectionMap TypesDWOSections;
+
+  DWARFSectionMap LocSection;
+  DWARFSectionMap LocListsSection;
+  DWARFSectionMap LineSection;
+  DWARFSectionMap RangeSection;
+  DWARFSectionMap RnglistsSection;
+  DWARFSectionMap StringOffsetSection;
+  DWARFSectionMap LineDWOSection;
+  DWARFSectionMap LocDWOSection;
+  DWARFSectionMap StringOffsetDWOSection;
+  DWARFSectionMap RangeDWOSection;
+  DWARFSectionMap RnglistsDWOSection;
+  DWARFSectionMap AddrSection;
+  DWARFSectionMap AppleNamesSection;
+  DWARFSectionMap AppleTypesSection;
+  DWARFSectionMap AppleNamespacesSection;
+  DWARFSectionMap AppleObjCSection;
+  DWARFSectionMap DebugNamesSection;
+  DWARFSectionMap PubNamesSection;
+  DWARFSectionMap PubTypesSection;
+  DWARFSectionMap GnuPubNamesSection;
+  DWARFSectionMap GnuPubTypesSection;
+
+  DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
+    return StringSwitch<DWARFSectionMap *>(Name)
+        .Case("debug_loc", &LocSection)
+        .Case("debug_loclists", &LocListsSection)
+        .Case("debug_line", &LineSection)
+        .Case("debug_str_offsets", &StringOffsetSection)
+        .Case("debug_ranges", &RangeSection)
+        .Case("debug_rnglists", &RnglistsSection)
+        .Case("debug_loc.dwo", &LocDWOSection)
+        .Case("debug_line.dwo", &LineDWOSection)
+        .Case("debug_names", &DebugNamesSection)
+        .Case("debug_rnglists.dwo", &RnglistsDWOSection)
+        .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+        .Case("debug_addr", &AddrSection)
+        .Case("apple_names", &AppleNamesSection)
+        .Case("debug_pubnames", &PubNamesSection)
+        .Case("debug_pubtypes", &PubTypesSection)
+        .Case("debug_gnu_pubnames", &GnuPubNamesSection)
+        .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
+        .Case("apple_types", &AppleTypesSection)
+        .Case("apple_namespaces", &AppleNamespacesSection)
+        .Case("apple_namespac", &AppleNamespacesSection)
+        .Case("apple_objc", &AppleObjCSection)
+        .Default(nullptr);
+  }
+
+  StringRef AbbrevSection;
+  StringRef ARangeSection;
+  StringRef DebugFrameSection;
+  StringRef EHFrameSection;
+  StringRef StringSection;
+  StringRef MacinfoSection;
+  StringRef AbbrevDWOSection;
+  StringRef StringDWOSection;
+  StringRef CUIndexSection;
+  StringRef GdbIndexSection;
+  StringRef TUIndexSection;
+  StringRef LineStringSection;
+
+  // A deque holding section data whose iterators are not invalidated when
+  // new decompressed sections are inserted at the end.
+  std::deque<SmallString<0>> UncompressedSections;
+
+  StringRef *mapSectionToMember(StringRef Name) {
+    if (DWARFSection *Sec = mapNameToDWARFSection(Name))
+      return &Sec->Data;
+    return StringSwitch<StringRef *>(Name)
+        .Case("debug_abbrev", &AbbrevSection)
+        .Case("debug_aranges", &ARangeSection)
+        .Case("debug_frame", &DebugFrameSection)
+        .Case("eh_frame", &EHFrameSection)
+        .Case("debug_str", &StringSection)
+        .Case("debug_macinfo", &MacinfoSection)
+        .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+        .Case("debug_str.dwo", &StringDWOSection)
+        .Case("debug_cu_index", &CUIndexSection)
+        .Case("debug_tu_index", &TUIndexSection)
+        .Case("gdb_index", &GdbIndexSection)
+        .Case("debug_line_str", &LineStringSection)
+        // Any more debug info sections go here.
+        .Default(nullptr);
+  }
+
+  /// 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) {
+    if (!Decompressor::isCompressed(Sec))
+      return Error::success();
+
+    Expected<Decompressor> Decompressor =
+        Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
+    if (!Decompressor)
+      return Decompressor.takeError();
+
+    SmallString<0> Out;
+    if (auto Err = Decompressor->resizeAndDecompress(Out))
+      return Err;
+
+    UncompressedSections.push_back(std::move(Out));
+    Data = UncompressedSections.back();
+
+    return Error::success();
+  }
+
+public:
+  DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+                   uint8_t AddrSize, bool IsLittleEndian)
+      : IsLittleEndian(IsLittleEndian) {
+    for (const auto &SecIt : Sections) {
+      if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
+        *SectionData = SecIt.second->getBuffer();
+      else if (SecIt.first() == "debug_info")
+        // Find debug_info and debug_types data by section rather than name as
+        // there are multiple, comdat grouped, of these sections.
+        InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
+      else if (SecIt.first() == "debug_info.dwo")
+        InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
+      else if (SecIt.first() == "debug_types")
+        TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
+      else if (SecIt.first() == "debug_types.dwo")
+        TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
+    }
+  }
+  DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
+                   function_ref<ErrorPolicy(Error)> HandleError)
+      : IsLittleEndian(Obj.isLittleEndian()),
+        AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
+        Obj(&Obj) {
+
+    StringMap<unsigned> SectionAmountMap;
+    for (const SectionRef &Section : Obj.sections()) {
+      StringRef Name;
+      Section.getName(Name);
+      ++SectionAmountMap[Name];
+      SectionNames.push_back({ Name, true });
+
+      // Skip BSS and Virtual sections, they aren't interesting.
+      if (Section.isBSS() || Section.isVirtual())
+        continue;
+
+      // Skip sections stripped by dsymutil.
+      if (Section.isStripped())
+        continue;
+
+      StringRef Data;
+      section_iterator RelocatedSection = Section.getRelocatedSection();
+      // Try to obtain an already relocated version of this section.
+      // Else use the unrelocated section from the object file. We'll have to
+      // apply relocations ourselves later.
+      if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data))
+        Section.getContents(Data);
+
+      if (auto Err = maybeDecompress(Section, Name, Data)) {
+        ErrorPolicy EP = HandleError(createError(
+            "failed to decompress '" + Name + "', ", std::move(Err)));
+        if (EP == ErrorPolicy::Halt)
+          return;
+        continue;
+      }
+
+      // Compressed sections names in GNU style starts from ".z",
+      // at this point section is decompressed and we drop compression prefix.
+      Name = Name.substr(
+          Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
+
+      // Map platform specific debug section names to DWARF standard section
+      // names.
+      Name = Obj.mapDebugSectionName(Name);
+
+      if (StringRef *SectionData = mapSectionToMember(Name)) {
+        *SectionData = Data;
+        if (Name == "debug_ranges") {
+          // FIXME: Use the other dwo range section when we emit it.
+          RangeDWOSection.Data = Data;
+        }
+      } else if (Name == "debug_info") {
+        // Find debug_info and debug_types data by section rather than name as
+        // there are multiple, comdat grouped, of these sections.
+        InfoSections[Section].Data = Data;
+      } else if (Name == "debug_info.dwo") {
+        InfoDWOSections[Section].Data = Data;
+      } else if (Name == "debug_types") {
+        TypesSections[Section].Data = Data;
+      } else if (Name == "debug_types.dwo") {
+        TypesDWOSections[Section].Data = Data;
+      }
+
+      if (RelocatedSection == Obj.section_end())
+        continue;
+
+      StringRef RelSecName;
+      StringRef RelSecData;
+      RelocatedSection->getName(RelSecName);
+
+      // If the section we're relocating was relocated already by the JIT,
+      // then we used the relocated version above, so we do not need to process
+      // relocations for it now.
+      if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
+        continue;
+
+      // In Mach-o files, the relocations do not need to be applied if
+      // there is no load offset to apply. The value read at the
+      // relocation point already factors in the section address
+      // (actually applying the relocations will produce wrong results
+      // as the section address will be added twice).
+      if (!L && isa<MachOObjectFile>(&Obj))
+        continue;
+
+      RelSecName = RelSecName.substr(
+          RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
+
+      // TODO: Add support for relocations in other sections as needed.
+      // Record relocations for the debug_info and debug_line sections.
+      DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
+      RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
+      if (!Map) {
+        // Find debug_info and debug_types relocs by section rather than name
+        // as there are multiple, comdat grouped, of these sections.
+        if (RelSecName == "debug_info")
+          Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
+                     .Relocs;
+        else if (RelSecName == "debug_info.dwo")
+          Map = &static_cast<DWARFSectionMap &>(
+                     InfoDWOSections[*RelocatedSection])
+                     .Relocs;
+        else if (RelSecName == "debug_types")
+          Map =
+              &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
+                   .Relocs;
+        else if (RelSecName == "debug_types.dwo")
+          Map = &static_cast<DWARFSectionMap &>(
+                     TypesDWOSections[*RelocatedSection])
+                     .Relocs;
+        else
+          continue;
+      }
+
+      if (Section.relocation_begin() == Section.relocation_end())
+        continue;
+
+      // Symbol to [address, section index] cache mapping.
+      std::map<SymbolRef, SymInfo> AddrCache;
+      for (const RelocationRef &Reloc : Section.relocations()) {
+        // FIXME: it's not clear how to correctly handle scattered
+        // relocations.
+        if (isRelocScattered(Obj, Reloc))
+          continue;
+
+        Expected<SymInfo> SymInfoOrErr =
+            getSymbolInfo(Obj, Reloc, L, AddrCache);
+        if (!SymInfoOrErr) {
+          if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
+            return;
+          continue;
+        }
+
+        object::RelocVisitor V(Obj);
+        uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address);
+        if (V.error()) {
+          SmallString<32> Type;
+          Reloc.getTypeName(Type);
+          ErrorPolicy EP = HandleError(
+              createError("failed to compute relocation: " + Type + ", ",
+                          errorCodeToError(object_error::parse_failed)));
+          if (EP == ErrorPolicy::Halt)
+            return;
+          continue;
+        }
+        RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
+        Map->insert({Reloc.getOffset(), Rel});
+      }
+    }
+
+    for (SectionName &S : SectionNames)
+      if (SectionAmountMap[S.Name] > 1)
+        S.IsNameUnique = false;
+  }
+
+  Optional<RelocAddrEntry> find(const DWARFSection &S,
+                                uint64_t Pos) const override {
+    auto &Sec = static_cast<const DWARFSectionMap &>(S);
+    RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
+    if (AI == Sec.Relocs.end())
+      return None;
+    return AI->second;
+  }
+
+  const object::ObjectFile *getFile() const override { return Obj; }
+
+  ArrayRef<SectionName> getSectionNames() const override {
+    return SectionNames;
+  }
+
+  bool isLittleEndian() const override { return IsLittleEndian; }
+  StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
+  const DWARFSection &getLineDWOSection() const override {
+    return LineDWOSection;
+  }
+  const DWARFSection &getLocDWOSection() const override {
+    return LocDWOSection;
+  }
+  StringRef getStringDWOSection() const override { return StringDWOSection; }
+  const DWARFSection &getStringOffsetDWOSection() const override {
+    return StringOffsetDWOSection;
+  }
+  const DWARFSection &getRangeDWOSection() const override {
+    return RangeDWOSection;
+  }
+  const DWARFSection &getRnglistsDWOSection() const override {
+    return RnglistsDWOSection;
+  }
+  const DWARFSection &getAddrSection() const override { return AddrSection; }
+  StringRef getCUIndexSection() const override { return CUIndexSection; }
+  StringRef getGdbIndexSection() const override { return GdbIndexSection; }
+  StringRef getTUIndexSection() const override { return TUIndexSection; }
+
+  // DWARF v5
+  const DWARFSection &getStringOffsetSection() const override {
+    return StringOffsetSection;
+  }
+  StringRef getLineStringSection() const override { return LineStringSection; }
+
+  // Sections for DWARF5 split dwarf proposal.
+  void forEachInfoDWOSections(
+      function_ref<void(const DWARFSection &)> F) const override {
+    for (auto &P : InfoDWOSections)
+      F(P.second);
+  }
+  void forEachTypesDWOSections(
+      function_ref<void(const DWARFSection &)> F) const override {
+    for (auto &P : TypesDWOSections)
+      F(P.second);
+  }
+
+  StringRef getAbbrevSection() const override { return AbbrevSection; }
+  const DWARFSection &getLocSection() const override { return LocSection; }
+  const DWARFSection &getLoclistsSection() const override { return LocListsSection; }
+  StringRef getARangeSection() const override { return ARangeSection; }
+  StringRef getDebugFrameSection() const override { return DebugFrameSection; }
+  StringRef getEHFrameSection() const override { return EHFrameSection; }
+  const DWARFSection &getLineSection() const override { return LineSection; }
+  StringRef getStringSection() const override { return StringSection; }
+  const DWARFSection &getRangeSection() const override { return RangeSection; }
+  const DWARFSection &getRnglistsSection() const override {
+    return RnglistsSection;
+  }
+  StringRef getMacinfoSection() const override { return MacinfoSection; }
+  const DWARFSection &getPubNamesSection() const override { return PubNamesSection; }
+  const DWARFSection &getPubTypesSection() const override { return PubTypesSection; }
+  const DWARFSection &getGnuPubNamesSection() const override {
+    return GnuPubNamesSection;
+  }
+  const DWARFSection &getGnuPubTypesSection() const override {
+    return GnuPubTypesSection;
+  }
+  const DWARFSection &getAppleNamesSection() const override {
+    return AppleNamesSection;
+  }
+  const DWARFSection &getAppleTypesSection() const override {
+    return AppleTypesSection;
+  }
+  const DWARFSection &getAppleNamespacesSection() const override {
+    return AppleNamespacesSection;
+  }
+  const DWARFSection &getAppleObjCSection() const override {
+    return AppleObjCSection;
+  }
+  const DWARFSection &getDebugNamesSection() const override {
+    return DebugNamesSection;
+  }
+
+  StringRef getFileName() const override { return FileName; }
+  uint8_t getAddressSize() const override { return AddressSize; }
+  void forEachInfoSections(
+      function_ref<void(const DWARFSection &)> F) const override {
+    for (auto &P : InfoSections)
+      F(P.second);
+  }
+  void forEachTypesSections(
+      function_ref<void(const DWARFSection &)> F) const override {
+    for (auto &P : TypesSections)
+      F(P.second);
+  }
+};
+} // namespace
+
+std::unique_ptr<DWARFContext>
+DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
+                     function_ref<ErrorPolicy(Error)> HandleError,
+                     std::string DWPName) {
+  auto DObj = llvm::make_unique<DWARFObjInMemory>(Obj, L, HandleError);
+  return llvm::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName));
+}
+
+std::unique_ptr<DWARFContext>
+DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+                     uint8_t AddrSize, bool isLittleEndian) {
+  auto DObj =
+      llvm::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
+  return llvm::make_unique<DWARFContext>(std::move(DObj), "");
+}
+
+Error DWARFContext::loadRegisterInfo(const object::ObjectFile &Obj) {
+  // Detect the architecture from the object file. We usually don't need OS
+  // info to lookup a target and create register info.
+  Triple TT;
+  TT.setArch(Triple::ArchType(Obj.getArch()));
+  TT.setVendor(Triple::UnknownVendor);
+  TT.setOS(Triple::UnknownOS);
+  std::string TargetLookupError;
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(TT.str(), TargetLookupError);
+  if (!TargetLookupError.empty())
+    return createStringError(errc::invalid_argument,
+                             TargetLookupError.c_str());
+  RegInfo.reset(TheTarget->createMCRegInfo(TT.str()));
+  return Error::success();
+}
+
+uint8_t DWARFContext::getCUAddrSize() {
+  // In theory, different compile units may have different address byte
+  // sizes, but for simplicity we just use the address byte size of the
+  // last compile unit. In practice the address size field is repeated across
+  // various DWARF headers (at least in version 5) to make it easier to dump
+  // them independently, not to enable varying the address size.
+  uint8_t Addr = 0;
+  for (const auto &CU : compile_units()) {
+    Addr = CU->getAddressByteSize();
+    break;
+  }
+  return Addr;
+}
+
+void DWARFContext::dumpWarning(Error Warning) {
+  handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) {
+      WithColor::warning() << Info.message() << '\n';
+  });
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
new file mode 100644
index 0000000..03e3174
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp
@@ -0,0 +1,96 @@
+//===- DWARFDataExtractor.cpp ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+
+using namespace llvm;
+
+uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
+                                               uint64_t *SecNdx) const {
+  if (SecNdx)
+    *SecNdx = -1ULL;
+  if (!Section)
+    return getUnsigned(Off, Size);
+  Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);
+  if (!Rel)
+    return getUnsigned(Off, Size);
+  if (SecNdx)
+    *SecNdx = Rel->SectionIndex;
+  return getUnsigned(Off, Size) + Rel->Value;
+}
+
+Optional<uint64_t>
+DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
+                                      uint64_t PCRelOffset) const {
+  if (Encoding == dwarf::DW_EH_PE_omit)
+    return None;
+
+  uint64_t Result = 0;
+  uint32_t OldOffset = *Offset;
+  // First get value
+  switch (Encoding & 0x0F) {
+  case dwarf::DW_EH_PE_absptr:
+    switch (getAddressSize()) {
+    case 2:
+    case 4:
+    case 8:
+      Result = getUnsigned(Offset, getAddressSize());
+      break;
+    default:
+      return None;
+    }
+    break;
+  case dwarf::DW_EH_PE_uleb128:
+    Result = getULEB128(Offset);
+    break;
+  case dwarf::DW_EH_PE_sleb128:
+    Result = getSLEB128(Offset);
+    break;
+  case dwarf::DW_EH_PE_udata2:
+    Result = getUnsigned(Offset, 2);
+    break;
+  case dwarf::DW_EH_PE_udata4:
+    Result = getUnsigned(Offset, 4);
+    break;
+  case dwarf::DW_EH_PE_udata8:
+    Result = getUnsigned(Offset, 8);
+    break;
+  case dwarf::DW_EH_PE_sdata2:
+    Result = getSigned(Offset, 2);
+    break;
+  case dwarf::DW_EH_PE_sdata4:
+    Result = getSigned(Offset, 4);
+    break;
+  case dwarf::DW_EH_PE_sdata8:
+    Result = getSigned(Offset, 8);
+    break;
+  default:
+    return None;
+  }
+  // Then add relative offset, if required
+  switch (Encoding & 0x70) {
+  case dwarf::DW_EH_PE_absptr:
+    // do nothing
+    break;
+  case dwarf::DW_EH_PE_pcrel:
+    Result += PCRelOffset;
+    break;
+  case dwarf::DW_EH_PE_datarel:
+  case dwarf::DW_EH_PE_textrel:
+  case dwarf::DW_EH_PE_funcrel:
+  case dwarf::DW_EH_PE_aligned:
+  default:
+    *Offset = OldOffset;
+    return None;
+  }
+
+  return Result;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
new file mode 100644
index 0000000..4830c36
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
@@ -0,0 +1,139 @@
+//===- DWARFDebugAbbrev.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cinttypes>
+#include <cstdint>
+
+using namespace llvm;
+
+DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
+  clear();
+}
+
+void DWARFAbbreviationDeclarationSet::clear() {
+  Offset = 0;
+  FirstAbbrCode = 0;
+  Decls.clear();
+}
+
+bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
+                                              uint32_t *OffsetPtr) {
+  clear();
+  const uint32_t BeginOffset = *OffsetPtr;
+  Offset = BeginOffset;
+  DWARFAbbreviationDeclaration AbbrDecl;
+  uint32_t PrevAbbrCode = 0;
+  while (AbbrDecl.extract(Data, OffsetPtr)) {
+    if (FirstAbbrCode == 0) {
+      FirstAbbrCode = AbbrDecl.getCode();
+    } else {
+      if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
+        // Codes are not consecutive, can't do O(1) lookups.
+        FirstAbbrCode = UINT32_MAX;
+      }
+    }
+    PrevAbbrCode = AbbrDecl.getCode();
+    Decls.push_back(std::move(AbbrDecl));
+  }
+  return BeginOffset != *OffsetPtr;
+}
+
+void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
+  for (const auto &Decl : Decls)
+    Decl.dump(OS);
+}
+
+const DWARFAbbreviationDeclaration *
+DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
+    uint32_t AbbrCode) const {
+  if (FirstAbbrCode == UINT32_MAX) {
+    for (const auto &Decl : Decls) {
+      if (Decl.getCode() == AbbrCode)
+        return &Decl;
+    }
+    return nullptr;
+  }
+  if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
+    return nullptr;
+  return &Decls[AbbrCode - FirstAbbrCode];
+}
+
+DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); }
+
+void DWARFDebugAbbrev::clear() {
+  AbbrDeclSets.clear();
+  PrevAbbrOffsetPos = AbbrDeclSets.end();
+}
+
+void DWARFDebugAbbrev::extract(DataExtractor Data) {
+  clear();
+  this->Data = Data;
+}
+
+void DWARFDebugAbbrev::parse() const {
+  if (!Data)
+    return;
+  uint32_t Offset = 0;
+  DWARFAbbreviationDeclarationSet AbbrDecls;
+  auto I = AbbrDeclSets.begin();
+  while (Data->isValidOffset(Offset)) {
+    while (I != AbbrDeclSets.end() && I->first < Offset)
+      ++I;
+    uint32_t CUAbbrOffset = Offset;
+    if (!AbbrDecls.extract(*Data, &Offset))
+      break;
+    AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));
+  }
+  Data = None;
+}
+
+void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
+  parse();
+
+  if (AbbrDeclSets.empty()) {
+    OS << "< EMPTY >\n";
+    return;
+  }
+
+  for (const auto &I : AbbrDeclSets) {
+    OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
+    I.second.dump(OS);
+  }
+}
+
+const DWARFAbbreviationDeclarationSet*
+DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
+  const auto End = AbbrDeclSets.end();
+  if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
+    return &(PrevAbbrOffsetPos->second);
+  }
+
+  const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
+  if (Pos != End) {
+    PrevAbbrOffsetPos = Pos;
+    return &(Pos->second);
+  }
+
+  if (Data && CUAbbrOffset < Data->getData().size()) {
+    uint32_t Offset = CUAbbrOffset;
+    DWARFAbbreviationDeclarationSet AbbrDecls;
+    if (!AbbrDecls.extract(*Data, &Offset))
+      return nullptr;
+    PrevAbbrOffsetPos =
+        AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))
+            .first;
+    return &PrevAbbrOffsetPos->second;
+  }
+
+  return nullptr;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
new file mode 100644
index 0000000..22759bf
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp
@@ -0,0 +1,198 @@
+//===- DWARFDebugAddr.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+
+using namespace llvm;
+
+void DWARFDebugAddrTable::clear() {
+  HeaderData = {};
+  Addrs.clear();
+  invalidateLength();
+}
+
+Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data,
+                                   uint32_t *OffsetPtr,
+                                   uint16_t Version,
+                                   uint8_t AddrSize,
+                                   std::function<void(Error)> WarnCallback) {
+  clear();
+  HeaderOffset = *OffsetPtr;
+  // Read and verify the length field.
+  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
+    return createStringError(errc::invalid_argument,
+                       "section is not large enough to contain a "
+                       ".debug_addr table length at offset 0x%"
+                       PRIx32, *OffsetPtr);
+  uint16_t UnitVersion;
+  if (Version == 0) {
+    WarnCallback(createStringError(errc::invalid_argument,
+                       "DWARF version is not defined in CU,"
+                       " assuming version 5"));
+    UnitVersion = 5;
+  } else {
+    UnitVersion = Version;
+  }
+  // TODO: Add support for DWARF64.
+  Format = dwarf::DwarfFormat::DWARF32;
+  if (UnitVersion >= 5) {
+    HeaderData.Length = Data.getU32(OffsetPtr);
+    if (HeaderData.Length == 0xffffffffu) {
+      invalidateLength();
+      return createStringError(errc::not_supported,
+          "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32,
+          HeaderOffset);
+    }
+    if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) {
+      uint32_t TmpLength = getLength();
+      invalidateLength();
+      return createStringError(errc::invalid_argument,
+                         ".debug_addr table at offset 0x%" PRIx32
+                         " has too small length (0x%" PRIx32
+                         ") to contain a complete header",
+                         HeaderOffset, TmpLength);
+    }
+    uint32_t End = HeaderOffset + getLength();
+    if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) {
+      uint32_t TmpLength = getLength();
+      invalidateLength();
+      return createStringError(errc::invalid_argument,
+          "section is not large enough to contain a .debug_addr table "
+          "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
+          TmpLength, HeaderOffset);
+    }
+
+    HeaderData.Version = Data.getU16(OffsetPtr);
+    HeaderData.AddrSize = Data.getU8(OffsetPtr);
+    HeaderData.SegSize = Data.getU8(OffsetPtr);
+    DataSize = getDataSize();
+  } else {
+    HeaderData.Version = UnitVersion;
+    HeaderData.AddrSize = AddrSize;
+    // TODO: Support for non-zero SegSize.
+    HeaderData.SegSize = 0;
+    DataSize = Data.size();
+  }
+
+  // Perform basic validation of the remaining header fields.
+
+  // We support DWARF version 5 for now as well as pre-DWARF5
+  // implementations of .debug_addr table, which doesn't contain a header
+  // and consists only of a series of addresses.
+  if (HeaderData.Version > 5) {
+    return createStringError(errc::not_supported, "version %" PRIu16
+        " of .debug_addr section at offset 0x%" PRIx32 " is not supported",
+        HeaderData.Version, HeaderOffset);
+  }
+  // FIXME: For now we just treat version mismatch as an error,
+  // however the correct way to associate a .debug_addr table
+  // with a .debug_info table is to look at the DW_AT_addr_base
+  // attribute in the info table.
+  if (HeaderData.Version != UnitVersion)
+    return createStringError(errc::invalid_argument,
+                       ".debug_addr table at offset 0x%" PRIx32
+                       " has version %" PRIu16
+                       " which is different from the version suggested"
+                       " by the DWARF unit header: %" PRIu16,
+                       HeaderOffset, HeaderData.Version, UnitVersion);
+  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
+    return createStringError(errc::not_supported,
+                       ".debug_addr table at offset 0x%" PRIx32
+                       " has unsupported address size %" PRIu8,
+                       HeaderOffset, HeaderData.AddrSize);
+  if (HeaderData.AddrSize != AddrSize && AddrSize != 0)
+    return createStringError(errc::invalid_argument,
+                       ".debug_addr table at offset 0x%" PRIx32
+                       " has address size %" PRIu8
+                       " which is different from CU address size %" PRIu8,
+                       HeaderOffset, HeaderData.AddrSize, AddrSize);
+
+  // TODO: add support for non-zero segment selector size.
+  if (HeaderData.SegSize != 0)
+    return createStringError(errc::not_supported,
+                       ".debug_addr table at offset 0x%" PRIx32
+                       " has unsupported segment selector size %" PRIu8,
+                       HeaderOffset, HeaderData.SegSize);
+  if (DataSize % HeaderData.AddrSize != 0) {
+    invalidateLength();
+    return createStringError(errc::invalid_argument,
+                       ".debug_addr table at offset 0x%" PRIx32
+                       " contains data of size %" PRIu32
+                       " which is not a multiple of addr size %" PRIu8,
+                       HeaderOffset, DataSize, HeaderData.AddrSize);
+  }
+  Data.setAddressSize(HeaderData.AddrSize);
+  uint32_t AddrCount = DataSize / HeaderData.AddrSize;
+  for (uint32_t I = 0; I < AddrCount; ++I)
+    if (HeaderData.AddrSize == 4)
+      Addrs.push_back(Data.getU32(OffsetPtr));
+    else
+      Addrs.push_back(Data.getU64(OffsetPtr));
+  return Error::success();
+}
+
+void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
+  if (DumpOpts.Verbose)
+    OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
+  OS << format("Addr Section: length = 0x%8.8" PRIx32
+               ", version = 0x%4.4" PRIx16 ", "
+               "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n",
+               HeaderData.Length, HeaderData.Version, HeaderData.AddrSize,
+               HeaderData.SegSize);
+
+  static const char *Fmt32 = "0x%8.8" PRIx64;
+  static const char *Fmt64 = "0x%16.16" PRIx64;
+  std::string AddrFmt = "\n";
+  std::string AddrFmtVerbose = " => ";
+  if (HeaderData.AddrSize == 4) {
+    AddrFmt.append(Fmt32);
+    AddrFmtVerbose.append(Fmt32);
+  }
+  else {
+    AddrFmt.append(Fmt64);
+    AddrFmtVerbose.append(Fmt64);
+  }
+
+  if (Addrs.size() > 0) {
+    OS << "Addrs: [";
+    for (uint64_t Addr : Addrs) {
+      OS << format(AddrFmt.c_str(), Addr);
+      if (DumpOpts.Verbose)
+        OS << format(AddrFmtVerbose.c_str(),
+                     Addr + HeaderOffset + sizeof(HeaderData));
+    }
+    OS << "\n]\n";
+  }
+}
+
+Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
+  if (Index < Addrs.size())
+    return Addrs[Index];
+  return createStringError(errc::invalid_argument,
+                           "Index %" PRIu32 " is out of range of the "
+                           ".debug_addr table at offset 0x%" PRIx32,
+                           Index, HeaderOffset);
+}
+
+uint32_t DWARFDebugAddrTable::getLength() const {
+  if (HeaderData.Length == 0)
+    return 0;
+  // TODO: DWARF64 support.
+  return HeaderData.Length + sizeof(uint32_t);
+}
+
+uint32_t DWARFDebugAddrTable::getDataSize() const {
+  if (DataSize != 0)
+    return DataSize;
+  if (getLength() == 0)
+    return 0;
+  return getLength() - getHeaderSize();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
new file mode 100644
index 0000000..b9ef690
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
@@ -0,0 +1,112 @@
+//===- DWARFDebugArangeSet.cpp --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+
+void DWARFDebugArangeSet::Descriptor::dump(raw_ostream &OS,
+                                           uint32_t AddressSize) const {
+  OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, Address)
+     << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
+               getEndAddress());
+}
+
+void DWARFDebugArangeSet::clear() {
+  Offset = -1U;
+  std::memset(&HeaderData, 0, sizeof(Header));
+  ArangeDescriptors.clear();
+}
+
+bool
+DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) {
+  if (data.isValidOffset(*offset_ptr)) {
+    ArangeDescriptors.clear();
+    Offset = *offset_ptr;
+
+    // 7.20 Address Range Table
+    //
+    // Each set of entries in the table of address ranges contained in
+    // the .debug_aranges section begins with a header consisting of: a
+    // 4-byte length containing the length of the set of entries for this
+    // compilation unit, not including the length field itself; a 2-byte
+    // version identifier containing the value 2 for DWARF Version 2; a
+    // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
+    // containing the size in bytes of an address (or the offset portion of
+    // an address for segmented addressing) on the target system; and a
+    // 1-byte unsigned integer containing the size in bytes of a segment
+    // descriptor on the target system. This header is followed by a series
+    // of tuples. Each tuple consists of an address and a length, each in
+    // the size appropriate for an address on the target architecture.
+    HeaderData.Length = data.getU32(offset_ptr);
+    HeaderData.Version = data.getU16(offset_ptr);
+    HeaderData.CuOffset = data.getU32(offset_ptr);
+    HeaderData.AddrSize = data.getU8(offset_ptr);
+    HeaderData.SegSize = data.getU8(offset_ptr);
+
+    // Perform basic validation of the header fields.
+    if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) ||
+        (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) {
+      clear();
+      return false;
+    }
+
+    // The first tuple following the header in each set begins at an offset
+    // that is a multiple of the size of a single tuple (that is, twice the
+    // size of an address). The header is padded, if necessary, to the
+    // appropriate boundary.
+    const uint32_t header_size = *offset_ptr - Offset;
+    const uint32_t tuple_size = HeaderData.AddrSize * 2;
+    uint32_t first_tuple_offset = 0;
+    while (first_tuple_offset < header_size)
+      first_tuple_offset += tuple_size;
+
+    *offset_ptr = Offset + first_tuple_offset;
+
+    Descriptor arangeDescriptor;
+
+    static_assert(sizeof(arangeDescriptor.Address) ==
+                      sizeof(arangeDescriptor.Length),
+                  "Different datatypes for addresses and sizes!");
+    assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
+
+    while (data.isValidOffset(*offset_ptr)) {
+      arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+      arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+
+      // Each set of tuples is terminated by a 0 for the address and 0
+      // for the length.
+      if (arangeDescriptor.Address || arangeDescriptor.Length)
+        ArangeDescriptors.push_back(arangeDescriptor);
+      else
+        break; // We are done if we get a zero address and length
+    }
+
+    return !ArangeDescriptors.empty();
+  }
+  return false;
+}
+
+void DWARFDebugArangeSet::dump(raw_ostream &OS) const {
+  OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ",
+               HeaderData.Length, HeaderData.Version)
+     << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
+               HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize);
+
+  for (const auto &Desc : ArangeDescriptors) {
+    Desc.dump(OS, HeaderData.AddrSize);
+    OS << '\n';
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
new file mode 100644
index 0000000..e8c5dec
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
@@ -0,0 +1,134 @@
+//===- DWARFDebugAranges.cpp ----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/WithColor.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <set>
+#include <vector>
+
+using namespace llvm;
+
+void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
+  if (!DebugArangesData.isValidOffset(0))
+    return;
+  uint32_t Offset = 0;
+  DWARFDebugArangeSet Set;
+
+  while (Set.extract(DebugArangesData, &Offset)) {
+    uint32_t CUOffset = Set.getCompileUnitDIEOffset();
+    for (const auto &Desc : Set.descriptors()) {
+      uint64_t LowPC = Desc.Address;
+      uint64_t HighPC = Desc.getEndAddress();
+      appendRange(CUOffset, LowPC, HighPC);
+    }
+    ParsedCUOffsets.insert(CUOffset);
+  }
+}
+
+void DWARFDebugAranges::generate(DWARFContext *CTX) {
+  clear();
+  if (!CTX)
+    return;
+
+  // Extract aranges from .debug_aranges section.
+  DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(),
+                            CTX->isLittleEndian(), 0);
+  extract(ArangesData);
+
+  // Generate aranges from DIEs: even if .debug_aranges section is present,
+  // it may describe only a small subset of compilation units, so we need to
+  // manually build aranges for the rest of them.
+  for (const auto &CU : CTX->compile_units()) {
+    uint32_t CUOffset = CU->getOffset();
+    if (ParsedCUOffsets.insert(CUOffset).second) {
+      Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges();
+      if (!CURanges)
+        WithColor::error() << toString(CURanges.takeError()) << '\n';
+      else
+        for (const auto &R : *CURanges)
+          appendRange(CUOffset, R.LowPC, R.HighPC);
+    }
+  }
+
+  construct();
+}
+
+void DWARFDebugAranges::clear() {
+  Endpoints.clear();
+  Aranges.clear();
+  ParsedCUOffsets.clear();
+}
+
+void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
+                                    uint64_t HighPC) {
+  if (LowPC >= HighPC)
+    return;
+  Endpoints.emplace_back(LowPC, CUOffset, true);
+  Endpoints.emplace_back(HighPC, CUOffset, false);
+}
+
+void DWARFDebugAranges::construct() {
+  std::multiset<uint32_t> ValidCUs;  // Maintain the set of CUs describing
+                                     // a current address range.
+  llvm::sort(Endpoints);
+  uint64_t PrevAddress = -1ULL;
+  for (const auto &E : Endpoints) {
+    if (PrevAddress < E.Address && !ValidCUs.empty()) {
+      // If the address range between two endpoints is described by some
+      // CU, first try to extend the last range in Aranges. If we can't
+      // do it, start a new range.
+      if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
+          ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
+        Aranges.back().setHighPC(E.Address);
+      } else {
+        Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
+      }
+    }
+    // Update the set of valid CUs.
+    if (E.IsRangeStart) {
+      ValidCUs.insert(E.CUOffset);
+    } else {
+      auto CUPos = ValidCUs.find(E.CUOffset);
+      assert(CUPos != ValidCUs.end());
+      ValidCUs.erase(CUPos);
+    }
+    PrevAddress = E.Address;
+  }
+  assert(ValidCUs.empty());
+
+  // Endpoints are not needed now.
+  Endpoints.clear();
+  Endpoints.shrink_to_fit();
+}
+
+uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
+  if (!Aranges.empty()) {
+    Range range(Address);
+    RangeCollIterator begin = Aranges.begin();
+    RangeCollIterator end = Aranges.end();
+    RangeCollIterator pos =
+        std::lower_bound(begin, end, range);
+
+    if (pos != end && pos->containsAddress(Address)) {
+      return pos->CUOffset;
+    } else if (pos != begin) {
+      --pos;
+      if (pos->containsAddress(Address))
+        return pos->CUOffset;
+    }
+  }
+  return -1U;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
new file mode 100644
index 0000000..ba55ffc
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -0,0 +1,556 @@
+//===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+
+// See DWARF standard v3, section 7.23
+const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
+const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
+
+Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
+                        uint32_t EndOffset) {
+  while (*Offset < EndOffset) {
+    uint8_t Opcode = Data.getU8(Offset);
+    // Some instructions have a primary opcode encoded in the top bits.
+    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
+
+    if (Primary) {
+      // If it's a primary opcode, the first operand is encoded in the bottom
+      // bits of the opcode itself.
+      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
+      switch (Primary) {
+      default:
+        return createStringError(errc::illegal_byte_sequence,
+                                 "Invalid primary CFI opcode 0x%" PRIx8,
+                                 Primary);
+      case DW_CFA_advance_loc:
+      case DW_CFA_restore:
+        addInstruction(Primary, Op1);
+        break;
+      case DW_CFA_offset:
+        addInstruction(Primary, Op1, Data.getULEB128(Offset));
+        break;
+      }
+    } else {
+      // Extended opcode - its value is Opcode itself.
+      switch (Opcode) {
+      default:
+        return createStringError(errc::illegal_byte_sequence,
+                                 "Invalid extended CFI opcode 0x%" PRIx8,
+                                 Opcode);
+      case DW_CFA_nop:
+      case DW_CFA_remember_state:
+      case DW_CFA_restore_state:
+      case DW_CFA_GNU_window_save:
+        // No operands
+        addInstruction(Opcode);
+        break;
+      case DW_CFA_set_loc:
+        // Operands: Address
+        addInstruction(Opcode, Data.getAddress(Offset));
+        break;
+      case DW_CFA_advance_loc1:
+        // Operands: 1-byte delta
+        addInstruction(Opcode, Data.getU8(Offset));
+        break;
+      case DW_CFA_advance_loc2:
+        // Operands: 2-byte delta
+        addInstruction(Opcode, Data.getU16(Offset));
+        break;
+      case DW_CFA_advance_loc4:
+        // Operands: 4-byte delta
+        addInstruction(Opcode, Data.getU32(Offset));
+        break;
+      case DW_CFA_restore_extended:
+      case DW_CFA_undefined:
+      case DW_CFA_same_value:
+      case DW_CFA_def_cfa_register:
+      case DW_CFA_def_cfa_offset:
+      case DW_CFA_GNU_args_size:
+        // Operands: ULEB128
+        addInstruction(Opcode, Data.getULEB128(Offset));
+        break;
+      case DW_CFA_def_cfa_offset_sf:
+        // Operands: SLEB128
+        addInstruction(Opcode, Data.getSLEB128(Offset));
+        break;
+      case DW_CFA_offset_extended:
+      case DW_CFA_register:
+      case DW_CFA_def_cfa:
+      case DW_CFA_val_offset: {
+        // Operands: ULEB128, ULEB128
+        // Note: We can not embed getULEB128 directly into function
+        // argument list. getULEB128 changes Offset and order of evaluation
+        // for arguments is unspecified.
+        auto op1 = Data.getULEB128(Offset);
+        auto op2 = Data.getULEB128(Offset);
+        addInstruction(Opcode, op1, op2);
+        break;
+        }
+        case DW_CFA_offset_extended_sf:
+        case DW_CFA_def_cfa_sf:
+        case DW_CFA_val_offset_sf: {
+          // Operands: ULEB128, SLEB128
+          // Note: see comment for the previous case
+          auto op1 = Data.getULEB128(Offset);
+          auto op2 = (uint64_t)Data.getSLEB128(Offset);
+          addInstruction(Opcode, op1, op2);
+          break;
+        }
+        case DW_CFA_def_cfa_expression: {
+          uint32_t ExprLength = Data.getULEB128(Offset);
+          addInstruction(Opcode, 0);
+          DataExtractor Extractor(
+              Data.getData().slice(*Offset, *Offset + ExprLength),
+              Data.isLittleEndian(), Data.getAddressSize());
+          Instructions.back().Expression = DWARFExpression(
+              Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
+          *Offset += ExprLength;
+          break;
+        }
+        case DW_CFA_expression:
+        case DW_CFA_val_expression: {
+          auto RegNum = Data.getULEB128(Offset);
+          auto BlockLength = Data.getULEB128(Offset);
+          addInstruction(Opcode, RegNum, 0);
+          DataExtractor Extractor(
+              Data.getData().slice(*Offset, *Offset + BlockLength),
+              Data.isLittleEndian(), Data.getAddressSize());
+          Instructions.back().Expression = DWARFExpression(
+              Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
+          *Offset += BlockLength;
+          break;
+        }
+      }
+    }
+  }
+
+  return Error::success();
+}
+
+namespace {
+
+
+} // end anonymous namespace
+
+ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
+  static OperandType OpTypes[DW_CFA_restore+1][2];
+  static bool Initialized = false;
+  if (Initialized) {
+    return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
+  }
+  Initialized = true;
+
+#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
+  do {                                          \
+    OpTypes[OP][0] = OPTYPE0;                   \
+    OpTypes[OP][1] = OPTYPE1;                   \
+  } while (false)
+#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
+#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
+
+  DECLARE_OP1(DW_CFA_set_loc, OT_Address);
+  DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
+  DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
+  DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
+  DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
+  DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
+  DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
+  DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
+  DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
+  DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
+  DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
+  DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
+  DECLARE_OP1(DW_CFA_undefined, OT_Register);
+  DECLARE_OP1(DW_CFA_same_value, OT_Register);
+  DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
+  DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
+  DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
+  DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
+  DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
+  DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
+  DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
+  DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
+  DECLARE_OP1(DW_CFA_restore, OT_Register);
+  DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
+  DECLARE_OP0(DW_CFA_remember_state);
+  DECLARE_OP0(DW_CFA_restore_state);
+  DECLARE_OP0(DW_CFA_GNU_window_save);
+  DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
+  DECLARE_OP0(DW_CFA_nop);
+
+#undef DECLARE_OP0
+#undef DECLARE_OP1
+#undef DECLARE_OP2
+
+  return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
+}
+
+/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
+void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
+                              bool IsEH, const Instruction &Instr,
+                              unsigned OperandIdx, uint64_t Operand) const {
+  assert(OperandIdx < 2);
+  uint8_t Opcode = Instr.Opcode;
+  OperandType Type = getOperandTypes()[Opcode][OperandIdx];
+
+  switch (Type) {
+  case OT_Unset: {
+    OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
+    auto OpcodeName = CallFrameString(Opcode, Arch);
+    if (!OpcodeName.empty())
+      OS << " " << OpcodeName;
+    else
+      OS << format(" Opcode %x",  Opcode);
+    break;
+  }
+  case OT_None:
+    break;
+  case OT_Address:
+    OS << format(" %" PRIx64, Operand);
+    break;
+  case OT_Offset:
+    // The offsets are all encoded in a unsigned form, but in practice
+    // consumers use them signed. It's most certainly legacy due to
+    // the lack of signed variants in the first Dwarf standards.
+    OS << format(" %+" PRId64, int64_t(Operand));
+    break;
+  case OT_FactoredCodeOffset: // Always Unsigned
+    if (CodeAlignmentFactor)
+      OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
+    else
+      OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
+    break;
+  case OT_SignedFactDataOffset:
+    if (DataAlignmentFactor)
+      OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
+    else
+      OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
+    break;
+  case OT_UnsignedFactDataOffset:
+    if (DataAlignmentFactor)
+      OS << format(" %" PRId64, Operand * DataAlignmentFactor);
+    else
+      OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
+    break;
+  case OT_Register:
+    OS << format(" reg%" PRId64, Operand);
+    break;
+  case OT_Expression:
+    assert(Instr.Expression && "missing DWARFExpression object");
+    OS << " ";
+    Instr.Expression->print(OS, MRI, IsEH);
+    break;
+  }
+}
+
+void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+                      unsigned IndentLevel) const {
+  for (const auto &Instr : Instructions) {
+    uint8_t Opcode = Instr.Opcode;
+    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
+      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
+    OS.indent(2 * IndentLevel);
+    OS << CallFrameString(Opcode, Arch) << ":";
+    for (unsigned i = 0; i < Instr.Ops.size(); ++i)
+      printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
+    OS << '\n';
+  }
+}
+
+void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
+  OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length,
+               DW_CIE_ID)
+     << "\n";
+  OS << format("  Version:               %d\n", Version);
+  OS << "  Augmentation:          \"" << Augmentation << "\"\n";
+  if (Version >= 4) {
+    OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
+    OS << format("  Segment desc size:     %u\n",
+                 (uint32_t)SegmentDescriptorSize);
+  }
+  OS << format("  Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
+  OS << format("  Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
+  OS << format("  Return address column: %d\n", (int32_t)ReturnAddressRegister);
+  if (Personality)
+    OS << format("  Personality Address: %08x\n", *Personality);
+  if (!AugmentationData.empty()) {
+    OS << "  Augmentation data:    ";
+    for (uint8_t Byte : AugmentationData)
+      OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
+    OS << "\n";
+  }
+  OS << "\n";
+  CFIs.dump(OS, MRI, IsEH);
+  OS << "\n";
+}
+
+void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
+  OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length,
+               (int32_t)LinkedCIEOffset);
+  OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
+               (uint32_t)InitialLocation,
+               (uint32_t)InitialLocation + (uint32_t)AddressRange);
+  if (LSDAAddress)
+    OS << format("  LSDA Address: %08x\n", *LSDAAddress);
+  CFIs.dump(OS, MRI, IsEH);
+  OS << "\n";
+}
+
+DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
+    bool IsEH, uint64_t EHFrameAddress)
+    : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
+
+DWARFDebugFrame::~DWARFDebugFrame() = default;
+
+static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
+                                              uint32_t Offset, int Length) {
+  errs() << "DUMP: ";
+  for (int i = 0; i < Length; ++i) {
+    uint8_t c = Data.getU8(&Offset);
+    errs().write_hex(c); errs() << " ";
+  }
+  errs() << "\n";
+}
+
+// This is a workaround for old compilers which do not allow
+// noreturn attribute usage in lambdas. Once the support for those
+// compilers are phased out, we can remove this and return back to
+// a ReportError lambda: [StartOffset](const char *ErrorMsg).
+static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset,
+                                                const char *ErrorMsg) {
+  std::string Str;
+  raw_string_ostream OS(Str);
+  OS << format(ErrorMsg, StartOffset);
+  OS.flush();
+  report_fatal_error(Str);
+}
+
+void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
+  uint32_t Offset = 0;
+  DenseMap<uint32_t, CIE *> CIEs;
+
+  while (Data.isValidOffset(Offset)) {
+    uint32_t StartOffset = Offset;
+
+    bool IsDWARF64 = false;
+    uint64_t Length = Data.getU32(&Offset);
+    uint64_t Id;
+
+    if (Length == UINT32_MAX) {
+      // DWARF-64 is distinguished by the first 32 bits of the initial length
+      // field being 0xffffffff. Then, the next 64 bits are the actual entry
+      // length.
+      IsDWARF64 = true;
+      Length = Data.getU64(&Offset);
+    }
+
+    // At this point, Offset points to the next field after Length.
+    // Length is the structure size excluding itself. Compute an offset one
+    // past the end of the structure (needed to know how many instructions to
+    // read).
+    // TODO: For honest DWARF64 support, DataExtractor will have to treat
+    //       offset_ptr as uint64_t*
+    uint32_t StartStructureOffset = Offset;
+    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
+
+    // The Id field's size depends on the DWARF format
+    Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
+    bool IsCIE =
+        ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id));
+
+    if (IsCIE) {
+      uint8_t Version = Data.getU8(&Offset);
+      const char *Augmentation = Data.getCStr(&Offset);
+      StringRef AugmentationString(Augmentation ? Augmentation : "");
+      uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
+                                          Data.getU8(&Offset);
+      Data.setAddressSize(AddressSize);
+      uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
+      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
+      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
+      uint64_t ReturnAddressRegister =
+          Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
+
+      // Parse the augmentation data for EH CIEs
+      StringRef AugmentationData("");
+      uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
+      uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
+      Optional<uint64_t> Personality;
+      Optional<uint32_t> PersonalityEncoding;
+      if (IsEH) {
+        Optional<uint64_t> AugmentationLength;
+        uint32_t StartAugmentationOffset;
+        uint32_t EndAugmentationOffset;
+
+        // Walk the augmentation string to get all the augmentation data.
+        for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
+          switch (AugmentationString[i]) {
+            default:
+              ReportError(StartOffset,
+                          "Unknown augmentation character in entry at %lx");
+            case 'L':
+              LSDAPointerEncoding = Data.getU8(&Offset);
+              break;
+            case 'P': {
+              if (Personality)
+                ReportError(StartOffset,
+                            "Duplicate personality in entry at %lx");
+              PersonalityEncoding = Data.getU8(&Offset);
+              Personality = Data.getEncodedPointer(
+                  &Offset, *PersonalityEncoding,
+                  EHFrameAddress ? EHFrameAddress + Offset : 0);
+              break;
+            }
+            case 'R':
+              FDEPointerEncoding = Data.getU8(&Offset);
+              break;
+            case 'S':
+              // Current frame is a signal trampoline.
+              break;
+            case 'z':
+              if (i)
+                ReportError(StartOffset,
+                            "'z' must be the first character at %lx");
+              // Parse the augmentation length first.  We only parse it if
+              // the string contains a 'z'.
+              AugmentationLength = Data.getULEB128(&Offset);
+              StartAugmentationOffset = Offset;
+              EndAugmentationOffset = Offset +
+                static_cast<uint32_t>(*AugmentationLength);
+              break;
+            case 'B':
+              // B-Key is used for signing functions associated with this
+              // augmentation string
+              break;
+          }
+        }
+
+        if (AugmentationLength.hasValue()) {
+          if (Offset != EndAugmentationOffset)
+            ReportError(StartOffset, "Parsing augmentation data at %lx failed");
+
+          AugmentationData = Data.getData().slice(StartAugmentationOffset,
+                                                  EndAugmentationOffset);
+        }
+      }
+
+      auto Cie = llvm::make_unique<CIE>(
+          StartOffset, Length, Version, AugmentationString, AddressSize,
+          SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
+          ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
+          LSDAPointerEncoding, Personality, PersonalityEncoding, Arch);
+      CIEs[StartOffset] = Cie.get();
+      Entries.emplace_back(std::move(Cie));
+    } else {
+      // FDE
+      uint64_t CIEPointer = Id;
+      uint64_t InitialLocation = 0;
+      uint64_t AddressRange = 0;
+      Optional<uint64_t> LSDAAddress;
+      CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
+
+      if (IsEH) {
+        // The address size is encoded in the CIE we reference.
+        if (!Cie)
+          ReportError(StartOffset,
+                      "Parsing FDE data at %lx failed due to missing CIE");
+
+        if (auto Val = Data.getEncodedPointer(
+                &Offset, Cie->getFDEPointerEncoding(),
+                EHFrameAddress ? EHFrameAddress + Offset : 0)) {
+          InitialLocation = *Val;
+        }
+        if (auto Val = Data.getEncodedPointer(
+                &Offset, Cie->getFDEPointerEncoding(), 0)) {
+          AddressRange = *Val;
+        }
+
+        StringRef AugmentationString = Cie->getAugmentationString();
+        if (!AugmentationString.empty()) {
+          // Parse the augmentation length and data for this FDE.
+          uint64_t AugmentationLength = Data.getULEB128(&Offset);
+
+          uint32_t EndAugmentationOffset =
+            Offset + static_cast<uint32_t>(AugmentationLength);
+
+          // Decode the LSDA if the CIE augmentation string said we should.
+          if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
+            LSDAAddress = Data.getEncodedPointer(
+                &Offset, Cie->getLSDAPointerEncoding(),
+                EHFrameAddress ? Offset + EHFrameAddress : 0);
+          }
+
+          if (Offset != EndAugmentationOffset)
+            ReportError(StartOffset, "Parsing augmentation data at %lx failed");
+        }
+      } else {
+        InitialLocation = Data.getAddress(&Offset);
+        AddressRange = Data.getAddress(&Offset);
+      }
+
+      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
+                                   InitialLocation, AddressRange,
+                                   Cie, LSDAAddress, Arch));
+    }
+
+    if (Error E =
+            Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) {
+      report_fatal_error(toString(std::move(E)));
+    }
+
+    if (Offset != EndStructureOffset)
+      ReportError(StartOffset, "Parsing entry instructions at %lx failed");
+  }
+}
+
+FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
+  auto It =
+      std::lower_bound(Entries.begin(), Entries.end(), Offset,
+                       [](const std::unique_ptr<FrameEntry> &E,
+                          uint64_t Offset) { return E->getOffset() < Offset; });
+  if (It != Entries.end() && (*It)->getOffset() == Offset)
+    return It->get();
+  return nullptr;
+}
+
+void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+                           Optional<uint64_t> Offset) const {
+  if (Offset) {
+    if (auto *Entry = getEntryAtOffset(*Offset))
+      Entry->dump(OS, MRI, IsEH);
+    return;
+  }
+
+  OS << "\n";
+  for (const auto &Entry : Entries)
+    Entry->dump(OS, MRI, IsEH);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
new file mode 100644
index 0000000..976bc46
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
@@ -0,0 +1,70 @@
+//===- DWARFDebugInfoEntry.cpp --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace dwarf;
+
+bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U,
+                                             uint32_t *OffsetPtr) {
+  DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
+  const uint32_t UEndOffset = U.getNextUnitOffset();
+  return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset, 0);
+}
+
+bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
+                                      const DWARFDataExtractor &DebugInfoData,
+                                      uint32_t UEndOffset, uint32_t D) {
+  Offset = *OffsetPtr;
+  Depth = D;
+  if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
+    return false;
+  uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
+  if (0 == AbbrCode) {
+    // NULL debug tag entry.
+    AbbrevDecl = nullptr;
+    return true;
+  }
+  AbbrevDecl = U.getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+  if (nullptr == AbbrevDecl) {
+    // Restore the original offset.
+    *OffsetPtr = Offset;
+    return false;
+  }
+  // See if all attributes in this DIE have fixed byte sizes. If so, we can
+  // just add this size to the offset to skip to the next DIE.
+  if (Optional<size_t> FixedSize = AbbrevDecl->getFixedAttributesByteSize(U)) {
+    *OffsetPtr += *FixedSize;
+    return true;
+  }
+
+  // Skip all data in the .debug_info for the attributes
+  for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+    // Check if this attribute has a fixed byte size.
+    if (auto FixedSize = AttrSpec.getByteSize(U)) {
+      // Attribute byte size if fixed, just add the size to the offset.
+      *OffsetPtr += *FixedSize;
+    } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData,
+                                          OffsetPtr, U.getFormParams())) {
+      // We failed to skip this attribute's value, restore the original offset
+      // and return the failure status.
+      *OffsetPtr = Offset;
+      return false;
+    }
+  }
+  return true;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
new file mode 100644
index 0000000..1d621ff
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -0,0 +1,1114 @@
+//===- DWARFDebugLine.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+#include <utility>
+
+using namespace llvm;
+using namespace dwarf;
+
+using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
+
+namespace {
+
+struct ContentDescriptor {
+  dwarf::LineNumberEntryFormat Type;
+  dwarf::Form Form;
+};
+
+using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
+
+} // end anonmyous namespace
+
+void DWARFDebugLine::ContentTypeTracker::trackContentType(
+    dwarf::LineNumberEntryFormat ContentType) {
+  switch (ContentType) {
+  case dwarf::DW_LNCT_timestamp:
+    HasModTime = true;
+    break;
+  case dwarf::DW_LNCT_size:
+    HasLength = true;
+    break;
+  case dwarf::DW_LNCT_MD5:
+    HasMD5 = true;
+    break;
+  case dwarf::DW_LNCT_LLVM_source:
+    HasSource = true;
+    break;
+  default:
+    // We only care about values we consider optional, and new values may be
+    // added in the vendor extension range, so we do not match exhaustively.
+    break;
+  }
+}
+
+DWARFDebugLine::Prologue::Prologue() { clear(); }
+
+void DWARFDebugLine::Prologue::clear() {
+  TotalLength = PrologueLength = 0;
+  SegSelectorSize = 0;
+  MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
+  OpcodeBase = 0;
+  FormParams = dwarf::FormParams({0, 0, DWARF32});
+  ContentTypes = ContentTypeTracker();
+  StandardOpcodeLengths.clear();
+  IncludeDirectories.clear();
+  FileNames.clear();
+}
+
+void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
+                                    DIDumpOptions DumpOptions) const {
+  OS << "Line table prologue:\n"
+     << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength)
+     << format("         version: %u\n", getVersion());
+  if (getVersion() >= 5)
+    OS << format("    address_size: %u\n", getAddressSize())
+       << format(" seg_select_size: %u\n", SegSelectorSize);
+  OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
+     << format(" min_inst_length: %u\n", MinInstLength)
+     << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
+     << format(" default_is_stmt: %u\n", DefaultIsStmt)
+     << format("       line_base: %i\n", LineBase)
+     << format("      line_range: %u\n", LineRange)
+     << format("     opcode_base: %u\n", OpcodeBase);
+
+  for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
+    OS << format("standard_opcode_lengths[%s] = %u\n",
+                 LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
+
+  if (!IncludeDirectories.empty()) {
+    // DWARF v5 starts directory indexes at 0.
+    uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
+    for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {
+      OS << format("include_directories[%3u] = ", I + DirBase);
+      IncludeDirectories[I].dump(OS, DumpOptions);
+      OS << '\n';
+    }
+  }
+
+  if (!FileNames.empty()) {
+    // DWARF v5 starts file indexes at 0.
+    uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
+    for (uint32_t I = 0; I != FileNames.size(); ++I) {
+      const FileNameEntry &FileEntry = FileNames[I];
+      OS <<   format("file_names[%3u]:\n", I + FileBase);
+      OS <<          "           name: ";
+      FileEntry.Name.dump(OS, DumpOptions);
+      OS << '\n'
+         <<   format("      dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
+      if (ContentTypes.HasMD5)
+        OS <<        "   md5_checksum: " << FileEntry.Checksum.digest() << '\n';
+      if (ContentTypes.HasModTime)
+        OS << format("       mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
+      if (ContentTypes.HasLength)
+        OS << format("         length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
+      if (ContentTypes.HasSource) {
+        OS <<        "         source: ";
+        FileEntry.Source.dump(OS, DumpOptions);
+        OS << '\n';
+      }
+    }
+  }
+}
+
+// Parse v2-v4 directory and file tables.
+static void
+parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
+                     uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
+                     DWARFDebugLine::ContentTypeTracker &ContentTypes,
+                     std::vector<DWARFFormValue> &IncludeDirectories,
+                     std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
+  while (*OffsetPtr < EndPrologueOffset) {
+    StringRef S = DebugLineData.getCStrRef(OffsetPtr);
+    if (S.empty())
+      break;
+    DWARFFormValue Dir(dwarf::DW_FORM_string);
+    Dir.setPValue(S.data());
+    IncludeDirectories.push_back(Dir);
+  }
+
+  while (*OffsetPtr < EndPrologueOffset) {
+    StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
+    if (Name.empty())
+      break;
+    DWARFDebugLine::FileNameEntry FileEntry;
+    FileEntry.Name.setForm(dwarf::DW_FORM_string);
+    FileEntry.Name.setPValue(Name.data());
+    FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
+    FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
+    FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
+    FileNames.push_back(FileEntry);
+  }
+
+  ContentTypes.HasModTime = true;
+  ContentTypes.HasLength = true;
+}
+
+// Parse v5 directory/file entry content descriptions.
+// Returns the descriptors, or an empty vector if we did not find a path or
+// ran off the end of the prologue.
+static ContentDescriptors
+parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t
+    *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker
+    *ContentTypes) {
+  ContentDescriptors Descriptors;
+  int FormatCount = DebugLineData.getU8(OffsetPtr);
+  bool HasPath = false;
+  for (int I = 0; I != FormatCount; ++I) {
+    if (*OffsetPtr >= EndPrologueOffset)
+      return ContentDescriptors();
+    ContentDescriptor Descriptor;
+    Descriptor.Type =
+      dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
+    Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
+    if (Descriptor.Type == dwarf::DW_LNCT_path)
+      HasPath = true;
+    if (ContentTypes)
+      ContentTypes->trackContentType(Descriptor.Type);
+    Descriptors.push_back(Descriptor);
+  }
+  return HasPath ? Descriptors : ContentDescriptors();
+}
+
+static bool
+parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
+                     uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
+                     const dwarf::FormParams &FormParams,
+                     const DWARFContext &Ctx, const DWARFUnit *U,
+                     DWARFDebugLine::ContentTypeTracker &ContentTypes,
+                     std::vector<DWARFFormValue> &IncludeDirectories,
+                     std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
+  // Get the directory entry description.
+  ContentDescriptors DirDescriptors =
+      parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr);
+  if (DirDescriptors.empty())
+    return false;
+
+  // Get the directory entries, according to the format described above.
+  int DirEntryCount = DebugLineData.getU8(OffsetPtr);
+  for (int I = 0; I != DirEntryCount; ++I) {
+    if (*OffsetPtr >= EndPrologueOffset)
+      return false;
+    for (auto Descriptor : DirDescriptors) {
+      DWARFFormValue Value(Descriptor.Form);
+      switch (Descriptor.Type) {
+      case DW_LNCT_path:
+        if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
+          return false;
+        IncludeDirectories.push_back(Value);
+        break;
+      default:
+        if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
+          return false;
+      }
+    }
+  }
+
+  // Get the file entry description.
+  ContentDescriptors FileDescriptors =
+      parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset,
+          &ContentTypes);
+  if (FileDescriptors.empty())
+    return false;
+
+  // Get the file entries, according to the format described above.
+  int FileEntryCount = DebugLineData.getU8(OffsetPtr);
+  for (int I = 0; I != FileEntryCount; ++I) {
+    if (*OffsetPtr >= EndPrologueOffset)
+      return false;
+    DWARFDebugLine::FileNameEntry FileEntry;
+    for (auto Descriptor : FileDescriptors) {
+      DWARFFormValue Value(Descriptor.Form);
+      if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
+        return false;
+      switch (Descriptor.Type) {
+      case DW_LNCT_path:
+        FileEntry.Name = Value;
+        break;
+      case DW_LNCT_LLVM_source:
+        FileEntry.Source = Value;
+        break;
+      case DW_LNCT_directory_index:
+        FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
+        break;
+      case DW_LNCT_timestamp:
+        FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
+        break;
+      case DW_LNCT_size:
+        FileEntry.Length = Value.getAsUnsignedConstant().getValue();
+        break;
+      case DW_LNCT_MD5:
+        assert(Value.getAsBlock().getValue().size() == 16);
+        std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16,
+                                  FileEntry.Checksum.Bytes.begin());
+        break;
+      default:
+        break;
+      }
+    }
+    FileNames.push_back(FileEntry);
+  }
+  return true;
+}
+
+Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
+                                      uint32_t *OffsetPtr,
+                                      const DWARFContext &Ctx,
+                                      const DWARFUnit *U) {
+  const uint64_t PrologueOffset = *OffsetPtr;
+
+  clear();
+  TotalLength = DebugLineData.getU32(OffsetPtr);
+  if (TotalLength == UINT32_MAX) {
+    FormParams.Format = dwarf::DWARF64;
+    TotalLength = DebugLineData.getU64(OffsetPtr);
+  } else if (TotalLength >= 0xffffff00) {
+    return createStringError(errc::invalid_argument,
+        "parsing line table prologue at offset 0x%8.8" PRIx64
+        " unsupported reserved unit length found of value 0x%8.8" PRIx64,
+        PrologueOffset, TotalLength);
+  }
+  FormParams.Version = DebugLineData.getU16(OffsetPtr);
+  if (getVersion() < 2)
+    return createStringError(errc::not_supported,
+                       "parsing line table prologue at offset 0x%8.8" PRIx64
+                       " found unsupported version 0x%2.2" PRIx16,
+                       PrologueOffset, getVersion());
+
+  if (getVersion() >= 5) {
+    FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
+    assert((DebugLineData.getAddressSize() == 0 ||
+            DebugLineData.getAddressSize() == getAddressSize()) &&
+           "Line table header and data extractor disagree");
+    SegSelectorSize = DebugLineData.getU8(OffsetPtr);
+  }
+
+  PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
+  const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
+  MinInstLength = DebugLineData.getU8(OffsetPtr);
+  if (getVersion() >= 4)
+    MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
+  DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
+  LineBase = DebugLineData.getU8(OffsetPtr);
+  LineRange = DebugLineData.getU8(OffsetPtr);
+  OpcodeBase = DebugLineData.getU8(OffsetPtr);
+
+  StandardOpcodeLengths.reserve(OpcodeBase - 1);
+  for (uint32_t I = 1; I < OpcodeBase; ++I) {
+    uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
+    StandardOpcodeLengths.push_back(OpLen);
+  }
+
+  if (getVersion() >= 5) {
+    if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
+                              FormParams, Ctx, U, ContentTypes,
+                              IncludeDirectories, FileNames)) {
+      return createStringError(errc::invalid_argument,
+          "parsing line table prologue at 0x%8.8" PRIx64
+          " found an invalid directory or file table description at"
+          " 0x%8.8" PRIx64,
+          PrologueOffset, (uint64_t)*OffsetPtr);
+    }
+  } else
+    parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
+                         ContentTypes, IncludeDirectories, FileNames);
+
+  if (*OffsetPtr != EndPrologueOffset)
+    return createStringError(errc::invalid_argument,
+                       "parsing line table prologue at 0x%8.8" PRIx64
+                       " should have ended at 0x%8.8" PRIx64
+                       " but it ended at 0x%8.8" PRIx64,
+                       PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
+  return Error::success();
+}
+
+DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
+
+void DWARFDebugLine::Row::postAppend() {
+  BasicBlock = false;
+  PrologueEnd = false;
+  EpilogueBegin = false;
+}
+
+void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
+  Address = 0;
+  Line = 1;
+  Column = 0;
+  File = 1;
+  Isa = 0;
+  Discriminator = 0;
+  IsStmt = DefaultIsStmt;
+  BasicBlock = false;
+  EndSequence = false;
+  PrologueEnd = false;
+  EpilogueBegin = false;
+}
+
+void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
+  OS << "Address            Line   Column File   ISA Discriminator Flags\n"
+     << "------------------ ------ ------ ------ --- ------------- "
+        "-------------\n";
+}
+
+void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
+  OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
+     << format(" %6u %3u %13u ", File, Isa, Discriminator)
+     << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
+     << (PrologueEnd ? " prologue_end" : "")
+     << (EpilogueBegin ? " epilogue_begin" : "")
+     << (EndSequence ? " end_sequence" : "") << '\n';
+}
+
+DWARFDebugLine::Sequence::Sequence() { reset(); }
+
+void DWARFDebugLine::Sequence::reset() {
+  LowPC = 0;
+  HighPC = 0;
+  FirstRowIndex = 0;
+  LastRowIndex = 0;
+  Empty = true;
+}
+
+DWARFDebugLine::LineTable::LineTable() { clear(); }
+
+void DWARFDebugLine::LineTable::dump(raw_ostream &OS,
+                                     DIDumpOptions DumpOptions) const {
+  Prologue.dump(OS, DumpOptions);
+  OS << '\n';
+
+  if (!Rows.empty()) {
+    Row::dumpTableHeader(OS);
+    for (const Row &R : Rows) {
+      R.dump(OS);
+    }
+  }
+}
+
+void DWARFDebugLine::LineTable::clear() {
+  Prologue.clear();
+  Rows.clear();
+  Sequences.clear();
+}
+
+DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
+    : LineTable(LT) {
+  resetRowAndSequence();
+}
+
+void DWARFDebugLine::ParsingState::resetRowAndSequence() {
+  Row.reset(LineTable->Prologue.DefaultIsStmt);
+  Sequence.reset();
+}
+
+void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
+  if (Sequence.Empty) {
+    // Record the beginning of instruction sequence.
+    Sequence.Empty = false;
+    Sequence.LowPC = Row.Address;
+    Sequence.FirstRowIndex = RowNumber;
+  }
+  ++RowNumber;
+  LineTable->appendRow(Row);
+  if (Row.EndSequence) {
+    // Record the end of instruction sequence.
+    Sequence.HighPC = Row.Address;
+    Sequence.LastRowIndex = RowNumber;
+    if (Sequence.isValid())
+      LineTable->appendSequence(Sequence);
+    Sequence.reset();
+  }
+  Row.postAppend();
+}
+
+const DWARFDebugLine::LineTable *
+DWARFDebugLine::getLineTable(uint32_t Offset) const {
+  LineTableConstIter Pos = LineTableMap.find(Offset);
+  if (Pos != LineTableMap.end())
+    return &Pos->second;
+  return nullptr;
+}
+
+Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(
+    DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx,
+    const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) {
+  if (!DebugLineData.isValidOffset(Offset))
+    return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx32
+                       " is not a valid debug line section offset",
+                       Offset);
+
+  std::pair<LineTableIter, bool> Pos =
+      LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
+  LineTable *LT = &Pos.first->second;
+  if (Pos.second) {
+    if (Error Err =
+            LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback))
+      return std::move(Err);
+    return LT;
+  }
+  return LT;
+}
+
+Error DWARFDebugLine::LineTable::parse(
+    DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+    const DWARFContext &Ctx, const DWARFUnit *U,
+    std::function<void(Error)> RecoverableErrorCallback, raw_ostream *OS) {
+  const uint32_t DebugLineOffset = *OffsetPtr;
+
+  clear();
+
+  Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr, Ctx, U);
+
+  if (OS) {
+    // The presence of OS signals verbose dumping.
+    DIDumpOptions DumpOptions;
+    DumpOptions.Verbose = true;
+    Prologue.dump(*OS, DumpOptions);
+  }
+
+  if (PrologueErr)
+    return PrologueErr;
+
+  const uint32_t EndOffset =
+      DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
+
+  // See if we should tell the data extractor the address size.
+  if (DebugLineData.getAddressSize() == 0)
+    DebugLineData.setAddressSize(Prologue.getAddressSize());
+  else
+    assert(Prologue.getAddressSize() == 0 ||
+           Prologue.getAddressSize() == DebugLineData.getAddressSize());
+
+  ParsingState State(this);
+
+  while (*OffsetPtr < EndOffset) {
+    if (OS)
+      *OS << format("0x%08.08" PRIx32 ": ", *OffsetPtr);
+
+    uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
+
+    if (OS)
+      *OS << format("%02.02" PRIx8 " ", Opcode);
+
+    if (Opcode == 0) {
+      // Extended Opcodes always start with a zero opcode followed by
+      // a uleb128 length so you can skip ones you don't know about
+      uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
+      uint32_t ExtOffset = *OffsetPtr;
+
+      // Tolerate zero-length; assume length is correct and soldier on.
+      if (Len == 0) {
+        if (OS)
+          *OS << "Badly formed extended line op (length 0)\n";
+        continue;
+      }
+
+      uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
+      if (OS)
+        *OS << LNExtendedString(SubOpcode);
+      switch (SubOpcode) {
+      case DW_LNE_end_sequence:
+        // Set the end_sequence register of the state machine to true and
+        // append a row to the matrix using the current values of the
+        // state-machine registers. Then reset the registers to the initial
+        // values specified above. Every statement program sequence must end
+        // with a DW_LNE_end_sequence instruction which creates a row whose
+        // address is that of the byte after the last target machine instruction
+        // of the sequence.
+        State.Row.EndSequence = true;
+        State.appendRowToMatrix(*OffsetPtr);
+        if (OS) {
+          *OS << "\n";
+          OS->indent(12);
+          State.Row.dump(*OS);
+        }
+        State.resetRowAndSequence();
+        break;
+
+      case DW_LNE_set_address:
+        // Takes a single relocatable address as an operand. The size of the
+        // operand is the size appropriate to hold an address on the target
+        // machine. Set the address register to the value given by the
+        // relocatable address. All of the other statement program opcodes
+        // that affect the address register add a delta to it. This instruction
+        // stores a relocatable value into it instead.
+        //
+        // Make sure the extractor knows the address size.  If not, infer it
+        // from the size of the operand.
+        if (DebugLineData.getAddressSize() == 0)
+          DebugLineData.setAddressSize(Len - 1);
+        else if (DebugLineData.getAddressSize() != Len - 1) {
+          return createStringError(errc::invalid_argument,
+                             "mismatching address size at offset 0x%8.8" PRIx32
+                             " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,
+                             ExtOffset, DebugLineData.getAddressSize(),
+                             Len - 1);
+        }
+        State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr);
+        if (OS)
+          *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address);
+        break;
+
+      case DW_LNE_define_file:
+        // Takes 4 arguments. The first is a null terminated string containing
+        // a source file name. The second is an unsigned LEB128 number
+        // representing the directory index of the directory in which the file
+        // was found. The third is an unsigned LEB128 number representing the
+        // time of last modification of the file. The fourth is an unsigned
+        // LEB128 number representing the length in bytes of the file. The time
+        // and length fields may contain LEB128(0) if the information is not
+        // available.
+        //
+        // The directory index represents an entry in the include_directories
+        // section of the statement program prologue. The index is LEB128(0)
+        // if the file was found in the current directory of the compilation,
+        // LEB128(1) if it was found in the first directory in the
+        // include_directories section, and so on. The directory index is
+        // ignored for file names that represent full path names.
+        //
+        // The files are numbered, starting at 1, in the order in which they
+        // appear; the names in the prologue come before names defined by
+        // the DW_LNE_define_file instruction. These numbers are used in the
+        // the file register of the state machine.
+        {
+          FileNameEntry FileEntry;
+          const char *Name = DebugLineData.getCStr(OffsetPtr);
+          FileEntry.Name.setForm(dwarf::DW_FORM_string);
+          FileEntry.Name.setPValue(Name);
+          FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
+          FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
+          FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
+          Prologue.FileNames.push_back(FileEntry);
+          if (OS)
+            *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
+                << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)
+                << ", length=" << FileEntry.Length << ")";
+        }
+        break;
+
+      case DW_LNE_set_discriminator:
+        State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
+        if (OS)
+          *OS << " (" << State.Row.Discriminator << ")";
+        break;
+
+      default:
+        if (OS)
+          *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
+              << format(" length %" PRIx64, Len);
+        // Len doesn't include the zero opcode byte or the length itself, but
+        // it does include the sub_opcode, so we have to adjust for that.
+        (*OffsetPtr) += Len - 1;
+        break;
+      }
+      // Make sure the stated and parsed lengths are the same.
+      // Otherwise we have an unparseable line-number program.
+      if (*OffsetPtr - ExtOffset != Len)
+        return createStringError(errc::illegal_byte_sequence,
+                           "unexpected line op length at offset 0x%8.8" PRIx32
+                           " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32,
+                           ExtOffset, Len, *OffsetPtr - ExtOffset);
+    } else if (Opcode < Prologue.OpcodeBase) {
+      if (OS)
+        *OS << LNStandardString(Opcode);
+      switch (Opcode) {
+      // Standard Opcodes
+      case DW_LNS_copy:
+        // Takes no arguments. Append a row to the matrix using the
+        // current values of the state-machine registers. Then set
+        // the basic_block register to false.
+        State.appendRowToMatrix(*OffsetPtr);
+        if (OS) {
+          *OS << "\n";
+          OS->indent(12);
+          State.Row.dump(*OS);
+          *OS << "\n";
+        }
+        break;
+
+      case DW_LNS_advance_pc:
+        // Takes a single unsigned LEB128 operand, multiplies it by the
+        // min_inst_length field of the prologue, and adds the
+        // result to the address register of the state machine.
+        {
+          uint64_t AddrOffset =
+              DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
+          State.Row.Address += AddrOffset;
+          if (OS)
+            *OS << " (" << AddrOffset << ")";
+        }
+        break;
+
+      case DW_LNS_advance_line:
+        // Takes a single signed LEB128 operand and adds that value to
+        // the line register of the state machine.
+        State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
+        if (OS)
+          *OS << " (" << State.Row.Line << ")";
+        break;
+
+      case DW_LNS_set_file:
+        // Takes a single unsigned LEB128 operand and stores it in the file
+        // register of the state machine.
+        State.Row.File = DebugLineData.getULEB128(OffsetPtr);
+        if (OS)
+          *OS << " (" << State.Row.File << ")";
+        break;
+
+      case DW_LNS_set_column:
+        // Takes a single unsigned LEB128 operand and stores it in the
+        // column register of the state machine.
+        State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
+        if (OS)
+          *OS << " (" << State.Row.Column << ")";
+        break;
+
+      case DW_LNS_negate_stmt:
+        // Takes no arguments. Set the is_stmt register of the state
+        // machine to the logical negation of its current value.
+        State.Row.IsStmt = !State.Row.IsStmt;
+        break;
+
+      case DW_LNS_set_basic_block:
+        // Takes no arguments. Set the basic_block register of the
+        // state machine to true
+        State.Row.BasicBlock = true;
+        break;
+
+      case DW_LNS_const_add_pc:
+        // Takes no arguments. Add to the address register of the state
+        // machine the address increment value corresponding to special
+        // opcode 255. The motivation for DW_LNS_const_add_pc is this:
+        // when the statement program needs to advance the address by a
+        // small amount, it can use a single special opcode, which occupies
+        // a single byte. When it needs to advance the address by up to
+        // twice the range of the last special opcode, it can use
+        // DW_LNS_const_add_pc followed by a special opcode, for a total
+        // of two bytes. Only if it needs to advance the address by more
+        // than twice that range will it need to use both DW_LNS_advance_pc
+        // and a special opcode, requiring three or more bytes.
+        {
+          uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
+          uint64_t AddrOffset =
+              (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
+          State.Row.Address += AddrOffset;
+          if (OS)
+            *OS
+                << format(" (0x%16.16" PRIx64 ")", AddrOffset);
+        }
+        break;
+
+      case DW_LNS_fixed_advance_pc:
+        // Takes a single uhalf operand. Add to the address register of
+        // the state machine the value of the (unencoded) operand. This
+        // is the only extended opcode that takes an argument that is not
+        // a variable length number. The motivation for DW_LNS_fixed_advance_pc
+        // is this: existing assemblers cannot emit DW_LNS_advance_pc or
+        // special opcodes because they cannot encode LEB128 numbers or
+        // judge when the computation of a special opcode overflows and
+        // requires the use of DW_LNS_advance_pc. Such assemblers, however,
+        // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+        {
+          uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
+          State.Row.Address += PCOffset;
+          if (OS)
+            *OS
+                << format(" (0x%16.16" PRIx64 ")", PCOffset);
+        }
+        break;
+
+      case DW_LNS_set_prologue_end:
+        // Takes no arguments. Set the prologue_end register of the
+        // state machine to true
+        State.Row.PrologueEnd = true;
+        break;
+
+      case DW_LNS_set_epilogue_begin:
+        // Takes no arguments. Set the basic_block register of the
+        // state machine to true
+        State.Row.EpilogueBegin = true;
+        break;
+
+      case DW_LNS_set_isa:
+        // Takes a single unsigned LEB128 operand and stores it in the
+        // column register of the state machine.
+        State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
+        if (OS)
+          *OS << " (" << State.Row.Isa << ")";
+        break;
+
+      default:
+        // Handle any unknown standard opcodes here. We know the lengths
+        // of such opcodes because they are specified in the prologue
+        // as a multiple of LEB128 operands for each opcode.
+        {
+          assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
+          uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
+          for (uint8_t I = 0; I < OpcodeLength; ++I) {
+            uint64_t Value = DebugLineData.getULEB128(OffsetPtr);
+            if (OS)
+              *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
+                            Value);
+          }
+        }
+        break;
+      }
+    } else {
+      // Special Opcodes
+
+      // A special opcode value is chosen based on the amount that needs
+      // to be added to the line and address registers. The maximum line
+      // increment for a special opcode is the value of the line_base
+      // field in the header, plus the value of the line_range field,
+      // minus 1 (line base + line range - 1). If the desired line
+      // increment is greater than the maximum line increment, a standard
+      // opcode must be used instead of a special opcode. The "address
+      // advance" is calculated by dividing the desired address increment
+      // by the minimum_instruction_length field from the header. The
+      // special opcode is then calculated using the following formula:
+      //
+      //  opcode = (desired line increment - line_base) +
+      //           (line_range * address advance) + opcode_base
+      //
+      // If the resulting opcode is greater than 255, a standard opcode
+      // must be used instead.
+      //
+      // To decode a special opcode, subtract the opcode_base from the
+      // opcode itself to give the adjusted opcode. The amount to
+      // increment the address register is the result of the adjusted
+      // opcode divided by the line_range multiplied by the
+      // minimum_instruction_length field from the header. That is:
+      //
+      //  address increment = (adjusted opcode / line_range) *
+      //                      minimum_instruction_length
+      //
+      // The amount to increment the line register is the line_base plus
+      // the result of the adjusted opcode modulo the line_range. That is:
+      //
+      // line increment = line_base + (adjusted opcode % line_range)
+
+      uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
+      uint64_t AddrOffset =
+          (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
+      int32_t LineOffset =
+          Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
+      State.Row.Line += LineOffset;
+      State.Row.Address += AddrOffset;
+
+      if (OS) {
+        *OS << "address += " << ((uint32_t)AdjustOpcode)
+            << ",  line += " << LineOffset << "\n";
+        OS->indent(12);
+        State.Row.dump(*OS);
+      }
+
+      State.appendRowToMatrix(*OffsetPtr);
+      // Reset discriminator to 0.
+      State.Row.Discriminator = 0;
+    }
+    if(OS)
+      *OS << "\n";
+  }
+
+  if (!State.Sequence.Empty)
+    RecoverableErrorCallback(
+        createStringError(errc::illegal_byte_sequence,
+                    "last sequence in debug line table is not terminated!"));
+
+  // Sort all sequences so that address lookup will work faster.
+  if (!Sequences.empty()) {
+    llvm::sort(Sequences, Sequence::orderByLowPC);
+    // Note: actually, instruction address ranges of sequences should not
+    // overlap (in shared objects and executables). If they do, the address
+    // lookup would still work, though, but result would be ambiguous.
+    // We don't report warning in this case. For example,
+    // sometimes .so compiled from multiple object files contains a few
+    // rudimentary sequences for address ranges [0x0, 0xsomething).
+  }
+
+  return Error::success();
+}
+
+uint32_t
+DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
+                                        uint64_t Address) const {
+  if (!Seq.containsPC(Address))
+    return UnknownRowIndex;
+  // Search for instruction address in the rows describing the sequence.
+  // Rows are stored in a vector, so we may use arithmetical operations with
+  // iterators.
+  DWARFDebugLine::Row Row;
+  Row.Address = Address;
+  RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
+  RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
+  LineTable::RowIter RowPos = std::lower_bound(
+      FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress);
+  if (RowPos == LastRow) {
+    return Seq.LastRowIndex - 1;
+  }
+  uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
+  if (RowPos->Address > Address) {
+    if (RowPos == FirstRow)
+      return UnknownRowIndex;
+    else
+      Index--;
+  }
+  return Index;
+}
+
+uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const {
+  if (Sequences.empty())
+    return UnknownRowIndex;
+  // First, find an instruction sequence containing the given address.
+  DWARFDebugLine::Sequence Sequence;
+  Sequence.LowPC = Address;
+  SequenceIter FirstSeq = Sequences.begin();
+  SequenceIter LastSeq = Sequences.end();
+  SequenceIter SeqPos = std::lower_bound(
+      FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
+  DWARFDebugLine::Sequence FoundSeq;
+  if (SeqPos == LastSeq) {
+    FoundSeq = Sequences.back();
+  } else if (SeqPos->LowPC == Address) {
+    FoundSeq = *SeqPos;
+  } else {
+    if (SeqPos == FirstSeq)
+      return UnknownRowIndex;
+    FoundSeq = *(SeqPos - 1);
+  }
+  return findRowInSeq(FoundSeq, Address);
+}
+
+bool DWARFDebugLine::LineTable::lookupAddressRange(
+    uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const {
+  if (Sequences.empty())
+    return false;
+  uint64_t EndAddr = Address + Size;
+  // First, find an instruction sequence containing the given address.
+  DWARFDebugLine::Sequence Sequence;
+  Sequence.LowPC = Address;
+  SequenceIter FirstSeq = Sequences.begin();
+  SequenceIter LastSeq = Sequences.end();
+  SequenceIter SeqPos = std::lower_bound(
+      FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
+  if (SeqPos == LastSeq || SeqPos->LowPC != Address) {
+    if (SeqPos == FirstSeq)
+      return false;
+    SeqPos--;
+  }
+  if (!SeqPos->containsPC(Address))
+    return false;
+
+  SequenceIter StartPos = SeqPos;
+
+  // Add the rows from the first sequence to the vector, starting with the
+  // index we just calculated
+
+  while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
+    const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
+    // For the first sequence, we need to find which row in the sequence is the
+    // first in our range.
+    uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
+    if (SeqPos == StartPos)
+      FirstRowIndex = findRowInSeq(CurSeq, Address);
+
+    // Figure out the last row in the range.
+    uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1);
+    if (LastRowIndex == UnknownRowIndex)
+      LastRowIndex = CurSeq.LastRowIndex - 1;
+
+    assert(FirstRowIndex != UnknownRowIndex);
+    assert(LastRowIndex != UnknownRowIndex);
+
+    for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
+      Result.push_back(I);
+    }
+
+    ++SeqPos;
+  }
+
+  return true;
+}
+
+bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
+  return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
+}
+
+Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
+                                                                FileLineInfoKind Kind) const {
+  if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
+    return None;
+  const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
+  if (Optional<const char *> source = Entry.Source.getAsCString())
+    return StringRef(*source);
+  return None;
+}
+
+static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
+  // Debug info can contain paths from any OS, not necessarily
+  // an OS we're currently running on. Moreover different compilation units can
+  // be compiled on different operating systems and linked together later.
+  return sys::path::is_absolute(Path, sys::path::Style::posix) ||
+         sys::path::is_absolute(Path, sys::path::Style::windows);
+}
+
+bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
+                                                   const char *CompDir,
+                                                   FileLineInfoKind Kind,
+                                                   std::string &Result) const {
+  if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
+    return false;
+  const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
+  StringRef FileName = Entry.Name.getAsCString().getValue();
+  if (Kind != FileLineInfoKind::AbsoluteFilePath ||
+      isPathAbsoluteOnWindowsOrPosix(FileName)) {
+    Result = FileName;
+    return true;
+  }
+
+  SmallString<16> FilePath;
+  uint64_t IncludeDirIndex = Entry.DirIdx;
+  StringRef IncludeDir;
+  // Be defensive about the contents of Entry.
+  if (IncludeDirIndex > 0 &&
+      IncludeDirIndex <= Prologue.IncludeDirectories.size())
+    IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1]
+                     .getAsCString()
+                     .getValue();
+
+  // We may still need to append compilation directory of compile unit.
+  // We know that FileName is not absolute, the only way to have an
+  // absolute path at this point would be if IncludeDir is absolute.
+  if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
+      !isPathAbsoluteOnWindowsOrPosix(IncludeDir))
+    sys::path::append(FilePath, CompDir);
+
+  // sys::path::append skips empty strings.
+  sys::path::append(FilePath, IncludeDir, FileName);
+  Result = FilePath.str();
+  return true;
+}
+
+bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
+    uint64_t Address, const char *CompDir, FileLineInfoKind Kind,
+    DILineInfo &Result) const {
+  // Get the index of row we're looking for in the line table.
+  uint32_t RowIndex = lookupAddress(Address);
+  if (RowIndex == -1U)
+    return false;
+  // Take file number and line/column from the row.
+  const auto &Row = Rows[RowIndex];
+  if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
+    return false;
+  Result.Line = Row.Line;
+  Result.Column = Row.Column;
+  Result.Discriminator = Row.Discriminator;
+  Result.Source = getSourceByIndex(Row.File, Kind);
+  return true;
+}
+
+// We want to supply the Unit associated with a .debug_line[.dwo] table when
+// we dump it, if possible, but still dump the table even if there isn't a Unit.
+// Therefore, collect up handles on all the Units that point into the
+// line-table section.
+static DWARFDebugLine::SectionParser::LineToUnitMap
+buildLineToUnitMap(DWARFDebugLine::SectionParser::cu_range CUs,
+                   DWARFDebugLine::SectionParser::tu_range TUs) {
+  DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit;
+  for (const auto &CU : CUs)
+    if (auto CUDIE = CU->getUnitDIE())
+      if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))
+        LineToUnit.insert(std::make_pair(*StmtOffset, &*CU));
+  for (const auto &TU : TUs)
+    if (auto TUDIE = TU->getUnitDIE())
+      if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list)))
+        LineToUnit.insert(std::make_pair(*StmtOffset, &*TU));
+  return LineToUnit;
+}
+
+DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data,
+                                             const DWARFContext &C,
+                                             cu_range CUs, tu_range TUs)
+    : DebugLineData(Data), Context(C) {
+  LineToUnit = buildLineToUnitMap(CUs, TUs);
+  if (!DebugLineData.isValidOffset(Offset))
+    Done = true;
+}
+
+bool DWARFDebugLine::Prologue::totalLengthIsValid() const {
+  return TotalLength == 0xffffffff || TotalLength < 0xffffff00;
+}
+
+DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
+    function_ref<void(Error)> RecoverableErrorCallback,
+    function_ref<void(Error)> UnrecoverableErrorCallback, raw_ostream *OS) {
+  assert(DebugLineData.isValidOffset(Offset) &&
+         "parsing should have terminated");
+  DWARFUnit *U = prepareToParse(Offset);
+  uint32_t OldOffset = Offset;
+  LineTable LT;
+  if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,
+                           RecoverableErrorCallback, OS))
+    UnrecoverableErrorCallback(std::move(Err));
+  moveToNextTable(OldOffset, LT.Prologue);
+  return LT;
+}
+
+void DWARFDebugLine::SectionParser::skip(
+    function_ref<void(Error)> ErrorCallback) {
+  assert(DebugLineData.isValidOffset(Offset) &&
+         "parsing should have terminated");
+  DWARFUnit *U = prepareToParse(Offset);
+  uint32_t OldOffset = Offset;
+  LineTable LT;
+  if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U))
+    ErrorCallback(std::move(Err));
+  moveToNextTable(OldOffset, LT.Prologue);
+}
+
+DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint32_t Offset) {
+  DWARFUnit *U = nullptr;
+  auto It = LineToUnit.find(Offset);
+  if (It != LineToUnit.end())
+    U = It->second;
+  DebugLineData.setAddressSize(U ? U->getAddressByteSize() : 0);
+  return U;
+}
+
+void DWARFDebugLine::SectionParser::moveToNextTable(uint32_t OldOffset,
+                                                    const Prologue &P) {
+  // If the length field is not valid, we don't know where the next table is, so
+  // cannot continue to parse. Mark the parser as done, and leave the Offset
+  // value as it currently is. This will be the end of the bad length field.
+  if (!P.totalLengthIsValid()) {
+    Done = true;
+    return;
+  }
+
+  Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();
+  if (!DebugLineData.isValidOffset(Offset)) {
+    Done = true;
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
new file mode 100644
index 0000000..94df694
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -0,0 +1,279 @@
+//===- DWARFDebugLoc.cpp --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cinttypes>
+#include <cstdint>
+
+using namespace llvm;
+
+// When directly dumping the .debug_loc without a compile unit, we have to guess
+// at the DWARF version. This only affects DW_OP_call_ref, which is a rare
+// expression that LLVM doesn't produce. Guessing the wrong version means we
+// won't be able to pretty print expressions in DWARF2 binaries produced by
+// non-LLVM tools.
+static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
+                           bool IsLittleEndian, unsigned AddressSize,
+                           const MCRegisterInfo *MRI) {
+  DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
+                               IsLittleEndian, AddressSize);
+  DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI);
+}
+
+void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
+                                       unsigned AddressSize,
+                                       const MCRegisterInfo *MRI,
+                                       uint64_t BaseAddress,
+                                       unsigned Indent) const {
+  for (const Entry &E : Entries) {
+    OS << '\n';
+    OS.indent(Indent);
+    OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2,
+                 BaseAddress + E.Begin);
+    OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2,
+                 BaseAddress + E.End);
+    OS << ": ";
+
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+  }
+}
+
+DWARFDebugLoc::LocationList const *
+DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const {
+  auto It = std::lower_bound(
+      Locations.begin(), Locations.end(), Offset,
+      [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
+  if (It != Locations.end() && It->Offset == Offset)
+    return &(*It);
+  return nullptr;
+}
+
+void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+                         Optional<uint64_t> Offset) const {
+  auto DumpLocationList = [&](const LocationList &L) {
+    OS << format("0x%8.8x: ", L.Offset);
+    L.dump(OS, IsLittleEndian, AddressSize, MRI, 0, 12);
+    OS << "\n\n";
+  };
+
+  if (Offset) {
+    if (auto *L = getLocationListAtOffset(*Offset))
+      DumpLocationList(*L);
+    return;
+  }
+
+  for (const LocationList &L : Locations) {
+    DumpLocationList(L);
+  }
+}
+
+Optional<DWARFDebugLoc::LocationList>
+DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
+  LocationList LL;
+  LL.Offset = *Offset;
+
+  // 2.6.2 Location Lists
+  // A location list entry consists of:
+  while (true) {
+    Entry E;
+    if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
+      WithColor::error() << "location list overflows the debug_loc section.\n";
+      return None;
+    }
+
+    // 1. A beginning address offset. ...
+    E.Begin = Data.getRelocatedAddress(Offset);
+
+    // 2. An ending address offset. ...
+    E.End = Data.getRelocatedAddress(Offset);
+
+    // The end of any given location list is marked by an end of list entry,
+    // which consists of a 0 for the beginning address offset and a 0 for the
+    // ending address offset.
+    if (E.Begin == 0 && E.End == 0)
+      return LL;
+
+    if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
+      WithColor::error() << "location list overflows the debug_loc section.\n";
+      return None;
+    }
+
+    unsigned Bytes = Data.getU16(Offset);
+    if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
+      WithColor::error() << "location list overflows the debug_loc section.\n";
+      return None;
+    }
+    // A single location description describing the location of the object...
+    StringRef str = Data.getData().substr(*Offset, Bytes);
+    *Offset += Bytes;
+    E.Loc.reserve(str.size());
+    llvm::copy(str, std::back_inserter(E.Loc));
+    LL.Entries.push_back(std::move(E));
+  }
+}
+
+void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
+  IsLittleEndian = data.isLittleEndian();
+  AddressSize = data.getAddressSize();
+
+  uint32_t Offset = 0;
+  while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
+    if (auto LL = parseOneLocationList(data, &Offset))
+      Locations.push_back(std::move(*LL));
+    else
+      break;
+  }
+  if (data.isValidOffset(Offset))
+    WithColor::error() << "failed to consume entire .debug_loc section\n";
+}
+
+Optional<DWARFDebugLoclists::LocationList>
+DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset,
+                                         unsigned Version) {
+  LocationList LL;
+  LL.Offset = *Offset;
+
+  // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
+  while (auto Kind =
+             static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
+
+    Entry E;
+    E.Kind = Kind;
+    switch (Kind) {
+    case dwarf::DW_LLE_startx_length:
+      E.Value0 = Data.getULEB128(Offset);
+      // Pre-DWARF 5 has different interpretation of the length field. We have
+      // to support both pre- and standartized styles for the compatibility.
+      if (Version < 5)
+        E.Value1 = Data.getU32(Offset);
+      else
+        E.Value1 = Data.getULEB128(Offset);
+      break;
+    case dwarf::DW_LLE_start_length:
+      E.Value0 = Data.getAddress(Offset);
+      E.Value1 = Data.getULEB128(Offset);
+      break;
+    case dwarf::DW_LLE_offset_pair:
+      E.Value0 = Data.getULEB128(Offset);
+      E.Value1 = Data.getULEB128(Offset);
+      break;
+    case dwarf::DW_LLE_base_address:
+      E.Value0 = Data.getAddress(Offset);
+      break;
+    default:
+      WithColor::error() << "dumping support for LLE of kind " << (int)Kind
+                         << " not implemented\n";
+      return None;
+    }
+
+    if (Kind != dwarf::DW_LLE_base_address) {
+      unsigned Bytes =
+          Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset);
+      // A single location description describing the location of the object...
+      StringRef str = Data.getData().substr(*Offset, Bytes);
+      *Offset += Bytes;
+      E.Loc.resize(str.size());
+      llvm::copy(str, E.Loc.begin());
+    }
+
+    LL.Entries.push_back(std::move(E));
+  }
+  return LL;
+}
+
+void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) {
+  IsLittleEndian = data.isLittleEndian();
+  AddressSize = data.getAddressSize();
+
+  uint32_t Offset = 0;
+  while (data.isValidOffset(Offset)) {
+    if (auto LL = parseOneLocationList(data, &Offset, Version))
+      Locations.push_back(std::move(*LL));
+    else
+      return;
+  }
+}
+
+DWARFDebugLoclists::LocationList const *
+DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const {
+  auto It = std::lower_bound(
+      Locations.begin(), Locations.end(), Offset,
+      [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
+  if (It != Locations.end() && It->Offset == Offset)
+    return &(*It);
+  return nullptr;
+}
+
+void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
+                                            bool IsLittleEndian,
+                                            unsigned AddressSize,
+                                            const MCRegisterInfo *MRI,
+                                            unsigned Indent) const {
+  for (const Entry &E : Entries) {
+    switch (E.Kind) {
+    case dwarf::DW_LLE_startx_length:
+      OS << '\n';
+      OS.indent(Indent);
+      OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): ";
+      break;
+    case dwarf::DW_LLE_start_length:
+      OS << '\n';
+      OS.indent(Indent);
+      OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
+                   AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2,
+                   E.Value0 + E.Value1);
+      break;
+    case dwarf::DW_LLE_offset_pair:
+      OS << '\n';
+      OS.indent(Indent);
+      OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
+                   AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2,
+                   AddressSize * 2, BaseAddr + E.Value1);
+      break;
+    case dwarf::DW_LLE_base_address:
+      BaseAddr = E.Value0;
+      break;
+    default:
+      llvm_unreachable("unreachable locations list kind");
+    }
+
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+  }
+}
+
+void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr,
+                              const MCRegisterInfo *MRI,
+                              Optional<uint64_t> Offset) const {
+  auto DumpLocationList = [&](const LocationList &L) {
+    OS << format("0x%8.8x: ", L.Offset);
+    L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
+    OS << "\n\n";
+  };
+
+  if (Offset) {
+    if (auto *L = getLocationListAtOffset(*Offset))
+      DumpLocationList(*L);
+    return;
+  }
+
+  for (const LocationList &L : Locations) {
+    DumpLocationList(L);
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
new file mode 100644
index 0000000..6d789c3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
@@ -0,0 +1,101 @@
+//===- DWARFDebugMacro.cpp ------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace dwarf;
+
+void DWARFDebugMacro::dump(raw_ostream &OS) const {
+  unsigned IndLevel = 0;
+  for (const Entry &E : Macros) {
+    // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
+    // this check handles the case of corrupted ".debug_macinfo" section.
+    if (IndLevel > 0)
+      IndLevel -= (E.Type == DW_MACINFO_end_file);
+    // Print indentation.
+    for (unsigned I = 0; I < IndLevel; I++)
+      OS << "  ";
+    IndLevel += (E.Type == DW_MACINFO_start_file);
+
+    WithColor(OS, HighlightColor::Macro).get() << MacinfoString(E.Type);
+    switch (E.Type) {
+    default:
+      // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
+      break;
+    case DW_MACINFO_define:
+    case DW_MACINFO_undef:
+      OS << " - lineno: " << E.Line;
+      OS << " macro: " << E.MacroStr;
+      break;
+    case DW_MACINFO_start_file:
+      OS << " - lineno: " << E.Line;
+      OS << " filenum: " << E.File;
+      break;
+    case DW_MACINFO_end_file:
+      break;
+    case DW_MACINFO_vendor_ext:
+      OS << " - constant: " << E.ExtConstant;
+      OS << " string: " << E.ExtStr;
+      break;
+    }
+    OS << "\n";
+  }
+}
+
+void DWARFDebugMacro::parse(DataExtractor data) {
+  uint32_t Offset = 0;
+  while (data.isValidOffset(Offset)) {
+    // A macro list entry consists of:
+    Entry E;
+    // 1. Macinfo type
+    E.Type = data.getULEB128(&Offset);
+
+    if (E.Type == 0) {
+      // Reached end of ".debug_macinfo" section.
+      return;
+    }
+
+    switch (E.Type) {
+    default:
+      // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
+      // Push the corrupted entry to the list and halt parsing.
+      E.Type = DW_MACINFO_invalid;
+      Macros.push_back(E);
+      return;
+    case DW_MACINFO_define:
+    case DW_MACINFO_undef:
+      // 2. Source line
+      E.Line = data.getULEB128(&Offset);
+      // 3. Macro string
+      E.MacroStr = data.getCStr(&Offset);
+      break;
+    case DW_MACINFO_start_file:
+      // 2. Source line
+      E.Line = data.getULEB128(&Offset);
+      // 3. Source file id
+      E.File = data.getULEB128(&Offset);
+      break;
+    case DW_MACINFO_end_file:
+      break;
+    case DW_MACINFO_vendor_ext:
+      // 2. Vendor extension constant
+      E.ExtConstant = data.getULEB128(&Offset);
+      // 3. Vendor extension string
+      E.ExtStr = data.getCStr(&Offset);
+      break;
+    }
+
+    Macros.push_back(E);
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
new file mode 100644
index 0000000..abd1ad5
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp
@@ -0,0 +1,70 @@
+//===- DWARFDebugPubTable.cpp ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace dwarf;
+
+DWARFDebugPubTable::DWARFDebugPubTable(const DWARFObject &Obj,
+                                       const DWARFSection &Sec,
+                                       bool LittleEndian, bool GnuStyle)
+    : GnuStyle(GnuStyle) {
+  DWARFDataExtractor PubNames(Obj, Sec, LittleEndian, 0);
+  uint32_t Offset = 0;
+  while (PubNames.isValidOffset(Offset)) {
+    Sets.push_back({});
+    Set &SetData = Sets.back();
+
+    SetData.Length = PubNames.getU32(&Offset);
+    SetData.Version = PubNames.getU16(&Offset);
+    SetData.Offset = PubNames.getRelocatedValue(4, &Offset);
+    SetData.Size = PubNames.getU32(&Offset);
+
+    while (Offset < Sec.Data.size()) {
+      uint32_t DieRef = PubNames.getU32(&Offset);
+      if (DieRef == 0)
+        break;
+      uint8_t IndexEntryValue = GnuStyle ? PubNames.getU8(&Offset) : 0;
+      StringRef Name = PubNames.getCStrRef(&Offset);
+      SetData.Entries.push_back(
+          {DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name});
+    }
+  }
+}
+
+void DWARFDebugPubTable::dump(raw_ostream &OS) const {
+  for (const Set &S : Sets) {
+    OS << "length = " << format("0x%08x", S.Length);
+    OS << " version = " << format("0x%04x", S.Version);
+    OS << " unit_offset = " << format("0x%08x", S.Offset);
+    OS << " unit_size = " << format("0x%08x", S.Size) << '\n';
+    OS << (GnuStyle ? "Offset     Linkage  Kind     Name\n"
+                    : "Offset     Name\n");
+
+    for (const Entry &E : S.Entries) {
+      OS << format("0x%8.8x ", E.SecOffset);
+      if (GnuStyle) {
+        StringRef EntryLinkage =
+            GDBIndexEntryLinkageString(E.Descriptor.Linkage);
+        StringRef EntryKind = dwarf::GDBIndexEntryKindString(E.Descriptor.Kind);
+        OS << format("%-8s", EntryLinkage.data()) << ' '
+           << format("%-8s", EntryKind.data()) << ' ';
+      }
+      OS << '\"' << E.Name << "\"\n";
+    }
+  }
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
new file mode 100644
index 0000000..dfb9130
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
@@ -0,0 +1,96 @@
+//===- DWARFDebugRangesList.cpp -------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cinttypes>
+#include <cstdint>
+
+using namespace llvm;
+
+void DWARFDebugRangeList::clear() {
+  Offset = -1U;
+  AddressSize = 0;
+  Entries.clear();
+}
+
+Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data,
+                                   uint32_t *offset_ptr) {
+  clear();
+  if (!data.isValidOffset(*offset_ptr))
+    return createStringError(errc::invalid_argument,
+                       "invalid range list offset 0x%" PRIx32, *offset_ptr);
+
+  AddressSize = data.getAddressSize();
+  if (AddressSize != 4 && AddressSize != 8)
+    return createStringError(errc::invalid_argument,
+                       "invalid address size: %" PRIu8, AddressSize);
+  Offset = *offset_ptr;
+  while (true) {
+    RangeListEntry Entry;
+    Entry.SectionIndex = -1ULL;
+
+    uint32_t prev_offset = *offset_ptr;
+    Entry.StartAddress = data.getRelocatedAddress(offset_ptr);
+    Entry.EndAddress =
+        data.getRelocatedAddress(offset_ptr, &Entry.SectionIndex);
+
+    // Check that both values were extracted correctly.
+    if (*offset_ptr != prev_offset + 2 * AddressSize) {
+      clear();
+      return createStringError(errc::invalid_argument,
+                         "invalid range list entry at offset 0x%" PRIx32,
+                         prev_offset);
+    }
+    if (Entry.isEndOfListEntry())
+      break;
+    Entries.push_back(Entry);
+  }
+  return Error::success();
+}
+
+void DWARFDebugRangeList::dump(raw_ostream &OS) const {
+  for (const RangeListEntry &RLE : Entries) {
+    const char *format_str = (AddressSize == 4
+                              ? "%08x %08"  PRIx64 " %08"  PRIx64 "\n"
+                              : "%08x %016" PRIx64 " %016" PRIx64 "\n");
+    OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
+  }
+  OS << format("%08x <End of list>\n", Offset);
+}
+
+DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges(
+    llvm::Optional<SectionedAddress> BaseAddr) const {
+  DWARFAddressRangesVector Res;
+  for (const RangeListEntry &RLE : Entries) {
+    if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
+      BaseAddr = {RLE.EndAddress, RLE.SectionIndex};
+      continue;
+    }
+
+    DWARFAddressRange E;
+    E.LowPC = RLE.StartAddress;
+    E.HighPC = RLE.EndAddress;
+    E.SectionIndex = RLE.SectionIndex;
+    // Base address of a range list entry is determined by the closest preceding
+    // base address selection entry in the same range list. It defaults to the
+    // base address of the compilation unit if there is no such entry.
+    if (BaseAddr) {
+      E.LowPC += BaseAddr->Address;
+      E.HighPC += BaseAddr->Address;
+      if (E.SectionIndex == -1ULL)
+        E.SectionIndex = BaseAddr->SectionIndex;
+    }
+    Res.push_back(E);
+  }
+  return Res;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
new file mode 100644
index 0000000..60c6eb3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp
@@ -0,0 +1,248 @@
+//===- DWARFDebugRnglists.cpp ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End,
+                              uint32_t *OffsetPtr) {
+  Offset = *OffsetPtr;
+  SectionIndex = -1ULL;
+  // The caller should guarantee that we have at least 1 byte available, so
+  // we just assert instead of revalidate.
+  assert(*OffsetPtr < End &&
+         "not enough space to extract a rangelist encoding");
+  uint8_t Encoding = Data.getU8(OffsetPtr);
+
+  switch (Encoding) {
+  case dwarf::DW_RLE_end_of_list:
+    Value0 = Value1 = 0;
+    break;
+  // TODO: Support other encodings.
+  case dwarf::DW_RLE_base_addressx: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createStringError(
+          errc::invalid_argument,
+          "read past end of table when reading "
+          "DW_RLE_base_addressx encoding at offset 0x%" PRIx32,
+          PreviousOffset);
+    break;
+  }
+  case dwarf::DW_RLE_startx_endx:
+    return createStringError(errc::not_supported,
+                       "unsupported rnglists encoding DW_RLE_startx_endx at "
+                       "offset 0x%" PRIx32,
+                       *OffsetPtr - 1);
+  case dwarf::DW_RLE_startx_length: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getULEB128(OffsetPtr);
+    Value1 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createStringError(
+          errc::invalid_argument,
+          "read past end of table when reading "
+          "DW_RLE_startx_length encoding at offset 0x%" PRIx32,
+          PreviousOffset);
+    break;
+  }
+  case dwarf::DW_RLE_offset_pair: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getULEB128(OffsetPtr);
+    Value1 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createStringError(errc::invalid_argument,
+                         "read past end of table when reading "
+                         "DW_RLE_offset_pair encoding at offset 0x%" PRIx32,
+                         PreviousOffset);
+    break;
+  }
+  case dwarf::DW_RLE_base_address: {
+    if ((End - *OffsetPtr) < Data.getAddressSize())
+      return createStringError(errc::invalid_argument,
+                         "insufficient space remaining in table for "
+                         "DW_RLE_base_address encoding at offset 0x%" PRIx32,
+                         *OffsetPtr - 1);
+    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
+    break;
+  }
+  case dwarf::DW_RLE_start_end: {
+    if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2))
+      return createStringError(errc::invalid_argument,
+                         "insufficient space remaining in table for "
+                         "DW_RLE_start_end encoding "
+                         "at offset 0x%" PRIx32,
+                         *OffsetPtr - 1);
+    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
+    Value1 = Data.getRelocatedAddress(OffsetPtr);
+    break;
+  }
+  case dwarf::DW_RLE_start_length: {
+    uint32_t PreviousOffset = *OffsetPtr - 1;
+    Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex);
+    Value1 = Data.getULEB128(OffsetPtr);
+    if (End < *OffsetPtr)
+      return createStringError(errc::invalid_argument,
+                         "read past end of table when reading "
+                         "DW_RLE_start_length encoding at offset 0x%" PRIx32,
+                         PreviousOffset);
+    break;
+  }
+  default:
+    return createStringError(errc::not_supported,
+                       "unknown rnglists encoding 0x%" PRIx32
+                       " at offset 0x%" PRIx32,
+                       uint32_t(Encoding), *OffsetPtr - 1);
+  }
+
+  EntryKind = Encoding;
+  return Error::success();
+}
+
+DWARFAddressRangesVector
+DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr,
+                                     DWARFUnit &U) const {
+  DWARFAddressRangesVector Res;
+  for (const RangeListEntry &RLE : Entries) {
+    if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
+      break;
+    if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
+      BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0);
+      if (!BaseAddr)
+        BaseAddr = {RLE.Value0, -1ULL};
+      continue;
+    }
+    if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
+      BaseAddr = {RLE.Value0, RLE.SectionIndex};
+      continue;
+    }
+
+    DWARFAddressRange E;
+    E.SectionIndex = RLE.SectionIndex;
+    if (BaseAddr && E.SectionIndex == -1ULL)
+      E.SectionIndex = BaseAddr->SectionIndex;
+
+    switch (RLE.EntryKind) {
+    case dwarf::DW_RLE_offset_pair:
+      E.LowPC = RLE.Value0;
+      E.HighPC = RLE.Value1;
+      if (BaseAddr) {
+        E.LowPC += BaseAddr->Address;
+        E.HighPC += BaseAddr->Address;
+      }
+      break;
+    case dwarf::DW_RLE_start_end:
+      E.LowPC = RLE.Value0;
+      E.HighPC = RLE.Value1;
+      break;
+    case dwarf::DW_RLE_start_length:
+      E.LowPC = RLE.Value0;
+      E.HighPC = E.LowPC + RLE.Value1;
+      break;
+    case dwarf::DW_RLE_startx_length: {
+      auto Start = U.getAddrOffsetSectionItem(RLE.Value0);
+      if (!Start)
+        Start = {0, -1ULL};
+      E.SectionIndex = Start->SectionIndex;
+      E.LowPC = Start->Address;
+      E.HighPC = E.LowPC + RLE.Value1;
+      break;
+    }
+    default:
+      // Unsupported encodings should have been reported during extraction,
+      // so we should not run into any here.
+      llvm_unreachable("Unsupported range list encoding");
+    }
+    Res.push_back(E);
+  }
+  return Res;
+}
+
+void RangeListEntry::dump(
+    raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
+    uint64_t &CurrentBase, DIDumpOptions DumpOpts,
+    llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
+        LookupPooledAddress) const {
+  auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
+                          uint8_t AddrSize, DIDumpOptions DumpOpts) {
+    if (DumpOpts.Verbose) {
+      DumpOpts.DisplayRawContents = true;
+      DWARFAddressRange(Entry.Value0, Entry.Value1)
+          .dump(OS, AddrSize, DumpOpts);
+      OS << " => ";
+    }
+  };
+
+  if (DumpOpts.Verbose) {
+    // Print the section offset in verbose mode.
+    OS << format("0x%8.8" PRIx32 ":", Offset);
+    auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
+    // Unsupported encodings should have been reported during parsing.
+    assert(!EncodingString.empty() && "Unknown range entry encoding");
+    OS << format(" [%s%*c", EncodingString.data(),
+                 MaxEncodingStringLength - EncodingString.size() + 1, ']');
+    if (EntryKind != dwarf::DW_RLE_end_of_list)
+      OS << ": ";
+  }
+
+  switch (EntryKind) {
+  case dwarf::DW_RLE_end_of_list:
+    OS << (DumpOpts.Verbose ? "" : "<End of list>");
+    break;
+    //  case dwarf::DW_RLE_base_addressx:
+  case dwarf::DW_RLE_base_addressx: {
+    if (auto SA = LookupPooledAddress(Value0))
+      CurrentBase = SA->Address;
+    else
+      CurrentBase = Value0;
+    if (!DumpOpts.Verbose)
+      return;
+    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
+    break;
+  }
+  case dwarf::DW_RLE_base_address:
+    // In non-verbose mode we do not print anything for this entry.
+    CurrentBase = Value0;
+    if (!DumpOpts.Verbose)
+      return;
+    OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0);
+    break;
+  case dwarf::DW_RLE_start_length:
+    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
+    DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
+    break;
+  case dwarf::DW_RLE_offset_pair:
+    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
+    DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
+        .dump(OS, AddrSize, DumpOpts);
+    break;
+  case dwarf::DW_RLE_start_end:
+    DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
+    break;
+  case dwarf::DW_RLE_startx_length: {
+    PrintRawEntry(OS, *this, AddrSize, DumpOpts);
+    uint64_t Start = 0;
+    if (auto SA = LookupPooledAddress(Value0))
+      Start = SA->Address;
+    DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
+    break;
+  } break;
+  default:
+    llvm_unreachable("Unsupported range list encoding");
+  }
+  OS << "\n";
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
new file mode 100644
index 0000000..81ef0c8
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -0,0 +1,712 @@
+//===- DWARFDie.cpp -------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <string>
+#include <utility>
+
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
+  OS << " (";
+  do {
+    uint64_t Shift = countTrailingZeros(Val);
+    assert(Shift < 64 && "undefined behavior");
+    uint64_t Bit = 1ULL << Shift;
+    auto PropName = ApplePropertyString(Bit);
+    if (!PropName.empty())
+      OS << PropName;
+    else
+      OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
+    if (!(Val ^= Bit))
+      break;
+    OS << ", ";
+  } while (true);
+  OS << ")";
+}
+
+static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS,
+                       const DWARFAddressRangesVector &Ranges,
+                       unsigned AddressSize, unsigned Indent,
+                       const DIDumpOptions &DumpOpts) {
+  if (!DumpOpts.ShowAddresses)
+    return;
+
+  ArrayRef<SectionName> SectionNames;
+  if (DumpOpts.Verbose)
+    SectionNames = Obj.getSectionNames();
+
+  for (const DWARFAddressRange &R : Ranges) {
+    OS << '\n';
+    OS.indent(Indent);
+    R.dump(OS, AddressSize);
+
+    DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, R.SectionIndex);
+  }
+}
+
+static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
+                         DWARFUnit *U, unsigned Indent,
+                         DIDumpOptions DumpOpts) {
+  DWARFContext &Ctx = U->getContext();
+  const DWARFObject &Obj = Ctx.getDWARFObj();
+  const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
+  if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
+      FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) {
+    ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
+    DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
+                       Ctx.isLittleEndian(), 0);
+    DWARFExpression(Data, U->getVersion(), U->getAddressByteSize())
+        .print(OS, MRI);
+    return;
+  }
+
+  FormValue.dump(OS, DumpOpts);
+  if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
+    uint32_t Offset = *FormValue.getAsSectionOffset();
+    if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
+      DWARFDebugLoc DebugLoc;
+      DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
+                              Obj.getAddressSize());
+      auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
+      if (LL) {
+        uint64_t BaseAddr = 0;
+        if (Optional<SectionedAddress> BA = U->getBaseAddress())
+          BaseAddr = BA->Address;
+        LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr,
+                 Indent);
+      } else
+        OS << "error extracting location list.";
+      return;
+    }
+
+    bool UseLocLists = !U->isDWOUnit();
+    StringRef LoclistsSectionData =
+        UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData();
+
+    if (!LoclistsSectionData.empty()) {
+      DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
+                         Obj.getAddressSize());
+
+      // Old-style location list were used in DWARF v4 (.debug_loc.dwo section).
+      // Modern locations list (.debug_loclists) are used starting from v5.
+      // Ideally we should take the version from the .debug_loclists section
+      // header, but using CU's version for simplicity.
+      auto LL = DWARFDebugLoclists::parseOneLocationList(
+          Data, &Offset, UseLocLists ? U->getVersion() : 4);
+
+      uint64_t BaseAddr = 0;
+      if (Optional<SectionedAddress> BA = U->getBaseAddress())
+        BaseAddr = BA->Address;
+
+      if (LL)
+        LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
+                 Indent);
+      else
+        OS << "error extracting location list.";
+    }
+  }
+}
+
+/// Dump the name encoded in the type tag.
+static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) {
+  StringRef TagStr = TagString(T);
+  if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type"))
+    return;
+  OS << TagStr.substr(7, TagStr.size() - 12) << " ";
+}
+
+static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) {
+  Optional<uint64_t> Bound;
+  for (const DWARFDie &C : D.children())
+    if (C.getTag() == DW_TAG_subrange_type) {
+      Optional<uint64_t> LB;
+      Optional<uint64_t> Count;
+      Optional<uint64_t> UB;
+      Optional<unsigned> DefaultLB;
+      if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound))
+        LB = L->getAsUnsignedConstant();
+      if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count))
+        Count = CountV->getAsUnsignedConstant();
+      if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound))
+        UB = UpperV->getAsUnsignedConstant();
+      if (Optional<DWARFFormValue> LV =
+              D.getDwarfUnit()->getUnitDIE().find(DW_AT_language))
+        if (Optional<uint64_t> LC = LV->getAsUnsignedConstant())
+          if ((DefaultLB =
+                   LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC))))
+            if (LB && *LB == *DefaultLB)
+              LB = None;
+      if (!LB && !Count && !UB)
+        OS << "[]";
+      else if (!LB && (Count || UB) && DefaultLB)
+        OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']';
+      else {
+        OS << "[[";
+        if (LB)
+          OS << *LB;
+        else
+          OS << '?';
+        OS << ", ";
+        if (Count)
+          if (LB)
+            OS << *LB + *Count;
+          else
+            OS << "? + " << *Count;
+        else if (UB)
+          OS << *UB + 1;
+        else
+          OS << '?';
+        OS << ")]";
+      }
+    }
+}
+
+/// Recursively dump the DIE type name when applicable.
+static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) {
+  if (!D.isValid())
+    return;
+
+  if (const char *Name = D.getName(DINameKind::LinkageName)) {
+    OS << Name;
+    return;
+  }
+
+  // FIXME: We should have pretty printers per language. Currently we print
+  // everything as if it was C++ and fall back to the TAG type name.
+  const dwarf::Tag T = D.getTag();
+  switch (T) {
+  case DW_TAG_array_type:
+  case DW_TAG_pointer_type:
+  case DW_TAG_ptr_to_member_type:
+  case DW_TAG_reference_type:
+  case DW_TAG_rvalue_reference_type:
+  case DW_TAG_subroutine_type:
+    break;
+  default:
+    dumpTypeTagName(OS, T);
+  }
+
+  // Follow the DW_AT_type if possible.
+  DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type);
+  dumpTypeName(OS, TypeDie);
+
+  switch (T) {
+  case DW_TAG_subroutine_type: {
+    if (!TypeDie)
+      OS << "void";
+    OS << '(';
+    bool First = true;
+    for (const DWARFDie &C : D.children()) {
+      if (C.getTag() == DW_TAG_formal_parameter) {
+        if (!First)
+          OS << ", ";
+        First = false;
+        dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type));
+      }
+    }
+    OS << ')';
+    break;
+  }
+  case DW_TAG_array_type: {
+    dumpArrayType(OS, D);
+    break;
+  }
+  case DW_TAG_pointer_type:
+    OS << '*';
+    break;
+  case DW_TAG_ptr_to_member_type:
+    if (DWARFDie Cont =
+            D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) {
+      dumpTypeName(OS << ' ', Cont);
+      OS << "::";
+    }
+    OS << '*';
+    break;
+  case DW_TAG_reference_type:
+    OS << '&';
+    break;
+  case DW_TAG_rvalue_reference_type:
+    OS << "&&";
+    break;
+  default:
+    break;
+  }
+}
+
+static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
+                          uint32_t *OffsetPtr, dwarf::Attribute Attr,
+                          dwarf::Form Form, unsigned Indent,
+                          DIDumpOptions DumpOpts) {
+  if (!Die.isValid())
+    return;
+  const char BaseIndent[] = "            ";
+  OS << BaseIndent;
+  OS.indent(Indent + 2);
+  WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);
+
+  if (DumpOpts.Verbose || DumpOpts.ShowForm)
+    OS << formatv(" [{0}]", Form);
+
+  DWARFUnit *U = Die.getDwarfUnit();
+  DWARFFormValue formValue(Form);
+
+  if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,
+                              U->getFormParams(), U))
+    return;
+
+  OS << "\t(";
+
+  StringRef Name;
+  std::string File;
+  auto Color = HighlightColor::Enumerator;
+  if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
+    Color = HighlightColor::String;
+    if (const auto *LT = U->getContext().getLineTableForUnit(U))
+      if (LT->getFileNameByIndex(
+              formValue.getAsUnsignedConstant().getValue(),
+              U->getCompilationDir(),
+              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
+        File = '"' + File + '"';
+        Name = File;
+      }
+  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
+    Name = AttributeValueString(Attr, *Val);
+
+  if (!Name.empty())
+    WithColor(OS, Color) << Name;
+  else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
+    OS << *formValue.getAsUnsignedConstant();
+  else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose &&
+           formValue.getAsUnsignedConstant()) {
+    if (DumpOpts.ShowAddresses) {
+      // Print the actual address rather than the offset.
+      uint64_t LowPC, HighPC, Index;
+      if (Die.getLowAndHighPC(LowPC, HighPC, Index))
+        OS << format("0x%016" PRIx64, HighPC);
+      else
+        formValue.dump(OS, DumpOpts);
+    }
+  } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
+             Attr == DW_AT_data_member_location ||
+             Attr == DW_AT_GNU_call_site_value)
+    dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
+  else
+    formValue.dump(OS, DumpOpts);
+
+  std::string Space = DumpOpts.ShowAddresses ? " " : "";
+
+  // We have dumped the attribute raw value. For some attributes
+  // having both the raw value and the pretty-printed value is
+  // interesting. These attributes are handled below.
+  if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
+    if (const char *Name =
+            Die.getAttributeValueAsReferencedDie(formValue).getName(
+                DINameKind::LinkageName))
+      OS << Space << "\"" << Name << '\"';
+  } else if (Attr == DW_AT_type) {
+    OS << Space << "\"";
+    dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(formValue));
+    OS << '"';
+  } else if (Attr == DW_AT_APPLE_property_attribute) {
+    if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
+      dumpApplePropertyAttribute(OS, *OptVal);
+  } else if (Attr == DW_AT_ranges) {
+    const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj();
+    // For DW_FORM_rnglistx we need to dump the offset separately, since
+    // we have only dumped the index so far.
+    if (formValue.getForm() == DW_FORM_rnglistx)
+      if (auto RangeListOffset =
+              U->getRnglistOffset(*formValue.getAsSectionOffset())) {
+        DWARFFormValue FV(dwarf::DW_FORM_sec_offset);
+        FV.setUValue(*RangeListOffset);
+        FV.dump(OS, DumpOpts);
+      }
+    if (auto RangesOrError = Die.getAddressRanges())
+      dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(),
+                 sizeof(BaseIndent) + Indent + 4, DumpOpts);
+    else
+      WithColor::error() << "decoding address ranges: "
+                         << toString(RangesOrError.takeError()) << '\n';
+  }
+
+  OS << ")\n";
+}
+
+bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; }
+
+bool DWARFDie::isSubroutineDIE() const {
+  auto Tag = getTag();
+  return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
+}
+
+Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const {
+  if (!isValid())
+    return None;
+  auto AbbrevDecl = getAbbreviationDeclarationPtr();
+  if (AbbrevDecl)
+    return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
+  return None;
+}
+
+Optional<DWARFFormValue>
+DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const {
+  if (!isValid())
+    return None;
+  auto AbbrevDecl = getAbbreviationDeclarationPtr();
+  if (AbbrevDecl) {
+    for (auto Attr : Attrs) {
+      if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U))
+        return Value;
+    }
+  }
+  return None;
+}
+
+Optional<DWARFFormValue>
+DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const {
+  std::vector<DWARFDie> Worklist;
+  Worklist.push_back(*this);
+
+  // Keep track if DIEs already seen to prevent infinite recursion.
+  // Empirically we rarely see a depth of more than 3 when dealing with valid
+  // DWARF. This corresponds to following the DW_AT_abstract_origin and
+  // DW_AT_specification just once.
+  SmallSet<DWARFDie, 3> Seen;
+
+  while (!Worklist.empty()) {
+    DWARFDie Die = Worklist.back();
+    Worklist.pop_back();
+
+    if (!Die.isValid())
+      continue;
+
+    if (Seen.count(Die))
+      continue;
+
+    Seen.insert(Die);
+
+    if (auto Value = Die.find(Attrs))
+      return Value;
+
+    if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+      Worklist.push_back(D);
+
+    if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification))
+      Worklist.push_back(D);
+  }
+
+  return None;
+}
+
+DWARFDie
+DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
+  if (Optional<DWARFFormValue> F = find(Attr))
+    return getAttributeValueAsReferencedDie(*F);
+  return DWARFDie();
+}
+
+DWARFDie
+DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
+  if (auto SpecRef = toReference(V)) {
+    if (auto SpecUnit = U->getUnitVector().getUnitForOffset(*SpecRef))
+      return SpecUnit->getDIEForOffset(*SpecRef);
+  }
+  return DWARFDie();
+}
+
+Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {
+  return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base}));
+}
+
+Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
+  if (auto FormValue = find(DW_AT_high_pc)) {
+    if (auto Address = FormValue->getAsAddress()) {
+      // High PC is an address.
+      return Address;
+    }
+    if (auto Offset = FormValue->getAsUnsignedConstant()) {
+      // High PC is an offset from LowPC.
+      return LowPC + *Offset;
+    }
+  }
+  return None;
+}
+
+bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
+                               uint64_t &SectionIndex) const {
+  auto F = find(DW_AT_low_pc);
+  auto LowPcAddr = toSectionedAddress(F);
+  if (!LowPcAddr)
+    return false;
+  if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) {
+    LowPC = LowPcAddr->Address;
+    HighPC = *HighPcAddr;
+    SectionIndex = LowPcAddr->SectionIndex;
+    return true;
+  }
+  return false;
+}
+
+Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const {
+  if (isNULL())
+    return DWARFAddressRangesVector();
+  // Single range specified by low/high PC.
+  uint64_t LowPC, HighPC, Index;
+  if (getLowAndHighPC(LowPC, HighPC, Index))
+    return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
+
+  Optional<DWARFFormValue> Value = find(DW_AT_ranges);
+  if (Value) {
+    if (Value->getForm() == DW_FORM_rnglistx)
+      return U->findRnglistFromIndex(*Value->getAsSectionOffset());
+    return U->findRnglistFromOffset(*Value->getAsSectionOffset());
+  }
+  return DWARFAddressRangesVector();
+}
+
+void DWARFDie::collectChildrenAddressRanges(
+    DWARFAddressRangesVector &Ranges) const {
+  if (isNULL())
+    return;
+  if (isSubprogramDIE()) {
+    if (auto DIERangesOrError = getAddressRanges())
+      Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(),
+                    DIERangesOrError.get().end());
+    else
+      llvm::consumeError(DIERangesOrError.takeError());
+  }
+
+  for (auto Child : children())
+    Child.collectChildrenAddressRanges(Ranges);
+}
+
+bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
+  auto RangesOrError = getAddressRanges();
+  if (!RangesOrError) {
+    llvm::consumeError(RangesOrError.takeError());
+    return false;
+  }
+
+  for (const auto &R : RangesOrError.get())
+    if (R.LowPC <= Address && Address < R.HighPC)
+      return true;
+  return false;
+}
+
+const char *DWARFDie::getSubroutineName(DINameKind Kind) const {
+  if (!isSubroutineDIE())
+    return nullptr;
+  return getName(Kind);
+}
+
+const char *DWARFDie::getName(DINameKind Kind) const {
+  if (!isValid() || Kind == DINameKind::None)
+    return nullptr;
+  // Try to get mangled name only if it was asked for.
+  if (Kind == DINameKind::LinkageName) {
+    if (auto Name = dwarf::toString(
+            findRecursively({DW_AT_MIPS_linkage_name, DW_AT_linkage_name}),
+            nullptr))
+      return Name;
+  }
+  if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
+    return Name;
+  return nullptr;
+}
+
+uint64_t DWARFDie::getDeclLine() const {
+  return toUnsigned(findRecursively(DW_AT_decl_line), 0);
+}
+
+void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
+                              uint32_t &CallColumn,
+                              uint32_t &CallDiscriminator) const {
+  CallFile = toUnsigned(find(DW_AT_call_file), 0);
+  CallLine = toUnsigned(find(DW_AT_call_line), 0);
+  CallColumn = toUnsigned(find(DW_AT_call_column), 0);
+  CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0);
+}
+
+/// Helper to dump a DIE with all of its parents, but no siblings.
+static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,
+                                DIDumpOptions DumpOpts) {
+  if (!Die)
+    return Indent;
+  Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts);
+  Die.dump(OS, Indent, DumpOpts);
+  return Indent + 2;
+}
+
+void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
+                    DIDumpOptions DumpOpts) const {
+  if (!isValid())
+    return;
+  DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
+  const uint32_t Offset = getOffset();
+  uint32_t offset = Offset;
+  if (DumpOpts.ShowParents) {
+    DIDumpOptions ParentDumpOpts = DumpOpts;
+    ParentDumpOpts.ShowParents = false;
+    ParentDumpOpts.ShowChildren = false;
+    Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts);
+  }
+
+  if (debug_info_data.isValidOffset(offset)) {
+    uint32_t abbrCode = debug_info_data.getULEB128(&offset);
+    if (DumpOpts.ShowAddresses)
+      WithColor(OS, HighlightColor::Address).get()
+          << format("\n0x%8.8x: ", Offset);
+
+    if (abbrCode) {
+      auto AbbrevDecl = getAbbreviationDeclarationPtr();
+      if (AbbrevDecl) {
+        WithColor(OS, HighlightColor::Tag).get().indent(Indent)
+            << formatv("{0}", getTag());
+        if (DumpOpts.Verbose)
+          OS << format(" [%u] %c", abbrCode,
+                       AbbrevDecl->hasChildren() ? '*' : ' ');
+        OS << '\n';
+
+        // Dump all data in the DIE for the attributes.
+        for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+          if (AttrSpec.Form == DW_FORM_implicit_const) {
+            // We are dumping .debug_info section ,
+            // implicit_const attribute values are not really stored here,
+            // but in .debug_abbrev section. So we just skip such attrs.
+            continue;
+          }
+          dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
+                        Indent, DumpOpts);
+        }
+
+        DWARFDie child = getFirstChild();
+        if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) {
+          DumpOpts.RecurseDepth--;
+          DIDumpOptions ChildDumpOpts = DumpOpts;
+          ChildDumpOpts.ShowParents = false;
+          while (child) {
+            child.dump(OS, Indent + 2, ChildDumpOpts);
+            child = child.getSibling();
+          }
+        }
+      } else {
+        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
+           << abbrCode << '\n';
+      }
+    } else {
+      OS.indent(Indent) << "NULL\n";
+    }
+  }
+}
+
+LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); }
+
+DWARFDie DWARFDie::getParent() const {
+  if (isValid())
+    return U->getParent(Die);
+  return DWARFDie();
+}
+
+DWARFDie DWARFDie::getSibling() const {
+  if (isValid())
+    return U->getSibling(Die);
+  return DWARFDie();
+}
+
+DWARFDie DWARFDie::getPreviousSibling() const {
+  if (isValid())
+    return U->getPreviousSibling(Die);
+  return DWARFDie();
+}
+
+DWARFDie DWARFDie::getFirstChild() const {
+  if (isValid())
+    return U->getFirstChild(Die);
+  return DWARFDie();
+}
+
+DWARFDie DWARFDie::getLastChild() const {
+  if (isValid())
+    return U->getLastChild(Die);
+  return DWARFDie();
+}
+
+iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const {
+  return make_range(attribute_iterator(*this, false),
+                    attribute_iterator(*this, true));
+}
+
+DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End)
+    : Die(D), AttrValue(0), Index(0) {
+  auto AbbrDecl = Die.getAbbreviationDeclarationPtr();
+  assert(AbbrDecl && "Must have abbreviation declaration");
+  if (End) {
+    // This is the end iterator so we set the index to the attribute count.
+    Index = AbbrDecl->getNumAttributes();
+  } else {
+    // This is the begin iterator so we extract the value for this->Index.
+    AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize();
+    updateForIndex(*AbbrDecl, 0);
+  }
+}
+
+void DWARFDie::attribute_iterator::updateForIndex(
+    const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) {
+  Index = I;
+  // AbbrDecl must be valid before calling this function.
+  auto NumAttrs = AbbrDecl.getNumAttributes();
+  if (Index < NumAttrs) {
+    AttrValue.Attr = AbbrDecl.getAttrByIndex(Index);
+    // Add the previous byte size of any previous attribute value.
+    AttrValue.Offset += AttrValue.ByteSize;
+    AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index));
+    uint32_t ParseOffset = AttrValue.Offset;
+    auto U = Die.getDwarfUnit();
+    assert(U && "Die must have valid DWARF unit");
+    bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(),
+                                          &ParseOffset, U->getFormParams(), U);
+    (void)b;
+    assert(b && "extractValue cannot fail on fully parsed DWARF");
+    AttrValue.ByteSize = ParseOffset - AttrValue.Offset;
+  } else {
+    assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only");
+    AttrValue.clear();
+  }
+}
+
+DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() {
+  if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr())
+    updateForIndex(*AbbrDecl, Index + 1);
+  return *this;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
new file mode 100644
index 0000000..a9d2006
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -0,0 +1,278 @@
+//===-- DWARFExpression.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Format.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+namespace llvm {
+
+typedef std::vector<DWARFExpression::Operation::Description> DescVector;
+
+static DescVector getDescriptions() {
+  DescVector Descriptions;
+  typedef DWARFExpression::Operation Op;
+  typedef Op::Description Desc;
+
+  Descriptions.resize(0xff);
+  Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);
+  Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);
+  Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);
+  Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);
+  Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);
+  Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);
+  Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);
+  Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_over] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_and] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_div] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_not] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_or] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_le] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);
+  Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);
+  Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);
+  Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);
+  Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);
+  Descriptions[DW_OP_implicit_value] =
+      Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
+  Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_WASM_location] =
+      Desc(Op::Dwarf4, Op::SizeLEB, Op::SignedSizeLEB);
+  Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
+  Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
+  Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
+  return Descriptions;
+}
+
+static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) {
+  // FIXME: Make this constexpr once all compilers are smart enough to do it.
+  static DescVector Descriptions = getDescriptions();
+  // Handle possible corrupted or unsupported operation.
+  if (OpCode >= Descriptions.size())
+    return {};
+  return Descriptions[OpCode];
+}
+
+static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
+  return (Version == 2) ? AddrSize : 4;
+}
+
+bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version,
+                                         uint8_t AddressSize, uint32_t Offset) {
+  Opcode = Data.getU8(&Offset);
+
+  Desc = getOpDesc(Opcode);
+  if (Desc.Version == Operation::DwarfNA) {
+    EndOffset = Offset;
+    return false;
+  }
+
+  for (unsigned Operand = 0; Operand < 2; ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+    unsigned Signed = Size & Operation::SignBit;
+
+    if (Size == Operation::SizeNA)
+      break;
+
+    switch (Size & ~Operation::SignBit) {
+    case Operation::Size1:
+      Operands[Operand] = Data.getU8(&Offset);
+      if (Signed)
+        Operands[Operand] = (int8_t)Operands[Operand];
+      break;
+    case Operation::Size2:
+      Operands[Operand] = Data.getU16(&Offset);
+      if (Signed)
+        Operands[Operand] = (int16_t)Operands[Operand];
+      break;
+    case Operation::Size4:
+      Operands[Operand] = Data.getU32(&Offset);
+      if (Signed)
+        Operands[Operand] = (int32_t)Operands[Operand];
+      break;
+    case Operation::Size8:
+      Operands[Operand] = Data.getU64(&Offset);
+      break;
+    case Operation::SizeAddr:
+      if (AddressSize == 8) {
+        Operands[Operand] = Data.getU64(&Offset);
+      } else {
+        assert(AddressSize == 4);
+        Operands[Operand] = Data.getU32(&Offset);
+      }
+      break;
+    case Operation::SizeRefAddr:
+      if (getRefAddrSize(AddressSize, Version) == 8) {
+        Operands[Operand] = Data.getU64(&Offset);
+      } else {
+        assert(getRefAddrSize(AddressSize, Version) == 4);
+        Operands[Operand] = Data.getU32(&Offset);
+      }
+      break;
+    case Operation::SizeLEB:
+      if (Signed)
+        Operands[Operand] = Data.getSLEB128(&Offset);
+      else
+        Operands[Operand] = Data.getULEB128(&Offset);
+      break;
+    case Operation::SizeBlock:
+      // We need a size, so this cannot be the first operand
+      if (Operand == 0)
+        return false;
+      // Store the offset of the block as the value.
+      Operands[Operand] = Offset;
+      Offset += Operands[Operand - 1];
+      break;
+    default:
+      llvm_unreachable("Unknown DWARFExpression Op size");
+    }
+  }
+
+  EndOffset = Offset;
+  return true;
+}
+
+static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode,
+                                  uint64_t Operands[2],
+                                  const MCRegisterInfo *MRI, bool isEH) {
+  if (!MRI)
+    return false;
+
+  uint64_t DwarfRegNum;
+  unsigned OpNum = 0;
+
+  if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx)
+    DwarfRegNum = Operands[OpNum++];
+  else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)
+    DwarfRegNum = Opcode - DW_OP_breg0;
+  else
+    DwarfRegNum = Opcode - DW_OP_reg0;
+
+  int LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH);
+  if (LLVMRegNum >= 0) {
+    if (const char *RegName = MRI->getName(LLVMRegNum)) {
+      if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
+          Opcode == DW_OP_bregx)
+        OS << format(" %s%+" PRId64, RegName, Operands[OpNum]);
+      else
+        OS << ' ' << RegName;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool DWARFExpression::Operation::print(raw_ostream &OS,
+                                       const DWARFExpression *Expr,
+                                       const MCRegisterInfo *RegInfo,
+                                       bool isEH) {
+  if (Error) {
+    OS << "<decoding error>";
+    return false;
+  }
+
+  StringRef Name = OperationEncodingString(Opcode);
+  assert(!Name.empty() && "DW_OP has no name!");
+  OS << Name;
+
+  if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
+      (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||
+      Opcode == DW_OP_bregx || Opcode == DW_OP_regx)
+    if (prettyPrintRegisterOp(OS, Opcode, Operands, RegInfo, isEH))
+      return true;
+
+  for (unsigned Operand = 0; Operand < 2; ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+    unsigned Signed = Size & Operation::SignBit;
+
+    if (Size == Operation::SizeNA)
+      break;
+
+    if (Size == Operation::SizeBlock) {
+      uint32_t Offset = Operands[Operand];
+      for (unsigned i = 0; i < Operands[Operand - 1]; ++i)
+        OS << format(" 0x%02x", Expr->Data.getU8(&Offset));
+    } else {
+      if (Signed)
+        OS << format(" %+" PRId64, (int64_t)Operands[Operand]);
+      else
+        OS << format(" 0x%" PRIx64, Operands[Operand]);
+    }
+  }
+  return true;
+}
+
+void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+                            bool IsEH) const {
+  for (auto &Op : *this) {
+    if (!Op.print(OS, this, RegInfo, IsEH)) {
+      uint32_t FailOffset = Op.getEndOffset();
+      while (FailOffset < Data.getData().size())
+        OS << format(" %02x", Data.getU8(&FailOffset));
+      return;
+    }
+    if (Op.getEndOffset() < Data.getData().size())
+      OS << ", ";
+  }
+}
+
+} // namespace llvm
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
new file mode 100644
index 0000000..7719fea
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -0,0 +1,679 @@
+//===- DWARFFormValue.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cinttypes>
+#include <cstdint>
+#include <limits>
+
+using namespace llvm;
+using namespace dwarf;
+
+static const DWARFFormValue::FormClass DWARF5FormClasses[] = {
+    DWARFFormValue::FC_Unknown,  // 0x0
+    DWARFFormValue::FC_Address,  // 0x01 DW_FORM_addr
+    DWARFFormValue::FC_Unknown,  // 0x02 unused
+    DWARFFormValue::FC_Block,    // 0x03 DW_FORM_block2
+    DWARFFormValue::FC_Block,    // 0x04 DW_FORM_block4
+    DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
+    // --- These can be FC_SectionOffset in DWARF3 and below:
+    DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
+    DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
+    // ---
+    DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
+    DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
+    DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
+    DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
+    DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
+    DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
+    DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
+    DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
+    DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
+    DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
+    DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
+    DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
+    DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
+    DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
+    DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
+    DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
+    DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
+    DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
+    DWARFFormValue::FC_String,        // 0x1a DW_FORM_strx
+    DWARFFormValue::FC_Address,       // 0x1b DW_FORM_addrx
+    DWARFFormValue::FC_Reference,     // 0x1c DW_FORM_ref_sup4
+    DWARFFormValue::FC_String,        // 0x1d DW_FORM_strp_sup
+    DWARFFormValue::FC_Constant,      // 0x1e DW_FORM_data16
+    DWARFFormValue::FC_String,        // 0x1f DW_FORM_line_strp
+    DWARFFormValue::FC_Reference,     // 0x20 DW_FORM_ref_sig8
+    DWARFFormValue::FC_Constant,      // 0x21 DW_FORM_implicit_const
+    DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx
+    DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx
+    DWARFFormValue::FC_Reference,     // 0x24 DW_FORM_ref_sup8
+    DWARFFormValue::FC_String,        // 0x25 DW_FORM_strx1
+    DWARFFormValue::FC_String,        // 0x26 DW_FORM_strx2
+    DWARFFormValue::FC_String,        // 0x27 DW_FORM_strx3
+    DWARFFormValue::FC_String,        // 0x28 DW_FORM_strx4
+    DWARFFormValue::FC_Address,       // 0x29 DW_FORM_addrx1
+    DWARFFormValue::FC_Address,       // 0x2a DW_FORM_addrx2
+    DWARFFormValue::FC_Address,       // 0x2b DW_FORM_addrx3
+    DWARFFormValue::FC_Address,       // 0x2c DW_FORM_addrx4
+
+};
+
+bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
+                               uint32_t *OffsetPtr,
+                               const dwarf::FormParams Params) {
+  bool Indirect = false;
+  do {
+    switch (Form) {
+    // Blocks of inlined data that have a length field and the data bytes
+    // inlined in the .debug_info.
+    case DW_FORM_exprloc:
+    case DW_FORM_block: {
+      uint64_t size = DebugInfoData.getULEB128(OffsetPtr);
+      *OffsetPtr += size;
+      return true;
+    }
+    case DW_FORM_block1: {
+      uint8_t size = DebugInfoData.getU8(OffsetPtr);
+      *OffsetPtr += size;
+      return true;
+    }
+    case DW_FORM_block2: {
+      uint16_t size = DebugInfoData.getU16(OffsetPtr);
+      *OffsetPtr += size;
+      return true;
+    }
+    case DW_FORM_block4: {
+      uint32_t size = DebugInfoData.getU32(OffsetPtr);
+      *OffsetPtr += size;
+      return true;
+    }
+
+    // Inlined NULL terminated C-strings.
+    case DW_FORM_string:
+      DebugInfoData.getCStr(OffsetPtr);
+      return true;
+
+    case DW_FORM_addr:
+    case DW_FORM_ref_addr:
+    case DW_FORM_flag_present:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+    case DW_FORM_data16:
+    case DW_FORM_flag:
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_sig8:
+    case DW_FORM_ref_sup4:
+    case DW_FORM_ref_sup8:
+    case DW_FORM_strx1:
+    case DW_FORM_strx2:
+    case DW_FORM_strx4:
+    case DW_FORM_addrx1:
+    case DW_FORM_addrx2:
+    case DW_FORM_addrx4:
+    case DW_FORM_sec_offset:
+    case DW_FORM_strp:
+    case DW_FORM_strp_sup:
+    case DW_FORM_line_strp:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
+      if (Optional<uint8_t> FixedSize =
+              dwarf::getFixedFormByteSize(Form, Params)) {
+        *OffsetPtr += *FixedSize;
+        return true;
+      }
+      return false;
+
+    // signed or unsigned LEB 128 values.
+    case DW_FORM_sdata:
+      DebugInfoData.getSLEB128(OffsetPtr);
+      return true;
+
+    case DW_FORM_udata:
+    case DW_FORM_ref_udata:
+    case DW_FORM_strx:
+    case DW_FORM_addrx:
+    case DW_FORM_loclistx:
+    case DW_FORM_rnglistx:
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_GNU_str_index:
+      DebugInfoData.getULEB128(OffsetPtr);
+      return true;
+
+    case DW_FORM_indirect:
+      Indirect = true;
+      Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
+      break;
+
+    default:
+      return false;
+    }
+  } while (Indirect);
+  return true;
+}
+
+bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
+  // First, check DWARF5 form classes.
+  if (Form < makeArrayRef(DWARF5FormClasses).size() &&
+      DWARF5FormClasses[Form] == FC)
+    return true;
+  // Check more forms from extensions and proposals.
+  switch (Form) {
+  case DW_FORM_GNU_ref_alt:
+    return (FC == FC_Reference);
+  case DW_FORM_GNU_addr_index:
+    return (FC == FC_Address);
+  case DW_FORM_GNU_str_index:
+  case DW_FORM_GNU_strp_alt:
+    return (FC == FC_String);
+  default:
+    break;
+  }
+  // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
+  // Don't check for DWARF version here, as some producers may still do this
+  // by mistake. Also accept DW_FORM_[line_]strp since these are
+  // .debug_[line_]str section offsets.
+  return (Form == DW_FORM_data4 || Form == DW_FORM_data8 ||
+          Form == DW_FORM_strp || Form == DW_FORM_line_strp) &&
+         FC == FC_SectionOffset;
+}
+
+bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
+                                  uint32_t *OffsetPtr, dwarf::FormParams FP,
+                                  const DWARFContext *Ctx,
+                                  const DWARFUnit *CU) {
+  if (!Ctx && CU)
+    Ctx = &CU->getContext();
+  C = Ctx;
+  U = CU;
+  bool Indirect = false;
+  bool IsBlock = false;
+  Value.data = nullptr;
+  // Read the value for the form into value and follow and DW_FORM_indirect
+  // instances we run into
+  do {
+    Indirect = false;
+    switch (Form) {
+    case DW_FORM_addr:
+    case DW_FORM_ref_addr: {
+      uint16_t Size =
+          (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();
+      Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex);
+      break;
+    }
+    case DW_FORM_exprloc:
+    case DW_FORM_block:
+      Value.uval = Data.getULEB128(OffsetPtr);
+      IsBlock = true;
+      break;
+    case DW_FORM_block1:
+      Value.uval = Data.getU8(OffsetPtr);
+      IsBlock = true;
+      break;
+    case DW_FORM_block2:
+      Value.uval = Data.getU16(OffsetPtr);
+      IsBlock = true;
+      break;
+    case DW_FORM_block4:
+      Value.uval = Data.getU32(OffsetPtr);
+      IsBlock = true;
+      break;
+    case DW_FORM_data1:
+    case DW_FORM_ref1:
+    case DW_FORM_flag:
+    case DW_FORM_strx1:
+    case DW_FORM_addrx1:
+      Value.uval = Data.getU8(OffsetPtr);
+      break;
+    case DW_FORM_data2:
+    case DW_FORM_ref2:
+    case DW_FORM_strx2:
+    case DW_FORM_addrx2:
+      Value.uval = Data.getU16(OffsetPtr);
+      break;
+    case DW_FORM_strx3:
+      Value.uval = Data.getU24(OffsetPtr);
+      break;
+    case DW_FORM_data4:
+    case DW_FORM_ref4:
+    case DW_FORM_ref_sup4:
+    case DW_FORM_strx4:
+    case DW_FORM_addrx4:
+      Value.uval = Data.getRelocatedValue(4, OffsetPtr);
+      break;
+    case DW_FORM_data8:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_sup8:
+      Value.uval = Data.getU64(OffsetPtr);
+      break;
+    case DW_FORM_data16:
+      // Treat this like a 16-byte block.
+      Value.uval = 16;
+      IsBlock = true;
+      break;
+    case DW_FORM_sdata:
+      Value.sval = Data.getSLEB128(OffsetPtr);
+      break;
+    case DW_FORM_udata:
+    case DW_FORM_ref_udata:
+    case DW_FORM_rnglistx:
+      Value.uval = Data.getULEB128(OffsetPtr);
+      break;
+    case DW_FORM_string:
+      Value.cstr = Data.getCStr(OffsetPtr);
+      break;
+    case DW_FORM_indirect:
+      Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr));
+      Indirect = true;
+      break;
+    case DW_FORM_strp:
+    case DW_FORM_sec_offset:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
+    case DW_FORM_line_strp:
+    case DW_FORM_strp_sup: {
+      Value.uval =
+          Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), OffsetPtr);
+      break;
+    }
+    case DW_FORM_flag_present:
+      Value.uval = 1;
+      break;
+    case DW_FORM_ref_sig8:
+      Value.uval = Data.getU64(OffsetPtr);
+      break;
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_GNU_str_index:
+    case DW_FORM_addrx:
+    case DW_FORM_strx:
+      Value.uval = Data.getULEB128(OffsetPtr);
+      break;
+    default:
+      // DWARFFormValue::skipValue() will have caught this and caused all
+      // DWARF DIEs to fail to be parsed, so this code is not be reachable.
+      llvm_unreachable("unsupported form");
+    }
+  } while (Indirect);
+
+  if (IsBlock) {
+    StringRef Str = Data.getData().substr(*OffsetPtr, Value.uval);
+    Value.data = nullptr;
+    if (!Str.empty()) {
+      Value.data = reinterpret_cast<const uint8_t *>(Str.data());
+      *OffsetPtr += Value.uval;
+    }
+  }
+
+  return true;
+}
+
+void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,
+                                          DIDumpOptions DumpOpts,
+                                          SectionedAddress SA) const {
+  OS << format("0x%016" PRIx64, SA.Address);
+  dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,
+                     SA.SectionIndex);
+}
+
+void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
+                                        DIDumpOptions DumpOpts,
+                                        uint64_t SectionIndex) {
+  if (!DumpOpts.Verbose || SectionIndex == -1ULL)
+    return;
+  ArrayRef<SectionName> SectionNames = Obj.getSectionNames();
+  const auto &SecRef = SectionNames[SectionIndex];
+
+  OS << " \"" << SecRef.Name << '\"';
+
+  // Print section index if name is not unique.
+  if (!SecRef.IsNameUnique)
+    OS << format(" [%" PRIu64 "]", SectionIndex);
+}
+
+void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
+  uint64_t UValue = Value.uval;
+  bool CURelativeOffset = false;
+  raw_ostream &AddrOS = DumpOpts.ShowAddresses
+                            ? WithColor(OS, HighlightColor::Address).get()
+                            : nulls();
+  switch (Form) {
+  case DW_FORM_addr:
+    dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});
+    break;
+  case DW_FORM_addrx:
+  case DW_FORM_addrx1:
+  case DW_FORM_addrx2:
+  case DW_FORM_addrx3:
+  case DW_FORM_addrx4:
+  case DW_FORM_GNU_addr_index: {
+    Optional<SectionedAddress> A = U->getAddrOffsetSectionItem(UValue);
+    if (!A || DumpOpts.Verbose)
+      AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
+    if (U == nullptr)
+      OS << "<invalid dwarf unit>";
+    else if (A)
+      dumpSectionedAddress(AddrOS, DumpOpts, *A);
+    else
+      OS << "<no .debug_addr section>";
+    break;
+  }
+  case DW_FORM_flag_present:
+    OS << "true";
+    break;
+  case DW_FORM_flag:
+  case DW_FORM_data1:
+    OS << format("0x%02x", (uint8_t)UValue);
+    break;
+  case DW_FORM_data2:
+    OS << format("0x%04x", (uint16_t)UValue);
+    break;
+  case DW_FORM_data4:
+    OS << format("0x%08x", (uint32_t)UValue);
+    break;
+  case DW_FORM_ref_sig8:
+    AddrOS << format("0x%016" PRIx64, UValue);
+    break;
+  case DW_FORM_data8:
+    OS << format("0x%016" PRIx64, UValue);
+    break;
+  case DW_FORM_data16:
+    OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), None, 16, 16);
+    break;
+  case DW_FORM_string:
+    OS << '"';
+    OS.write_escaped(Value.cstr);
+    OS << '"';
+    break;
+  case DW_FORM_exprloc:
+  case DW_FORM_block:
+  case DW_FORM_block1:
+  case DW_FORM_block2:
+  case DW_FORM_block4:
+    if (UValue > 0) {
+      switch (Form) {
+      case DW_FORM_exprloc:
+      case DW_FORM_block:
+        AddrOS << format("<0x%" PRIx64 "> ", UValue);
+        break;
+      case DW_FORM_block1:
+        AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);
+        break;
+      case DW_FORM_block2:
+        AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);
+        break;
+      case DW_FORM_block4:
+        AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);
+        break;
+      default:
+        break;
+      }
+
+      const uint8_t *DataPtr = Value.data;
+      if (DataPtr) {
+        // UValue contains size of block
+        const uint8_t *EndDataPtr = DataPtr + UValue;
+        while (DataPtr < EndDataPtr) {
+          AddrOS << format("%2.2x ", *DataPtr);
+          ++DataPtr;
+        }
+      } else
+        OS << "NULL";
+    }
+    break;
+
+  case DW_FORM_sdata:
+    OS << Value.sval;
+    break;
+  case DW_FORM_udata:
+    OS << Value.uval;
+    break;
+  case DW_FORM_strp:
+    if (DumpOpts.Verbose)
+      OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)UValue);
+    dumpString(OS);
+    break;
+  case DW_FORM_line_strp:
+    if (DumpOpts.Verbose)
+      OS << format(" .debug_line_str[0x%8.8x] = ", (uint32_t)UValue);
+    dumpString(OS);
+    break;
+  case DW_FORM_strx:
+  case DW_FORM_strx1:
+  case DW_FORM_strx2:
+  case DW_FORM_strx3:
+  case DW_FORM_strx4:
+  case DW_FORM_GNU_str_index:
+    if (DumpOpts.Verbose)
+      OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);
+    dumpString(OS);
+    break;
+  case DW_FORM_GNU_strp_alt:
+    if (DumpOpts.Verbose)
+      OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);
+    dumpString(OS);
+    break;
+  case DW_FORM_ref_addr:
+    AddrOS << format("0x%016" PRIx64, UValue);
+    break;
+  case DW_FORM_ref1:
+    CURelativeOffset = true;
+    if (DumpOpts.Verbose)
+      AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);
+    break;
+  case DW_FORM_ref2:
+    CURelativeOffset = true;
+    if (DumpOpts.Verbose)
+      AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);
+    break;
+  case DW_FORM_ref4:
+    CURelativeOffset = true;
+    if (DumpOpts.Verbose)
+      AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);
+    break;
+  case DW_FORM_ref8:
+    CURelativeOffset = true;
+    if (DumpOpts.Verbose)
+      AddrOS << format("cu + 0x%8.8" PRIx64, UValue);
+    break;
+  case DW_FORM_ref_udata:
+    CURelativeOffset = true;
+    if (DumpOpts.Verbose)
+      AddrOS << format("cu + 0x%" PRIx64, UValue);
+    break;
+  case DW_FORM_GNU_ref_alt:
+    AddrOS << format("<alt 0x%" PRIx64 ">", UValue);
+    break;
+
+  // All DW_FORM_indirect attributes should be resolved prior to calling
+  // this function
+  case DW_FORM_indirect:
+    OS << "DW_FORM_indirect";
+    break;
+
+  case DW_FORM_rnglistx:
+    OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);
+    break;
+
+  // Should be formatted to 64-bit for DWARF64.
+  case DW_FORM_sec_offset:
+    AddrOS << format("0x%08x", (uint32_t)UValue);
+    break;
+
+  default:
+    OS << format("DW_FORM(0x%4.4x)", Form);
+    break;
+  }
+
+  if (CURelativeOffset) {
+    if (DumpOpts.Verbose)
+      OS << " => {";
+    if (DumpOpts.ShowAddresses)
+      WithColor(OS, HighlightColor::Address).get()
+          << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));
+    if (DumpOpts.Verbose)
+      OS << "}";
+  }
+}
+
+void DWARFFormValue::dumpString(raw_ostream &OS) const {
+  Optional<const char *> DbgStr = getAsCString();
+  if (DbgStr.hasValue()) {
+    auto COS = WithColor(OS, HighlightColor::String);
+    COS.get() << '"';
+    COS.get().write_escaped(DbgStr.getValue());
+    COS.get() << '"';
+  }
+}
+
+Optional<const char *> DWARFFormValue::getAsCString() const {
+  if (!isFormClass(FC_String))
+    return None;
+  if (Form == DW_FORM_string)
+    return Value.cstr;
+  // FIXME: Add support for DW_FORM_GNU_strp_alt
+  if (Form == DW_FORM_GNU_strp_alt || C == nullptr)
+    return None;
+  uint32_t Offset = Value.uval;
+  if (Form == DW_FORM_line_strp) {
+    // .debug_line_str is tracked in the Context.
+    if (const char *Str = C->getLineStringExtractor().getCStr(&Offset))
+      return Str;
+    return None;
+  }
+  if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||
+      Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||
+      Form == DW_FORM_strx4) {
+    if (!U)
+      return None;
+    Optional<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);
+    if (!StrOffset)
+      return None;
+    Offset = *StrOffset;
+  }
+  // Prefer the Unit's string extractor, because for .dwo it will point to
+  // .debug_str.dwo, while the Context's extractor always uses .debug_str.
+  if (U) {
+    if (const char *Str = U->getStringExtractor().getCStr(&Offset))
+      return Str;
+    return None;
+  }
+  if (const char *Str = C->getStringExtractor().getCStr(&Offset))
+    return Str;
+  return None;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsAddress() const {
+  if (auto SA = getAsSectionedAddress())
+    return SA->Address;
+  return None;
+}
+Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const {
+  if (!isFormClass(FC_Address))
+    return None;
+  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) {
+    uint32_t Index = Value.uval;
+    if (!U)
+      return None;
+    Optional<SectionedAddress> SA = U->getAddrOffsetSectionItem(Index);
+    if (!SA)
+      return None;
+    return SA;
+  }
+  return {{Value.uval, Value.SectionIndex}};
+}
+
+Optional<uint64_t> DWARFFormValue::getAsReference() const {
+  if (!isFormClass(FC_Reference))
+    return None;
+  switch (Form) {
+  case DW_FORM_ref1:
+  case DW_FORM_ref2:
+  case DW_FORM_ref4:
+  case DW_FORM_ref8:
+  case DW_FORM_ref_udata:
+    if (!U)
+      return None;
+    return Value.uval + U->getOffset();
+  case DW_FORM_ref_addr:
+  case DW_FORM_ref_sig8:
+  case DW_FORM_GNU_ref_alt:
+    return Value.uval;
+  default:
+    return None;
+  }
+}
+
+Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
+  if (!isFormClass(FC_SectionOffset))
+    return None;
+  return Value.uval;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
+  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
+      Form == DW_FORM_sdata)
+    return None;
+  return Value.uval;
+}
+
+Optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
+  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
+      (Form == DW_FORM_udata &&
+       uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))
+    return None;
+  switch (Form) {
+  case DW_FORM_data4:
+    return int32_t(Value.uval);
+  case DW_FORM_data2:
+    return int16_t(Value.uval);
+  case DW_FORM_data1:
+    return int8_t(Value.uval);
+  case DW_FORM_sdata:
+  case DW_FORM_data8:
+  default:
+    return Value.sval;
+  }
+}
+
+Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
+  if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&
+      Form != DW_FORM_data16)
+    return None;
+  return makeArrayRef(Value.data, Value.uval);
+}
+
+Optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {
+  if (!isFormClass(FC_String) && Form == DW_FORM_string)
+    return None;
+  return Value.uval;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {
+  if (!isFormClass(FC_Reference))
+    return None;
+  return Value.uval;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
new file mode 100644
index 0000000..1abd931
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp
@@ -0,0 +1,200 @@
+//===- DWARFGdbIndex.cpp --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <utility>
+
+using namespace llvm;
+
+// .gdb_index section format reference:
+// https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
+
+void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const {
+  OS << format("\n  CU list offset = 0x%x, has %" PRId64 " entries:",
+               CuListOffset, (uint64_t)CuList.size())
+     << '\n';
+  uint32_t I = 0;
+  for (const CompUnitEntry &CU : CuList)
+    OS << format("    %d: Offset = 0x%llx, Length = 0x%llx\n", I++, CU.Offset,
+                 CU.Length);
+}
+
+void DWARFGdbIndex::dumpTUList(raw_ostream &OS) const {
+  OS << formatv("\n  Types CU list offset = {0:x}, has {1} entries:\n",
+                TuListOffset, TuList.size());
+  uint32_t I = 0;
+  for (const TypeUnitEntry &TU : TuList)
+    OS << formatv("    {0}: offset = {1:x8}, type_offset = {2:x8}, "
+                  "type_signature = {3:x16}\n",
+                  I++, TU.Offset, TU.TypeOffset, TU.TypeSignature);
+}
+
+void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const {
+  OS << format("\n  Address area offset = 0x%x, has %" PRId64 " entries:",
+               AddressAreaOffset, (uint64_t)AddressArea.size())
+     << '\n';
+  for (const AddressEntry &Addr : AddressArea)
+    OS << format(
+        "    Low/High address = [0x%llx, 0x%llx) (Size: 0x%llx), CU id = %d\n",
+        Addr.LowAddress, Addr.HighAddress, Addr.HighAddress - Addr.LowAddress,
+        Addr.CuIndex);
+}
+
+void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const {
+  OS << format("\n  Symbol table offset = 0x%x, size = %" PRId64
+               ", filled slots:",
+               SymbolTableOffset, (uint64_t)SymbolTable.size())
+     << '\n';
+  uint32_t I = -1;
+  for (const SymTableEntry &E : SymbolTable) {
+    ++I;
+    if (!E.NameOffset && !E.VecOffset)
+      continue;
+
+    OS << format("    %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I,
+                 E.NameOffset, E.VecOffset);
+
+    StringRef Name = ConstantPoolStrings.substr(
+        ConstantPoolOffset - StringPoolOffset + E.NameOffset);
+
+    auto CuVector = std::find_if(
+        ConstantPoolVectors.begin(), ConstantPoolVectors.end(),
+        [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) {
+          return V.first == E.VecOffset;
+        });
+    assert(CuVector != ConstantPoolVectors.end() && "Invalid symbol table");
+    uint32_t CuVectorId = CuVector - ConstantPoolVectors.begin();
+    OS << format("      String name: %s, CU vector index: %d\n", Name.data(),
+                 CuVectorId);
+  }
+}
+
+void DWARFGdbIndex::dumpConstantPool(raw_ostream &OS) const {
+  OS << format("\n  Constant pool offset = 0x%x, has %" PRId64 " CU vectors:",
+               ConstantPoolOffset, (uint64_t)ConstantPoolVectors.size());
+  uint32_t I = 0;
+  for (const auto &V : ConstantPoolVectors) {
+    OS << format("\n    %d(0x%x): ", I++, V.first);
+    for (uint32_t Val : V.second)
+      OS << format("0x%x ", Val);
+  }
+  OS << '\n';
+}
+
+void DWARFGdbIndex::dump(raw_ostream &OS) {
+  if (HasError) {
+    OS << "\n<error parsing>\n";
+    return;
+  }
+
+  if (HasContent) {
+    OS << "  Version = " << Version << '\n';
+    dumpCUList(OS);
+    dumpTUList(OS);
+    dumpAddressArea(OS);
+    dumpSymbolTable(OS);
+    dumpConstantPool(OS);
+  }
+}
+
+bool DWARFGdbIndex::parseImpl(DataExtractor Data) {
+  uint32_t Offset = 0;
+
+  // Only version 7 is supported at this moment.
+  Version = Data.getU32(&Offset);
+  if (Version != 7)
+    return false;
+
+  CuListOffset = Data.getU32(&Offset);
+  uint32_t CuTypesOffset = Data.getU32(&Offset);
+  AddressAreaOffset = Data.getU32(&Offset);
+  SymbolTableOffset = Data.getU32(&Offset);
+  ConstantPoolOffset = Data.getU32(&Offset);
+
+  if (Offset != CuListOffset)
+    return false;
+
+  uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16;
+  CuList.reserve(CuListSize);
+  for (uint32_t i = 0; i < CuListSize; ++i) {
+    uint64_t CuOffset = Data.getU64(&Offset);
+    uint64_t CuLength = Data.getU64(&Offset);
+    CuList.push_back({CuOffset, CuLength});
+  }
+
+  // CU Types are no longer needed as DWARF skeleton type units never made it
+  // into the standard.
+  uint32_t TuListSize = (AddressAreaOffset - CuTypesOffset) / 24;
+  TuList.resize(TuListSize);
+  for (uint32_t I = 0; I < TuListSize; ++I) {
+    uint64_t CuOffset = Data.getU64(&Offset);
+    uint64_t TypeOffset = Data.getU64(&Offset);
+    uint64_t Signature = Data.getU64(&Offset);
+    TuList[I] = {CuOffset, TypeOffset, Signature};
+  }
+
+  uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20;
+  AddressArea.reserve(AddressAreaSize);
+  for (uint32_t i = 0; i < AddressAreaSize; ++i) {
+    uint64_t LowAddress = Data.getU64(&Offset);
+    uint64_t HighAddress = Data.getU64(&Offset);
+    uint32_t CuIndex = Data.getU32(&Offset);
+    AddressArea.push_back({LowAddress, HighAddress, CuIndex});
+  }
+
+  // The symbol table. This is an open addressed hash table. The size of the
+  // hash table is always a power of 2.
+  // Each slot in the hash table consists of a pair of offset_type values. The
+  // first value is the offset of the symbol's name in the constant pool. The
+  // second value is the offset of the CU vector in the constant pool.
+  // If both values are 0, then this slot in the hash table is empty. This is ok
+  // because while 0 is a valid constant pool index, it cannot be a valid index
+  // for both a string and a CU vector.
+  uint32_t SymTableSize = (ConstantPoolOffset - SymbolTableOffset) / 8;
+  SymbolTable.reserve(SymTableSize);
+  uint32_t CuVectorsTotal = 0;
+  for (uint32_t i = 0; i < SymTableSize; ++i) {
+    uint32_t NameOffset = Data.getU32(&Offset);
+    uint32_t CuVecOffset = Data.getU32(&Offset);
+    SymbolTable.push_back({NameOffset, CuVecOffset});
+    if (NameOffset || CuVecOffset)
+      ++CuVectorsTotal;
+  }
+
+  // The constant pool. CU vectors are stored first, followed by strings.
+  // The first value is the number of CU indices in the vector. Each subsequent
+  // value is the index and symbol attributes of a CU in the CU list.
+  for (uint32_t i = 0; i < CuVectorsTotal; ++i) {
+    ConstantPoolVectors.emplace_back(0, SmallVector<uint32_t, 0>());
+    auto &Vec = ConstantPoolVectors.back();
+    Vec.first = Offset - ConstantPoolOffset;
+
+    uint32_t Num = Data.getU32(&Offset);
+    for (uint32_t j = 0; j < Num; ++j)
+      Vec.second.push_back(Data.getU32(&Offset));
+  }
+
+  ConstantPoolStrings = Data.getData().drop_front(Offset);
+  StringPoolOffset = Offset;
+  return true;
+}
+
+void DWARFGdbIndex::parse(DataExtractor Data) {
+  HasContent = !Data.getData().empty();
+  HasError = HasContent && !parseImpl(Data);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
new file mode 100644
index 0000000..462c036
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp
@@ -0,0 +1,109 @@
+//===- DWARFListTable.cpp ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+Error DWARFListTableHeader::extract(DWARFDataExtractor Data,
+                                    uint32_t *OffsetPtr) {
+  HeaderOffset = *OffsetPtr;
+  // Read and verify the length field.
+  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t)))
+    return createStringError(errc::invalid_argument,
+                       "section is not large enough to contain a "
+                       "%s table length at offset 0x%" PRIx32,
+                       SectionName.data(), *OffsetPtr);
+  // TODO: Add support for DWARF64.
+  HeaderData.Length = Data.getU32(OffsetPtr);
+  if (HeaderData.Length == 0xffffffffu)
+    return createStringError(errc::not_supported,
+                       "DWARF64 is not supported in %s at offset 0x%" PRIx32,
+                       SectionName.data(), HeaderOffset);
+  Format = dwarf::DwarfFormat::DWARF32;
+  if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header))
+    return createStringError(errc::invalid_argument,
+                       "%s table at offset 0x%" PRIx32
+                       " has too small length (0x%" PRIx32
+                       ") to contain a complete header",
+                       SectionName.data(), HeaderOffset, length());
+  uint32_t End = HeaderOffset + length();
+  if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset))
+    return createStringError(errc::invalid_argument,
+                       "section is not large enough to contain a %s table "
+                       "of length 0x%" PRIx32 " at offset 0x%" PRIx32,
+                       SectionName.data(), length(), HeaderOffset);
+
+  HeaderData.Version = Data.getU16(OffsetPtr);
+  HeaderData.AddrSize = Data.getU8(OffsetPtr);
+  HeaderData.SegSize = Data.getU8(OffsetPtr);
+  HeaderData.OffsetEntryCount = Data.getU32(OffsetPtr);
+
+  // Perform basic validation of the remaining header fields.
+  if (HeaderData.Version != 5)
+    return createStringError(errc::invalid_argument,
+                       "unrecognised %s table version %" PRIu16
+                       " in table at offset 0x%" PRIx32,
+                       SectionName.data(), HeaderData.Version, HeaderOffset);
+  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
+    return createStringError(errc::not_supported,
+                       "%s table at offset 0x%" PRIx32
+                       " has unsupported address size %" PRIu8,
+                       SectionName.data(), HeaderOffset, HeaderData.AddrSize);
+  if (HeaderData.SegSize != 0)
+    return createStringError(errc::not_supported,
+                       "%s table at offset 0x%" PRIx32
+                       " has unsupported segment selector size %" PRIu8,
+                       SectionName.data(), HeaderOffset, HeaderData.SegSize);
+  if (End < HeaderOffset + sizeof(HeaderData) +
+                HeaderData.OffsetEntryCount * sizeof(uint32_t))
+    return createStringError(errc::invalid_argument,
+        "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32
+        ") than there is space for",
+        SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount);
+  Data.setAddressSize(HeaderData.AddrSize);
+  for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I)
+    Offsets.push_back(Data.getU32(OffsetPtr));
+  return Error::success();
+}
+
+void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
+  if (DumpOpts.Verbose)
+    OS << format("0x%8.8" PRIx32 ": ", HeaderOffset);
+  OS << format(
+      "%s list header: length = 0x%8.8" PRIx32 ", version = 0x%4.4" PRIx16 ", "
+      "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8
+      ", offset_entry_count = "
+      "0x%8.8" PRIx32 "\n",
+      ListTypeString.data(), HeaderData.Length, HeaderData.Version,
+      HeaderData.AddrSize, HeaderData.SegSize, HeaderData.OffsetEntryCount);
+
+  if (HeaderData.OffsetEntryCount > 0) {
+    OS << "offsets: [";
+    for (const auto &Off : Offsets) {
+      OS << format("\n0x%8.8" PRIx32, Off);
+      if (DumpOpts.Verbose)
+        OS << format(" => 0x%8.8" PRIx32,
+                     Off + HeaderOffset + sizeof(HeaderData));
+    }
+    OS << "\n]\n";
+  }
+}
+
+uint32_t DWARFListTableHeader::length() const {
+  if (HeaderData.Length == 0)
+    return 0;
+  // TODO: DWARF64 support.
+  return HeaderData.Length + sizeof(uint32_t);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
new file mode 100644
index 0000000..00be75e
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
@@ -0,0 +1,48 @@
+//===- DWARFTypeUnit.cpp --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cinttypes>
+
+using namespace llvm;
+
+void DWARFTypeUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
+  DWARFDie TD = getDIEForOffset(getTypeOffset() + getOffset());
+  const char *Name = TD.getName(DINameKind::ShortName);
+
+  if (DumpOpts.SummarizeTypes) {
+    OS << "name = '" << Name << "'"
+       << " type_signature = " << format("0x%016" PRIx64, getTypeHash())
+       << " length = " << format("0x%08x", getLength()) << '\n';
+    return;
+  }
+
+  OS << format("0x%08x", getOffset()) << ": Type Unit:"
+     << " length = " << format("0x%08x", getLength())
+     << " version = " << format("0x%04x", getVersion());
+  if (getVersion() >= 5)
+    OS << " unit_type = " << dwarf::UnitTypeString(getUnitType());
+  OS << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+     << " addr_size = " << format("0x%02x", getAddressByteSize())
+     << " name = '" << Name << "'"
+     << " type_signature = " << format("0x%016" PRIx64, getTypeHash())
+     << " type_offset = " << format("0x%04x", getTypeOffset())
+     << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n";
+
+  if (DWARFDie TU = getUnitDIE(false))
+    TU.dump(OS, 0, DumpOpts);
+  else
+    OS << "<type unit can't be parsed!>\n\n";
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
new file mode 100644
index 0000000..8023466
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -0,0 +1,844 @@
+//===- DWARFUnit.cpp ------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+void DWARFUnitVector::addUnitsForSection(DWARFContext &C,
+                                         const DWARFSection &Section,
+                                         DWARFSectionKind SectionKind) {
+  const DWARFObject &D = C.getDWARFObj();
+  addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(),
+               &D.getLocSection(), D.getStringSection(),
+               D.getStringOffsetSection(), &D.getAddrSection(),
+               D.getLineSection(), D.isLittleEndian(), false, false,
+               SectionKind);
+}
+
+void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C,
+                                            const DWARFSection &DWOSection,
+                                            DWARFSectionKind SectionKind,
+                                            bool Lazy) {
+  const DWARFObject &D = C.getDWARFObj();
+  addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(),
+               &D.getLocDWOSection(), D.getStringDWOSection(),
+               D.getStringOffsetDWOSection(), &D.getAddrSection(),
+               D.getLineDWOSection(), C.isLittleEndian(), true, Lazy,
+               SectionKind);
+}
+
+void DWARFUnitVector::addUnitsImpl(
+    DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section,
+    const DWARFDebugAbbrev *DA, const DWARFSection *RS,
+    const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS,
+    const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO,
+    bool Lazy, DWARFSectionKind SectionKind) {
+  DWARFDataExtractor Data(Obj, Section, LE, 0);
+  // Lazy initialization of Parser, now that we have all section info.
+  if (!Parser) {
+    Parser = [=, &Context, &Obj, &Section, &SOS,
+              &LS](uint32_t Offset, DWARFSectionKind SectionKind,
+                   const DWARFSection *CurSection,
+                   const DWARFUnitIndex::Entry *IndexEntry)
+        -> std::unique_ptr<DWARFUnit> {
+      const DWARFSection &InfoSection = CurSection ? *CurSection : Section;
+      DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
+      if (!Data.isValidOffset(Offset))
+        return nullptr;
+      const DWARFUnitIndex *Index = nullptr;
+      if (IsDWO)
+        Index = &getDWARFUnitIndex(Context, SectionKind);
+      DWARFUnitHeader Header;
+      if (!Header.extract(Context, Data, &Offset, SectionKind, Index,
+                          IndexEntry))
+        return nullptr;
+      std::unique_ptr<DWARFUnit> U;
+      if (Header.isTypeUnit())
+        U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
+                                             RS, LocSection, SS, SOS, AOS, LS,
+                                             LE, IsDWO, *this);
+      else
+        U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header,
+                                                DA, RS, LocSection, SS, SOS,
+                                                AOS, LS, LE, IsDWO, *this);
+      return U;
+    };
+  }
+  if (Lazy)
+    return;
+  // Find a reasonable insertion point within the vector.  We skip over
+  // (a) units from a different section, (b) units from the same section
+  // but with lower offset-within-section.  This keeps units in order
+  // within a section, although not necessarily within the object file,
+  // even if we do lazy parsing.
+  auto I = this->begin();
+  uint32_t Offset = 0;
+  while (Data.isValidOffset(Offset)) {
+    if (I != this->end() &&
+        (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) {
+      ++I;
+      continue;
+    }
+    auto U = Parser(Offset, SectionKind, &Section, nullptr);
+    // If parsing failed, we're done with this section.
+    if (!U)
+      break;
+    Offset = U->getNextUnitOffset();
+    I = std::next(this->insert(I, std::move(U)));
+  }
+}
+
+DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) {
+  auto I = std::upper_bound(begin(), end(), Unit,
+                            [](const std::unique_ptr<DWARFUnit> &LHS,
+                               const std::unique_ptr<DWARFUnit> &RHS) {
+                              return LHS->getOffset() < RHS->getOffset();
+                            });
+  return this->insert(I, std::move(Unit))->get();
+}
+
+DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const {
+  auto end = begin() + getNumInfoUnits();
+  auto *CU =
+      std::upper_bound(begin(), end, Offset,
+                       [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
+                         return LHS < RHS->getNextUnitOffset();
+                       });
+  if (CU != end && (*CU)->getOffset() <= Offset)
+    return CU->get();
+  return nullptr;
+}
+
+DWARFUnit *
+DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
+  const auto *CUOff = E.getOffset(DW_SECT_INFO);
+  if (!CUOff)
+    return nullptr;
+
+  auto Offset = CUOff->Offset;
+  auto end = begin() + getNumInfoUnits();
+
+  auto *CU =
+      std::upper_bound(begin(), end, CUOff->Offset,
+                       [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
+                         return LHS < RHS->getNextUnitOffset();
+                       });
+  if (CU != end && (*CU)->getOffset() <= Offset)
+    return CU->get();
+
+  if (!Parser)
+    return nullptr;
+
+  auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E);
+  if (!U)
+    U = nullptr;
+
+  auto *NewCU = U.get();
+  this->insert(CU, std::move(U));
+  ++NumInfoUnits;
+  return NewCU;
+}
+
+DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
+                     const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
+                     const DWARFSection *RS, const DWARFSection *LocSection,
+                     StringRef SS, const DWARFSection &SOS,
+                     const DWARFSection *AOS, const DWARFSection &LS, bool LE,
+                     bool IsDWO, const DWARFUnitVector &UnitVector)
+    : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
+      RangeSection(RS), LocSection(LocSection), LineSection(LS),
+      StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
+      isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) {
+  clear();
+  // For split DWARF we only need to keep track of the location list section's
+  // data (no relocations), and if we are reading a package file, we need to
+  // adjust the location list data based on the index entries.
+  if (IsDWO) {
+    LocSectionData = LocSection->Data;
+    if (auto *IndexEntry = Header.getIndexEntry())
+      if (const auto *C = IndexEntry->getOffset(DW_SECT_LOC))
+        LocSectionData = LocSectionData.substr(C->Offset, C->Length);
+  }
+}
+
+DWARFUnit::~DWARFUnit() = default;
+
+DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
+  return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian,
+                            getAddressByteSize());
+}
+
+Optional<SectionedAddress>
+DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
+  if (IsDWO) {
+    auto R = Context.info_section_units();
+    auto I = R.begin();
+    // Surprising if a DWO file has more than one skeleton unit in it - this
+    // probably shouldn't be valid, but if a use case is found, here's where to
+    // support it (probably have to linearly search for the matching skeleton CU
+    // here)
+    if (I != R.end() && std::next(I) == R.end())
+      return (*I)->getAddrOffsetSectionItem(Index);
+  }
+  uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize();
+  if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
+    return None;
+  DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
+                        isLittleEndian, getAddressByteSize());
+  uint64_t Section;
+  uint64_t Address = DA.getRelocatedAddress(&Offset, &Section);
+  return {{Address, Section}};
+}
+
+Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
+  if (!StringOffsetsTableContribution)
+    return None;
+  unsigned ItemSize = getDwarfStringOffsetsByteSize();
+  uint32_t Offset = getStringOffsetsBase() + Index * ItemSize;
+  if (StringOffsetSection.Data.size() < Offset + ItemSize)
+    return None;
+  DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
+                        isLittleEndian, 0);
+  return DA.getRelocatedValue(ItemSize, &Offset);
+}
+
+bool DWARFUnitHeader::extract(DWARFContext &Context,
+                              const DWARFDataExtractor &debug_info,
+                              uint32_t *offset_ptr,
+                              DWARFSectionKind SectionKind,
+                              const DWARFUnitIndex *Index,
+                              const DWARFUnitIndex::Entry *Entry) {
+  Offset = *offset_ptr;
+  IndexEntry = Entry;
+  if (!IndexEntry && Index)
+    IndexEntry = Index->getFromOffset(*offset_ptr);
+  Length = debug_info.getU32(offset_ptr);
+  // FIXME: Support DWARF64.
+  unsigned SizeOfLength = 4;
+  FormParams.Format = DWARF32;
+  FormParams.Version = debug_info.getU16(offset_ptr);
+  if (FormParams.Version >= 5) {
+    UnitType = debug_info.getU8(offset_ptr);
+    FormParams.AddrSize = debug_info.getU8(offset_ptr);
+    AbbrOffset = debug_info.getU32(offset_ptr);
+  } else {
+    AbbrOffset = debug_info.getRelocatedValue(4, offset_ptr);
+    FormParams.AddrSize = debug_info.getU8(offset_ptr);
+    // Fake a unit type based on the section type.  This isn't perfect,
+    // but distinguishing compile and type units is generally enough.
+    if (SectionKind == DW_SECT_TYPES)
+      UnitType = DW_UT_type;
+    else
+      UnitType = DW_UT_compile;
+  }
+  if (IndexEntry) {
+    if (AbbrOffset)
+      return false;
+    auto *UnitContrib = IndexEntry->getOffset();
+    if (!UnitContrib || UnitContrib->Length != (Length + 4))
+      return false;
+    auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
+    if (!AbbrEntry)
+      return false;
+    AbbrOffset = AbbrEntry->Offset;
+  }
+  if (isTypeUnit()) {
+    TypeHash = debug_info.getU64(offset_ptr);
+    TypeOffset = debug_info.getU32(offset_ptr);
+  } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
+    DWOId = debug_info.getU64(offset_ptr);
+
+  // Header fields all parsed, capture the size of this unit header.
+  assert(*offset_ptr - Offset <= 255 && "unexpected header size");
+  Size = uint8_t(*offset_ptr - Offset);
+
+  // Type offset is unit-relative; should be after the header and before
+  // the end of the current unit.
+  bool TypeOffsetOK =
+      !isTypeUnit()
+          ? true
+          : TypeOffset >= Size && TypeOffset < getLength() + SizeOfLength;
+  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
+  bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
+  bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;
+
+  if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
+    return false;
+
+  // Keep track of the highest DWARF version we encounter across all units.
+  Context.setMaxVersionIfGreater(getVersion());
+  return true;
+}
+
+// Parse the rangelist table header, including the optional array of offsets
+// following it (DWARF v5 and later).
+static Expected<DWARFDebugRnglistTable>
+parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+  // TODO: Support DWARF64
+  // We are expected to be called with Offset 0 or pointing just past the table
+  // header, which is 12 bytes long for DWARF32.
+  if (Offset > 0) {
+    if (Offset < 12U)
+      return createStringError(errc::invalid_argument, "Did not detect a valid"
+                               " range list table with base = 0x%" PRIu32,
+                               Offset);
+    Offset -= 12U;
+  }
+  llvm::DWARFDebugRnglistTable Table;
+  if (Error E = Table.extractHeaderAndOffsets(DA, &Offset))
+    return std::move(E);
+  return Table;
+}
+
+Error DWARFUnit::extractRangeList(uint32_t RangeListOffset,
+                                  DWARFDebugRangeList &RangeList) const {
+  // Require that compile unit is extracted.
+  assert(!DieArray.empty());
+  DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
+                                isLittleEndian, getAddressByteSize());
+  uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
+  return RangeList.extract(RangesData, &ActualRangeListOffset);
+}
+
+void DWARFUnit::clear() {
+  Abbrevs = nullptr;
+  BaseAddr.reset();
+  RangeSectionBase = 0;
+  AddrOffsetSectionBase = 0;
+  clearDIEs(false);
+  DWO.reset();
+}
+
+const char *DWARFUnit::getCompilationDir() {
+  return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr);
+}
+
+void DWARFUnit::extractDIEsToVector(
+    bool AppendCUDie, bool AppendNonCUDies,
+    std::vector<DWARFDebugInfoEntry> &Dies) const {
+  if (!AppendCUDie && !AppendNonCUDies)
+    return;
+
+  // Set the offset to that of the first DIE and calculate the start of the
+  // next compilation unit header.
+  uint32_t DIEOffset = getOffset() + getHeaderSize();
+  uint32_t NextCUOffset = getNextUnitOffset();
+  DWARFDebugInfoEntry DIE;
+  DWARFDataExtractor DebugInfoData = getDebugInfoExtractor();
+  uint32_t Depth = 0;
+  bool IsCUDie = true;
+
+  while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
+                         Depth)) {
+    if (IsCUDie) {
+      if (AppendCUDie)
+        Dies.push_back(DIE);
+      if (!AppendNonCUDies)
+        break;
+      // The average bytes per DIE entry has been seen to be
+      // around 14-20 so let's pre-reserve the needed memory for
+      // our DIE entries accordingly.
+      Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
+      IsCUDie = false;
+    } else {
+      Dies.push_back(DIE);
+    }
+
+    if (const DWARFAbbreviationDeclaration *AbbrDecl =
+            DIE.getAbbreviationDeclarationPtr()) {
+      // Normal DIE
+      if (AbbrDecl->hasChildren())
+        ++Depth;
+    } else {
+      // NULL DIE.
+      if (Depth > 0)
+        --Depth;
+      if (Depth == 0)
+        break;  // We are done with this compile unit!
+    }
+  }
+
+  // Give a little bit of info if we encounter corrupt DWARF (our offset
+  // should always terminate at or before the start of the next compilation
+  // unit header).
+  if (DIEOffset > NextCUOffset)
+    WithColor::warning() << format("DWARF compile unit extends beyond its "
+                                   "bounds cu 0x%8.8x at 0x%8.8x\n",
+                                   getOffset(), DIEOffset);
+}
+
+size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
+  if ((CUDieOnly && !DieArray.empty()) ||
+      DieArray.size() > 1)
+    return 0; // Already parsed.
+
+  bool HasCUDie = !DieArray.empty();
+  extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
+
+  if (DieArray.empty())
+    return 0;
+
+  // If CU DIE was just parsed, copy several attribute values from it.
+  if (!HasCUDie) {
+    DWARFDie UnitDie = getUnitDIE();
+    if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
+      Header.setDWOId(*DWOId);
+    if (!IsDWO) {
+      assert(AddrOffsetSectionBase == 0);
+      assert(RangeSectionBase == 0);
+      AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0);
+      if (!AddrOffsetSectionBase)
+        AddrOffsetSectionBase =
+            toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0);
+      RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
+    }
+
+    // In general, in DWARF v5 and beyond we derive the start of the unit's
+    // contribution to the string offsets table from the unit DIE's
+    // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
+    // attribute, so we assume that there is a contribution to the string
+    // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
+    // In both cases we need to determine the format of the contribution,
+    // which may differ from the unit's format.
+    DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
+                          isLittleEndian, 0);
+    if (IsDWO)
+      StringOffsetsTableContribution =
+          determineStringOffsetsTableContributionDWO(DA);
+    else if (getVersion() >= 5)
+      StringOffsetsTableContribution =
+          determineStringOffsetsTableContribution(DA);
+
+    // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
+    // describe address ranges.
+    if (getVersion() >= 5) {
+      if (IsDWO)
+        setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
+      else
+        setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
+                         toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0));
+      if (RangeSection->Data.size()) {
+        // Parse the range list table header. Individual range lists are
+        // extracted lazily.
+        DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
+                                    isLittleEndian, 0);
+        if (auto TableOrError =
+                parseRngListTableHeader(RangesDA, RangeSectionBase))
+          RngListTable = TableOrError.get();
+        else
+          WithColor::error() << "parsing a range list table: "
+                             << toString(TableOrError.takeError())
+                             << '\n';
+
+        // In a split dwarf unit, there is no DW_AT_rnglists_base attribute.
+        // Adjust RangeSectionBase to point past the table header.
+        if (IsDWO && RngListTable)
+          RangeSectionBase = RngListTable->getHeaderSize();
+      }
+    }
+
+    // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
+    // skeleton CU DIE, so that DWARF users not aware of it are not broken.
+    }
+
+  return DieArray.size();
+}
+
+bool DWARFUnit::parseDWO() {
+  if (IsDWO)
+    return false;
+  if (DWO.get())
+    return false;
+  DWARFDie UnitDie = getUnitDIE();
+  if (!UnitDie)
+    return false;
+  auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name));
+  if (!DWOFileName)
+    return false;
+  auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir));
+  SmallString<16> AbsolutePath;
+  if (sys::path::is_relative(*DWOFileName) && CompilationDir &&
+      *CompilationDir) {
+    sys::path::append(AbsolutePath, *CompilationDir);
+  }
+  sys::path::append(AbsolutePath, *DWOFileName);
+  auto DWOId = getDWOId();
+  if (!DWOId)
+    return false;
+  auto DWOContext = Context.getDWOContext(AbsolutePath);
+  if (!DWOContext)
+    return false;
+
+  DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId);
+  if (!DWOCU)
+    return false;
+  DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
+  // Share .debug_addr and .debug_ranges section with compile unit in .dwo
+  DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
+  if (getVersion() >= 5) {
+    DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
+    DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
+                                isLittleEndian, 0);
+    if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase))
+      DWO->RngListTable = TableOrError.get();
+    else
+      WithColor::error() << "parsing a range list table: "
+                         << toString(TableOrError.takeError())
+                         << '\n';
+    if (DWO->RngListTable)
+      DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
+  } else {
+    auto DWORangesBase = UnitDie.getRangesBaseAttribute();
+    DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
+  }
+
+  return true;
+}
+
+void DWARFUnit::clearDIEs(bool KeepCUDie) {
+  if (DieArray.size() > (unsigned)KeepCUDie) {
+    DieArray.resize((unsigned)KeepCUDie);
+    DieArray.shrink_to_fit();
+  }
+}
+
+Expected<DWARFAddressRangesVector>
+DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
+  if (getVersion() <= 4) {
+    DWARFDebugRangeList RangeList;
+    if (Error E = extractRangeList(Offset, RangeList))
+      return std::move(E);
+    return RangeList.getAbsoluteRanges(getBaseAddress());
+  }
+  if (RngListTable) {
+    DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
+                                  isLittleEndian, RngListTable->getAddrSize());
+    auto RangeListOrError = RngListTable->findList(RangesData, Offset);
+    if (RangeListOrError)
+      return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this);
+    return RangeListOrError.takeError();
+  }
+
+  return createStringError(errc::invalid_argument,
+                           "missing or invalid range list table");
+}
+
+Expected<DWARFAddressRangesVector>
+DWARFUnit::findRnglistFromIndex(uint32_t Index) {
+  if (auto Offset = getRnglistOffset(Index))
+    return findRnglistFromOffset(*Offset + RangeSectionBase);
+
+  if (RngListTable)
+    return createStringError(errc::invalid_argument,
+                             "invalid range list table index %d", Index);
+  else
+    return createStringError(errc::invalid_argument,
+                             "missing or invalid range list table");
+}
+
+Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() {
+  DWARFDie UnitDie = getUnitDIE();
+  if (!UnitDie)
+    return createStringError(errc::invalid_argument, "No unit DIE");
+
+  // First, check if unit DIE describes address ranges for the whole unit.
+  auto CUDIERangesOrError = UnitDie.getAddressRanges();
+  if (!CUDIERangesOrError)
+    return createStringError(errc::invalid_argument,
+                             "decoding address ranges: %s",
+                             toString(CUDIERangesOrError.takeError()).c_str());
+  return *CUDIERangesOrError;
+}
+
+void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
+  if (Die.isSubroutineDIE()) {
+    auto DIERangesOrError = Die.getAddressRanges();
+    if (DIERangesOrError) {
+      for (const auto &R : DIERangesOrError.get()) {
+        // Ignore 0-sized ranges.
+        if (R.LowPC == R.HighPC)
+          continue;
+        auto B = AddrDieMap.upper_bound(R.LowPC);
+        if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) {
+          // The range is a sub-range of existing ranges, we need to split the
+          // existing range.
+          if (R.HighPC < B->second.first)
+            AddrDieMap[R.HighPC] = B->second;
+          if (R.LowPC > B->first)
+            AddrDieMap[B->first].first = R.LowPC;
+        }
+        AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
+      }
+    } else
+      llvm::consumeError(DIERangesOrError.takeError());
+  }
+  // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to
+  // simplify the logic to update AddrDieMap. The child's range will always
+  // be equal or smaller than the parent's range. With this assumption, when
+  // adding one range into the map, it will at most split a range into 3
+  // sub-ranges.
+  for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling())
+    updateAddressDieMap(Child);
+}
+
+DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
+  extractDIEsIfNeeded(false);
+  if (AddrDieMap.empty())
+    updateAddressDieMap(getUnitDIE());
+  auto R = AddrDieMap.upper_bound(Address);
+  if (R == AddrDieMap.begin())
+    return DWARFDie();
+  // upper_bound's previous item contains Address.
+  --R;
+  if (Address >= R->second.first)
+    return DWARFDie();
+  return R->second.second;
+}
+
+void
+DWARFUnit::getInlinedChainForAddress(uint64_t Address,
+                                     SmallVectorImpl<DWARFDie> &InlinedChain) {
+  assert(InlinedChain.empty());
+  // Try to look for subprogram DIEs in the DWO file.
+  parseDWO();
+  // First, find the subroutine that contains the given address (the leaf
+  // of inlined chain).
+  DWARFDie SubroutineDIE =
+      (DWO ? DWO.get() : this)->getSubroutineForAddress(Address);
+
+  if (!SubroutineDIE)
+    return;
+
+  while (!SubroutineDIE.isSubprogramDIE()) {
+    if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
+      InlinedChain.push_back(SubroutineDIE);
+    SubroutineDIE  = SubroutineDIE.getParent();
+  }
+  InlinedChain.push_back(SubroutineDIE);
+}
+
+const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
+                                              DWARFSectionKind Kind) {
+  if (Kind == DW_SECT_INFO)
+    return Context.getCUIndex();
+  assert(Kind == DW_SECT_TYPES);
+  return Context.getTUIndex();
+}
+
+DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
+  if (!Die)
+    return DWARFDie();
+  const uint32_t Depth = Die->getDepth();
+  // Unit DIEs always have a depth of zero and never have parents.
+  if (Depth == 0)
+    return DWARFDie();
+  // Depth of 1 always means parent is the compile/type unit.
+  if (Depth == 1)
+    return getUnitDIE();
+  // Look for previous DIE with a depth that is one less than the Die's depth.
+  const uint32_t ParentDepth = Depth - 1;
+  for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) {
+    if (DieArray[I].getDepth() == ParentDepth)
+      return DWARFDie(this, &DieArray[I]);
+  }
+  return DWARFDie();
+}
+
+DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
+  if (!Die)
+    return DWARFDie();
+  uint32_t Depth = Die->getDepth();
+  // Unit DIEs always have a depth of zero and never have siblings.
+  if (Depth == 0)
+    return DWARFDie();
+  // NULL DIEs don't have siblings.
+  if (Die->getAbbreviationDeclarationPtr() == nullptr)
+    return DWARFDie();
+
+  // Find the next DIE whose depth is the same as the Die's depth.
+  for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx;
+       ++I) {
+    if (DieArray[I].getDepth() == Depth)
+      return DWARFDie(this, &DieArray[I]);
+  }
+  return DWARFDie();
+}
+
+DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
+  if (!Die)
+    return DWARFDie();
+  uint32_t Depth = Die->getDepth();
+  // Unit DIEs always have a depth of zero and never have siblings.
+  if (Depth == 0)
+    return DWARFDie();
+
+  // Find the previous DIE whose depth is the same as the Die's depth.
+  for (size_t I = getDIEIndex(Die); I > 0;) {
+    --I;
+    if (DieArray[I].getDepth() == Depth - 1)
+      return DWARFDie();
+    if (DieArray[I].getDepth() == Depth)
+      return DWARFDie(this, &DieArray[I]);
+  }
+  return DWARFDie();
+}
+
+DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) {
+  if (!Die->hasChildren())
+    return DWARFDie();
+
+  // We do not want access out of bounds when parsing corrupted debug data.
+  size_t I = getDIEIndex(Die) + 1;
+  if (I >= DieArray.size())
+    return DWARFDie();
+  return DWARFDie(this, &DieArray[I]);
+}
+
+DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
+  if (!Die->hasChildren())
+    return DWARFDie();
+
+  uint32_t Depth = Die->getDepth();
+  for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx;
+       ++I) {
+    if (DieArray[I].getDepth() == Depth + 1 &&
+        DieArray[I].getTag() == dwarf::DW_TAG_null)
+      return DWARFDie(this, &DieArray[I]);
+    assert(DieArray[I].getDepth() > Depth && "Not processing children?");
+  }
+  return DWARFDie();
+}
+
+const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
+  if (!Abbrevs)
+    Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset());
+  return Abbrevs;
+}
+
+llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() {
+  if (BaseAddr)
+    return BaseAddr;
+
+  DWARFDie UnitDie = getUnitDIE();
+  Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
+  BaseAddr = toSectionedAddress(PC);
+  return BaseAddr;
+}
+
+Optional<StrOffsetsContributionDescriptor>
+StrOffsetsContributionDescriptor::validateContributionSize(
+    DWARFDataExtractor &DA) {
+  uint8_t EntrySize = getDwarfOffsetByteSize();
+  // In order to ensure that we don't read a partial record at the end of
+  // the section we validate for a multiple of the entry size.
+  uint64_t ValidationSize = alignTo(Size, EntrySize);
+  // Guard against overflow.
+  if (ValidationSize >= Size)
+    if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
+      return *this;
+  return None;
+}
+
+// Look for a DWARF64-formatted contribution to the string offsets table
+// starting at a given offset and record it in a descriptor.
+static Optional<StrOffsetsContributionDescriptor>
+parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+  if (!DA.isValidOffsetForDataOfSize(Offset, 16))
+    return None;
+
+  if (DA.getU32(&Offset) != 0xffffffff)
+    return None;
+
+  uint64_t Size = DA.getU64(&Offset);
+  uint8_t Version = DA.getU16(&Offset);
+  (void)DA.getU16(&Offset); // padding
+  // The encoded length includes the 2-byte version field and the 2-byte
+  // padding, so we need to subtract them out when we populate the descriptor.
+  return {{Offset, Size - 4, Version, DWARF64}};
+}
+
+// Look for a DWARF32-formatted contribution to the string offsets table
+// starting at a given offset and record it in a descriptor.
+static Optional<StrOffsetsContributionDescriptor>
+parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
+  if (!DA.isValidOffsetForDataOfSize(Offset, 8))
+    return None;
+  uint32_t ContributionSize = DA.getU32(&Offset);
+  if (ContributionSize >= 0xfffffff0)
+    return None;
+  uint8_t Version = DA.getU16(&Offset);
+  (void)DA.getU16(&Offset); // padding
+  // The encoded length includes the 2-byte version field and the 2-byte
+  // padding, so we need to subtract them out when we populate the descriptor.
+  return {{Offset, ContributionSize - 4, Version, DWARF32}};
+}
+
+Optional<StrOffsetsContributionDescriptor>
+DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
+  auto Offset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base), 0);
+  Optional<StrOffsetsContributionDescriptor> Descriptor;
+  // Attempt to find a DWARF64 contribution 16 bytes before the base.
+  if (Offset >= 16)
+    Descriptor =
+        parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16);
+  // Try to find a DWARF32 contribution 8 bytes before the base.
+  if (!Descriptor && Offset >= 8)
+    Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8);
+  return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
+}
+
+Optional<StrOffsetsContributionDescriptor>
+DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) {
+  uint64_t Offset = 0;
+  auto IndexEntry = Header.getIndexEntry();
+  const auto *C =
+      IndexEntry ? IndexEntry->getOffset(DW_SECT_STR_OFFSETS) : nullptr;
+  if (C)
+    Offset = C->Offset;
+  if (getVersion() >= 5) {
+    // Look for a valid contribution at the given offset.
+    auto Descriptor =
+        parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset);
+    if (!Descriptor)
+      Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset);
+    return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
+  }
+  // Prior to DWARF v5, we derive the contribution size from the
+  // index table (in a package file). In a .dwo file it is simply
+  // the length of the string offsets section.
+  if (!IndexEntry)
+    return {{0, StringOffsetSection.Data.size(), 4, DWARF32}};
+  if (C)
+    return {{C->Offset, C->Length, 4, DWARF32}};
+  return None;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
new file mode 100644
index 0000000..84b6c4b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
@@ -0,0 +1,202 @@
+//===- DWARFUnitIndex.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cinttypes>
+#include <cstdint>
+
+using namespace llvm;
+
+bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
+                                   uint32_t *OffsetPtr) {
+  if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
+    return false;
+  Version = IndexData.getU32(OffsetPtr);
+  NumColumns = IndexData.getU32(OffsetPtr);
+  NumUnits = IndexData.getU32(OffsetPtr);
+  NumBuckets = IndexData.getU32(OffsetPtr);
+  return Version <= 2;
+}
+
+void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
+  OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
+}
+
+bool DWARFUnitIndex::parse(DataExtractor IndexData) {
+  bool b = parseImpl(IndexData);
+  if (!b) {
+    // Make sure we don't try to dump anything
+    Header.NumBuckets = 0;
+    // Release any partially initialized data.
+    ColumnKinds.reset();
+    Rows.reset();
+  }
+  return b;
+}
+
+bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
+  uint32_t Offset = 0;
+  if (!Header.parse(IndexData, &Offset))
+    return false;
+
+  if (!IndexData.isValidOffsetForDataOfSize(
+          Offset, Header.NumBuckets * (8 + 4) +
+                      (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
+    return false;
+
+  Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
+  auto Contribs =
+      llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
+  ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
+
+  // Read Hash Table of Signatures
+  for (unsigned i = 0; i != Header.NumBuckets; ++i)
+    Rows[i].Signature = IndexData.getU64(&Offset);
+
+  // Read Parallel Table of Indexes
+  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
+    auto Index = IndexData.getU32(&Offset);
+    if (!Index)
+      continue;
+    Rows[i].Index = this;
+    Rows[i].Contributions =
+        llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
+    Contribs[Index - 1] = Rows[i].Contributions.get();
+  }
+
+  // Read the Column Headers
+  for (unsigned i = 0; i != Header.NumColumns; ++i) {
+    ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
+    if (ColumnKinds[i] == InfoColumnKind) {
+      if (InfoColumn != -1)
+        return false;
+      InfoColumn = i;
+    }
+  }
+
+  if (InfoColumn == -1)
+    return false;
+
+  // Read Table of Section Offsets
+  for (unsigned i = 0; i != Header.NumUnits; ++i) {
+    auto *Contrib = Contribs[i];
+    for (unsigned i = 0; i != Header.NumColumns; ++i)
+      Contrib[i].Offset = IndexData.getU32(&Offset);
+  }
+
+  // Read Table of Section Sizes
+  for (unsigned i = 0; i != Header.NumUnits; ++i) {
+    auto *Contrib = Contribs[i];
+    for (unsigned i = 0; i != Header.NumColumns; ++i)
+      Contrib[i].Length = IndexData.getU32(&Offset);
+  }
+
+  return true;
+}
+
+StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
+#define CASE(DS)                                                               \
+  case DW_SECT_##DS:                                                           \
+    return #DS;
+  switch (DS) {
+    CASE(INFO);
+    CASE(TYPES);
+    CASE(ABBREV);
+    CASE(LINE);
+    CASE(LOC);
+    CASE(STR_OFFSETS);
+    CASE(MACINFO);
+    CASE(MACRO);
+  }
+  llvm_unreachable("unknown DWARFSectionKind");
+}
+
+void DWARFUnitIndex::dump(raw_ostream &OS) const {
+  if (!*this)
+    return;
+
+  Header.dump(OS);
+  OS << "Index Signature         ";
+  for (unsigned i = 0; i != Header.NumColumns; ++i)
+    OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
+  OS << "\n----- ------------------";
+  for (unsigned i = 0; i != Header.NumColumns; ++i)
+    OS << " ------------------------";
+  OS << '\n';
+  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
+    auto &Row = Rows[i];
+    if (auto *Contribs = Row.Contributions.get()) {
+      OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
+      for (unsigned i = 0; i != Header.NumColumns; ++i) {
+        auto &Contrib = Contribs[i];
+        OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
+                     Contrib.Offset + Contrib.Length);
+      }
+      OS << '\n';
+    }
+  }
+}
+
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
+  uint32_t i = 0;
+  for (; i != Index->Header.NumColumns; ++i)
+    if (Index->ColumnKinds[i] == Sec)
+      return &Contributions[i];
+  return nullptr;
+}
+
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset() const {
+  return &Contributions[Index->InfoColumn];
+}
+
+const DWARFUnitIndex::Entry *
+DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
+  if (OffsetLookup.empty()) {
+    for (uint32_t i = 0; i != Header.NumBuckets; ++i)
+      if (Rows[i].Contributions)
+        OffsetLookup.push_back(&Rows[i]);
+    llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
+      return E1->Contributions[InfoColumn].Offset <
+             E2->Contributions[InfoColumn].Offset;
+    });
+  }
+  auto I =
+      llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) {
+        return Offset < E2->Contributions[InfoColumn].Offset;
+      });
+  if (I == OffsetLookup.begin())
+    return nullptr;
+  --I;
+  const auto *E = *I;
+  const auto &InfoContrib = E->Contributions[InfoColumn];
+  if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
+    return nullptr;
+  return E;
+}
+
+const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
+  uint64_t Mask = Header.NumBuckets - 1;
+
+  auto H = S & Mask;
+  auto HP = ((S >> 32) & Mask) | 1;
+  while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
+    H = (H + HP) & Mask;
+
+  if (Rows[H].getSignature() != S)
+    return nullptr;
+
+  return &Rows[H];
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
new file mode 100644
index 0000000..f837017
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -0,0 +1,1514 @@
+//===- DWARFVerifier.cpp --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <set>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+DWARFVerifier::DieRangeInfo::address_range_iterator
+DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
+  auto Begin = Ranges.begin();
+  auto End = Ranges.end();
+  auto Pos = std::lower_bound(Begin, End, R);
+
+  if (Pos != End) {
+    if (Pos->intersects(R))
+      return Pos;
+    if (Pos != Begin) {
+      auto Iter = Pos - 1;
+      if (Iter->intersects(R))
+        return Iter;
+    }
+  }
+
+  Ranges.insert(Pos, R);
+  return Ranges.end();
+}
+
+DWARFVerifier::DieRangeInfo::die_range_info_iterator
+DWARFVerifier::DieRangeInfo::insert(const DieRangeInfo &RI) {
+  auto End = Children.end();
+  auto Iter = Children.begin();
+  while (Iter != End) {
+    if (Iter->intersects(RI))
+      return Iter;
+    ++Iter;
+  }
+  Children.insert(RI);
+  return Children.end();
+}
+
+bool DWARFVerifier::DieRangeInfo::contains(const DieRangeInfo &RHS) const {
+  // Both list of ranges are sorted so we can make this fast.
+
+  if (Ranges.empty() || RHS.Ranges.empty())
+    return false;
+
+  // Since the ranges are sorted we can advance where we start searching with
+  // this object's ranges as we traverse RHS.Ranges.
+  auto End = Ranges.end();
+  auto Iter = findRange(RHS.Ranges.front());
+
+  // Now linearly walk the ranges in this object and see if they contain each
+  // ranges from RHS.Ranges.
+  for (const auto &R : RHS.Ranges) {
+    while (Iter != End) {
+      if (Iter->contains(R))
+        break;
+      ++Iter;
+    }
+    if (Iter == End)
+      return false;
+  }
+  return true;
+}
+
+bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const {
+  if (Ranges.empty() || RHS.Ranges.empty())
+    return false;
+
+  auto End = Ranges.end();
+  auto Iter = findRange(RHS.Ranges.front());
+  for (const auto &R : RHS.Ranges) {
+    if (Iter == End)
+      return false;
+    if (R.HighPC <= Iter->LowPC)
+      continue;
+    while (Iter != End) {
+      if (Iter->intersects(R))
+        return true;
+      ++Iter;
+    }
+  }
+
+  return false;
+}
+
+bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
+                                     uint32_t *Offset, unsigned UnitIndex,
+                                     uint8_t &UnitType, bool &isUnitDWARF64) {
+  uint32_t AbbrOffset, Length;
+  uint8_t AddrSize = 0;
+  uint16_t Version;
+  bool Success = true;
+
+  bool ValidLength = false;
+  bool ValidVersion = false;
+  bool ValidAddrSize = false;
+  bool ValidType = true;
+  bool ValidAbbrevOffset = true;
+
+  uint32_t OffsetStart = *Offset;
+  Length = DebugInfoData.getU32(Offset);
+  if (Length == UINT32_MAX) {
+    isUnitDWARF64 = true;
+    OS << format(
+        "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
+        UnitIndex);
+    return false;
+  }
+  Version = DebugInfoData.getU16(Offset);
+
+  if (Version >= 5) {
+    UnitType = DebugInfoData.getU8(Offset);
+    AddrSize = DebugInfoData.getU8(Offset);
+    AbbrOffset = DebugInfoData.getU32(Offset);
+    ValidType = dwarf::isUnitType(UnitType);
+  } else {
+    UnitType = 0;
+    AbbrOffset = DebugInfoData.getU32(Offset);
+    AddrSize = DebugInfoData.getU8(Offset);
+  }
+
+  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
+    ValidAbbrevOffset = false;
+
+  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
+  ValidVersion = DWARFContext::isSupportedVersion(Version);
+  ValidAddrSize = AddrSize == 4 || AddrSize == 8;
+  if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
+      !ValidType) {
+    Success = false;
+    error() << format("Units[%d] - start offset: 0x%08x \n", UnitIndex,
+                      OffsetStart);
+    if (!ValidLength)
+      note() << "The length for this unit is too "
+                "large for the .debug_info provided.\n";
+    if (!ValidVersion)
+      note() << "The 16 bit unit header version is not valid.\n";
+    if (!ValidType)
+      note() << "The unit type encoding is not valid.\n";
+    if (!ValidAbbrevOffset)
+      note() << "The offset into the .debug_abbrev section is "
+                "not valid.\n";
+    if (!ValidAddrSize)
+      note() << "The address size is unsupported.\n";
+  }
+  *Offset = OffsetStart + Length + 4;
+  return Success;
+}
+
+unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) {
+  unsigned NumUnitErrors = 0;
+  unsigned NumDies = Unit.getNumDIEs();
+  for (unsigned I = 0; I < NumDies; ++I) {
+    auto Die = Unit.getDIEAtIndex(I);
+
+    if (Die.getTag() == DW_TAG_null)
+      continue;
+
+    bool HasTypeAttr = false;
+    for (auto AttrValue : Die.attributes()) {
+      NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
+      NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
+      HasTypeAttr |= (AttrValue.Attr == DW_AT_type);
+    }
+
+    if (!HasTypeAttr && (Die.getTag() == DW_TAG_formal_parameter ||
+                         Die.getTag() == DW_TAG_variable ||
+                         Die.getTag() == DW_TAG_array_type)) {
+      error() << "DIE with tag " << TagString(Die.getTag())
+              << " is missing type attribute:\n";
+      dump(Die) << '\n';
+      NumUnitErrors++;
+    }
+    NumUnitErrors += verifyDebugInfoCallSite(Die);
+  }
+
+  DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
+  if (!Die) {
+    error() << "Compilation unit without DIE.\n";
+    NumUnitErrors++;
+    return NumUnitErrors;
+  }
+
+  if (!dwarf::isUnitType(Die.getTag())) {
+    error() << "Compilation unit root DIE is not a unit DIE: "
+            << dwarf::TagString(Die.getTag()) << ".\n";
+    NumUnitErrors++;
+  }
+
+  uint8_t UnitType = Unit.getUnitType();
+  if (!DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) {
+    error() << "Compilation unit type (" << dwarf::UnitTypeString(UnitType)
+            << ") and root DIE (" << dwarf::TagString(Die.getTag())
+            << ") do not match.\n";
+    NumUnitErrors++;
+  }
+
+  DieRangeInfo RI;
+  NumUnitErrors += verifyDieRanges(Die, RI);
+
+  return NumUnitErrors;
+}
+
+unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
+  if (Die.getTag() != DW_TAG_call_site)
+    return 0;
+
+  DWARFDie Curr = Die.getParent();
+  for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) {
+    if (Curr.getTag() == DW_TAG_inlined_subroutine) {
+      error() << "Call site entry nested within inlined subroutine:";
+      Curr.dump(OS);
+      return 1;
+    }
+  }
+
+  if (!Curr.isValid()) {
+    error() << "Call site entry not nested within a valid subprogram:";
+    Die.dump(OS);
+    return 1;
+  }
+
+  Optional<DWARFFormValue> CallAttr =
+      Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
+                 DW_AT_call_all_tail_calls});
+  if (!CallAttr) {
+    error() << "Subprogram with call site entry has no DW_AT_call attribute:";
+    Curr.dump(OS);
+    Die.dump(OS, /*indent*/ 1);
+    return 1;
+  }
+
+  return 0;
+}
+
+unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
+  unsigned NumErrors = 0;
+  if (Abbrev) {
+    const DWARFAbbreviationDeclarationSet *AbbrDecls =
+        Abbrev->getAbbreviationDeclarationSet(0);
+    for (auto AbbrDecl : *AbbrDecls) {
+      SmallDenseSet<uint16_t> AttributeSet;
+      for (auto Attribute : AbbrDecl.attributes()) {
+        auto Result = AttributeSet.insert(Attribute.Attr);
+        if (!Result.second) {
+          error() << "Abbreviation declaration contains multiple "
+                  << AttributeString(Attribute.Attr) << " attributes.\n";
+          AbbrDecl.dump(OS);
+          ++NumErrors;
+        }
+      }
+    }
+  }
+  return NumErrors;
+}
+
+bool DWARFVerifier::handleDebugAbbrev() {
+  OS << "Verifying .debug_abbrev...\n";
+
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  bool noDebugAbbrev = DObj.getAbbrevSection().empty();
+  bool noDebugAbbrevDWO = DObj.getAbbrevDWOSection().empty();
+
+  if (noDebugAbbrev && noDebugAbbrevDWO) {
+    return true;
+  }
+
+  unsigned NumErrors = 0;
+  if (!noDebugAbbrev)
+    NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
+
+  if (!noDebugAbbrevDWO)
+    NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
+  return NumErrors == 0;
+}
+
+unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S,
+                                          DWARFSectionKind SectionKind) {
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
+  unsigned NumDebugInfoErrors = 0;
+  uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
+  uint8_t UnitType = 0;
+  bool isUnitDWARF64 = false;
+  bool isHeaderChainValid = true;
+  bool hasDIE = DebugInfoData.isValidOffset(Offset);
+  DWARFUnitVector TypeUnitVector;
+  DWARFUnitVector CompileUnitVector;
+  while (hasDIE) {
+    OffsetStart = Offset;
+    if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
+                          isUnitDWARF64)) {
+      isHeaderChainValid = false;
+      if (isUnitDWARF64)
+        break;
+    } else {
+      DWARFUnitHeader Header;
+      Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind);
+      DWARFUnit *Unit;
+      switch (UnitType) {
+      case dwarf::DW_UT_type:
+      case dwarf::DW_UT_split_type: {
+        Unit = TypeUnitVector.addUnit(llvm::make_unique<DWARFTypeUnit>(
+            DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
+            &DObj.getLocSection(), DObj.getStringSection(),
+            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
+            DObj.getLineSection(), DCtx.isLittleEndian(), false,
+            TypeUnitVector));
+        break;
+      }
+      case dwarf::DW_UT_skeleton:
+      case dwarf::DW_UT_split_compile:
+      case dwarf::DW_UT_compile:
+      case dwarf::DW_UT_partial:
+      // UnitType = 0 means that we are verifying a compile unit in DWARF v4.
+      case 0: {
+        Unit = CompileUnitVector.addUnit(llvm::make_unique<DWARFCompileUnit>(
+            DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
+            &DObj.getLocSection(), DObj.getStringSection(),
+            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
+            DObj.getLineSection(), DCtx.isLittleEndian(), false,
+            CompileUnitVector));
+        break;
+      }
+      default: { llvm_unreachable("Invalid UnitType."); }
+      }
+      NumDebugInfoErrors += verifyUnitContents(*Unit);
+    }
+    hasDIE = DebugInfoData.isValidOffset(Offset);
+    ++UnitIdx;
+  }
+  if (UnitIdx == 0 && !hasDIE) {
+    warn() << "Section is empty.\n";
+    isHeaderChainValid = true;
+  }
+  if (!isHeaderChainValid)
+    ++NumDebugInfoErrors;
+  NumDebugInfoErrors += verifyDebugInfoReferences();
+  return NumDebugInfoErrors;
+}
+
+bool DWARFVerifier::handleDebugInfo() {
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  unsigned NumErrors = 0;
+
+  OS << "Verifying .debug_info Unit Header Chain...\n";
+  DObj.forEachInfoSections([&](const DWARFSection &S) {
+    NumErrors += verifyUnitSection(S, DW_SECT_INFO);
+  });
+
+  OS << "Verifying .debug_types Unit Header Chain...\n";
+  DObj.forEachTypesSections([&](const DWARFSection &S) {
+    NumErrors += verifyUnitSection(S, DW_SECT_TYPES);
+  });
+  return NumErrors == 0;
+}
+
+unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
+                                        DieRangeInfo &ParentRI) {
+  unsigned NumErrors = 0;
+
+  if (!Die.isValid())
+    return NumErrors;
+
+  auto RangesOrError = Die.getAddressRanges();
+  if (!RangesOrError) {
+    // FIXME: Report the error.
+    ++NumErrors;
+    llvm::consumeError(RangesOrError.takeError());
+    return NumErrors;
+  }
+
+  DWARFAddressRangesVector Ranges = RangesOrError.get();
+  // Build RI for this DIE and check that ranges within this DIE do not
+  // overlap.
+  DieRangeInfo RI(Die);
+
+  // TODO support object files better
+  //
+  // Some object file formats (i.e. non-MachO) support COMDAT.  ELF in
+  // particular does so by placing each function into a section.  The DWARF data
+  // for the function at that point uses a section relative DW_FORM_addrp for
+  // the DW_AT_low_pc and a DW_FORM_data4 for the offset as the DW_AT_high_pc.
+  // In such a case, when the Die is the CU, the ranges will overlap, and we
+  // will flag valid conflicting ranges as invalid.
+  //
+  // For such targets, we should read the ranges from the CU and partition them
+  // by the section id.  The ranges within a particular section should be
+  // disjoint, although the ranges across sections may overlap.  We would map
+  // the child die to the entity that it references and the section with which
+  // it is associated.  The child would then be checked against the range
+  // information for the associated section.
+  //
+  // For now, simply elide the range verification for the CU DIEs if we are
+  // processing an object file.
+
+  if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) {
+    for (auto Range : Ranges) {
+      if (!Range.valid()) {
+        ++NumErrors;
+        error() << "Invalid address range " << Range << "\n";
+        continue;
+      }
+
+      // Verify that ranges don't intersect.
+      const auto IntersectingRange = RI.insert(Range);
+      if (IntersectingRange != RI.Ranges.end()) {
+        ++NumErrors;
+        error() << "DIE has overlapping address ranges: " << Range << " and "
+                << *IntersectingRange << "\n";
+        break;
+      }
+    }
+  }
+
+  // Verify that children don't intersect.
+  const auto IntersectingChild = ParentRI.insert(RI);
+  if (IntersectingChild != ParentRI.Children.end()) {
+    ++NumErrors;
+    error() << "DIEs have overlapping address ranges:";
+    dump(Die);
+    dump(IntersectingChild->Die) << '\n';
+  }
+
+  // Verify that ranges are contained within their parent.
+  bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
+                           !(Die.getTag() == DW_TAG_subprogram &&
+                             ParentRI.Die.getTag() == DW_TAG_subprogram);
+  if (ShouldBeContained && !ParentRI.contains(RI)) {
+    ++NumErrors;
+    error() << "DIE address ranges are not contained in its parent's ranges:";
+    dump(ParentRI.Die);
+    dump(Die, 2) << '\n';
+  }
+
+  // Recursively check children.
+  for (DWARFDie Child : Die)
+    NumErrors += verifyDieRanges(Child, RI);
+
+  return NumErrors;
+}
+
+unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
+                                                 DWARFAttribute &AttrValue) {
+  unsigned NumErrors = 0;
+  auto ReportError = [&](const Twine &TitleMsg) {
+    ++NumErrors;
+    error() << TitleMsg << '\n';
+    dump(Die) << '\n';
+  };
+
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  const auto Attr = AttrValue.Attr;
+  switch (Attr) {
+  case DW_AT_ranges:
+    // Make sure the offset in the DW_AT_ranges attribute is valid.
+    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+      if (*SectionOffset >= DObj.getRangeSection().Data.size())
+        ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
+      break;
+    }
+    ReportError("DIE has invalid DW_AT_ranges encoding:");
+    break;
+  case DW_AT_stmt_list:
+    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
+    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
+      if (*SectionOffset >= DObj.getLineSection().Data.size())
+        ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
+                    llvm::formatv("{0:x8}", *SectionOffset));
+      break;
+    }
+    ReportError("DIE has invalid DW_AT_stmt_list encoding:");
+    break;
+  case DW_AT_location: {
+    auto VerifyLocationExpr = [&](StringRef D) {
+      DWARFUnit *U = Die.getDwarfUnit();
+      DataExtractor Data(D, DCtx.isLittleEndian(), 0);
+      DWARFExpression Expression(Data, U->getVersion(),
+                                 U->getAddressByteSize());
+      bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
+        return Op.isError();
+      });
+      if (Error)
+        ReportError("DIE contains invalid DWARF expression:");
+    };
+    if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) {
+      // Verify inlined location.
+      VerifyLocationExpr(llvm::toStringRef(*Expr));
+    } else if (auto LocOffset = AttrValue.Value.getAsSectionOffset()) {
+      // Verify location list.
+      if (auto DebugLoc = DCtx.getDebugLoc())
+        if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset))
+          for (const auto &Entry : LocList->Entries)
+            VerifyLocationExpr({Entry.Loc.data(), Entry.Loc.size()});
+    }
+    break;
+  }
+  case DW_AT_specification:
+  case DW_AT_abstract_origin: {
+    if (auto ReferencedDie = Die.getAttributeValueAsReferencedDie(Attr)) {
+      auto DieTag = Die.getTag();
+      auto RefTag = ReferencedDie.getTag();
+      if (DieTag == RefTag)
+        break;
+      if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
+        break;
+      if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
+        break;
+      ReportError("DIE with tag " + TagString(DieTag) + " has " +
+                  AttributeString(Attr) +
+                  " that points to DIE with "
+                  "incompatible tag " +
+                  TagString(RefTag));
+    }
+    break;
+  }
+  case DW_AT_type: {
+    DWARFDie TypeDie = Die.getAttributeValueAsReferencedDie(DW_AT_type);
+    if (TypeDie && !isType(TypeDie.getTag())) {
+      ReportError("DIE has " + AttributeString(Attr) +
+                  " with incompatible tag " + TagString(TypeDie.getTag()));
+    }
+    break;
+  }
+  default:
+    break;
+  }
+  return NumErrors;
+}
+
+unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
+                                            DWARFAttribute &AttrValue) {
+  const DWARFObject &DObj = DCtx.getDWARFObj();
+  auto DieCU = Die.getDwarfUnit();
+  unsigned NumErrors = 0;
+  const auto Form = AttrValue.Value.getForm();
+  switch (Form) {
+  case DW_FORM_ref1:
+  case DW_FORM_ref2:
+  case DW_FORM_ref4:
+  case DW_FORM_ref8:
+  case DW_FORM_ref_udata: {
+    // Verify all CU relative references are valid CU offsets.
+    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+    assert(RefVal);
+    if (RefVal) {
+      auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
+      auto CUOffset = AttrValue.Value.getRawUValue();
+      if (CUOffset >= CUSize) {
+        ++NumErrors;
+        error() << FormEncodingString(Form) << " CU offset "
+                << format("0x%08" PRIx64, CUOffset)
+                << " is invalid (must be less than CU size of "
+                << format("0x%08" PRIx32, CUSize) << "):\n";
+        Die.dump(OS, 0, DumpOpts);
+        dump(Die) << '\n';
+      } else {
+        // Valid reference, but we will verify it points to an actual
+        // DIE later.
+        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+      }
+    }
+    break;
+  }
+  case DW_FORM_ref_addr: {
+    // Verify all absolute DIE references have valid offsets in the
+    // .debug_info section.
+    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
+    assert(RefVal);
+    if (RefVal) {
+      if (*RefVal >= DieCU->getInfoSection().Data.size()) {
+        ++NumErrors;
+        error() << "DW_FORM_ref_addr offset beyond .debug_info "
+                   "bounds:\n";
+        dump(Die) << '\n';
+      } else {
+        // Valid reference, but we will verify it points to an actual
+        // DIE later.
+        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
+      }
+    }
+    break;
+  }
+  case DW_FORM_strp: {
+    auto SecOffset = AttrValue.Value.getAsSectionOffset();
+    assert(SecOffset); // DW_FORM_strp is a section offset.
+    if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
+      ++NumErrors;
+      error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
+      dump(Die) << '\n';
+    }
+    break;
+  }
+  case DW_FORM_strx:
+  case DW_FORM_strx1:
+  case DW_FORM_strx2:
+  case DW_FORM_strx3:
+  case DW_FORM_strx4: {
+    auto Index = AttrValue.Value.getRawUValue();
+    auto DieCU = Die.getDwarfUnit();
+    // Check that we have a valid DWARF v5 string offsets table.
+    if (!DieCU->getStringOffsetsTableContribution()) {
+      ++NumErrors;
+      error() << FormEncodingString(Form)
+              << " used without a valid string offsets table:\n";
+      dump(Die) << '\n';
+      break;
+    }
+    // Check that the index is within the bounds of the section. 
+    unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize();
+    // Use a 64-bit type to calculate the offset to guard against overflow.
+    uint64_t Offset =
+        (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize;
+    if (DObj.getStringOffsetSection().Data.size() < Offset + ItemSize) {
+      ++NumErrors;
+      error() << FormEncodingString(Form) << " uses index "
+              << format("%" PRIu64, Index) << ", which is too large:\n";
+      dump(Die) << '\n';
+      break;
+    }
+    // Check that the string offset is valid.
+    uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index);
+    if (StringOffset >= DObj.getStringSection().size()) {
+      ++NumErrors;
+      error() << FormEncodingString(Form) << " uses index "
+              << format("%" PRIu64, Index)
+              << ", but the referenced string"
+                 " offset is beyond .debug_str bounds:\n";
+      dump(Die) << '\n';
+    }
+    break;
+  }
+  default:
+    break;
+  }
+  return NumErrors;
+}
+
+unsigned DWARFVerifier::verifyDebugInfoReferences() {
+  // Take all references and make sure they point to an actual DIE by
+  // getting the DIE by offset and emitting an error
+  OS << "Verifying .debug_info references...\n";
+  unsigned NumErrors = 0;
+  for (auto Pair : ReferenceToDIEOffsets) {
+    auto Die = DCtx.getDIEForOffset(Pair.first);
+    if (Die)
+      continue;
+    ++NumErrors;
+    error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
+            << ". Offset is in between DIEs:\n";
+    for (auto Offset : Pair.second)
+      dump(DCtx.getDIEForOffset(Offset)) << '\n';
+    OS << "\n";
+  }
+  return NumErrors;
+}
+
+void DWARFVerifier::verifyDebugLineStmtOffsets() {
+  std::map<uint64_t, DWARFDie> StmtListToDie;
+  for (const auto &CU : DCtx.compile_units()) {
+    auto Die = CU->getUnitDIE();
+    // Get the attribute value as a section offset. No need to produce an
+    // error here if the encoding isn't correct because we validate this in
+    // the .debug_info verifier.
+    auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
+    if (!StmtSectionOffset)
+      continue;
+    const uint32_t LineTableOffset = *StmtSectionOffset;
+    auto LineTable = DCtx.getLineTableForUnit(CU.get());
+    if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
+      if (!LineTable) {
+        ++NumDebugLineErrors;
+        error() << ".debug_line[" << format("0x%08" PRIx32, LineTableOffset)
+                << "] was not able to be parsed for CU:\n";
+        dump(Die) << '\n';
+        continue;
+      }
+    } else {
+      // Make sure we don't get a valid line table back if the offset is wrong.
+      assert(LineTable == nullptr);
+      // Skip this line table as it isn't valid. No need to create an error
+      // here because we validate this in the .debug_info verifier.
+      continue;
+    }
+    auto Iter = StmtListToDie.find(LineTableOffset);
+    if (Iter != StmtListToDie.end()) {
+      ++NumDebugLineErrors;
+      error() << "two compile unit DIEs, "
+              << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
+              << format("0x%08" PRIx32, Die.getOffset())
+              << ", have the same DW_AT_stmt_list section offset:\n";
+      dump(Iter->second);
+      dump(Die) << '\n';
+      // Already verified this line table before, no need to do it again.
+      continue;
+    }
+    StmtListToDie[LineTableOffset] = Die;
+  }
+}
+
+void DWARFVerifier::verifyDebugLineRows() {
+  for (const auto &CU : DCtx.compile_units()) {
+    auto Die = CU->getUnitDIE();
+    auto LineTable = DCtx.getLineTableForUnit(CU.get());
+    // If there is no line table we will have created an error in the
+    // .debug_info verifier or in verifyDebugLineStmtOffsets().
+    if (!LineTable)
+      continue;
+
+    // Verify prologue.
+    uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
+    uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
+    uint32_t FileIndex = 1;
+    StringMap<uint16_t> FullPathMap;
+    for (const auto &FileName : LineTable->Prologue.FileNames) {
+      // Verify directory index.
+      if (FileName.DirIdx > MaxDirIndex) {
+        ++NumDebugLineErrors;
+        error() << ".debug_line["
+                << format("0x%08" PRIx64,
+                          *toSectionOffset(Die.find(DW_AT_stmt_list)))
+                << "].prologue.file_names[" << FileIndex
+                << "].dir_idx contains an invalid index: " << FileName.DirIdx
+                << "\n";
+      }
+
+      // Check file paths for duplicates.
+      std::string FullPath;
+      const bool HasFullPath = LineTable->getFileNameByIndex(
+          FileIndex, CU->getCompilationDir(),
+          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
+      assert(HasFullPath && "Invalid index?");
+      (void)HasFullPath;
+      auto It = FullPathMap.find(FullPath);
+      if (It == FullPathMap.end())
+        FullPathMap[FullPath] = FileIndex;
+      else if (It->second != FileIndex) {
+        warn() << ".debug_line["
+               << format("0x%08" PRIx64,
+                         *toSectionOffset(Die.find(DW_AT_stmt_list)))
+               << "].prologue.file_names[" << FileIndex
+               << "] is a duplicate of file_names[" << It->second << "]\n";
+      }
+
+      FileIndex++;
+    }
+
+    // Verify rows.
+    uint64_t PrevAddress = 0;
+    uint32_t RowIndex = 0;
+    for (const auto &Row : LineTable->Rows) {
+      // Verify row address.
+      if (Row.Address < PrevAddress) {
+        ++NumDebugLineErrors;
+        error() << ".debug_line["
+                << format("0x%08" PRIx64,
+                          *toSectionOffset(Die.find(DW_AT_stmt_list)))
+                << "] row[" << RowIndex
+                << "] decreases in address from previous row:\n";
+
+        DWARFDebugLine::Row::dumpTableHeader(OS);
+        if (RowIndex > 0)
+          LineTable->Rows[RowIndex - 1].dump(OS);
+        Row.dump(OS);
+        OS << '\n';
+      }
+
+      // Verify file index.
+      if (Row.File > MaxFileIndex) {
+        ++NumDebugLineErrors;
+        error() << ".debug_line["
+                << format("0x%08" PRIx64,
+                          *toSectionOffset(Die.find(DW_AT_stmt_list)))
+                << "][" << RowIndex << "] has invalid file index " << Row.File
+                << " (valid values are [1," << MaxFileIndex << "]):\n";
+        DWARFDebugLine::Row::dumpTableHeader(OS);
+        Row.dump(OS);
+        OS << '\n';
+      }
+      if (Row.EndSequence)
+        PrevAddress = 0;
+      else
+        PrevAddress = Row.Address;
+      ++RowIndex;
+    }
+  }
+}
+
+DWARFVerifier::DWARFVerifier(raw_ostream &S, DWARFContext &D,
+                             DIDumpOptions DumpOpts)
+    : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)), IsObjectFile(false),
+      IsMachOObject(false) {
+  if (const auto *F = DCtx.getDWARFObj().getFile()) {
+    IsObjectFile = F->isRelocatableObject();
+    IsMachOObject = F->isMachO();
+  }
+}
+
+bool DWARFVerifier::handleDebugLine() {
+  NumDebugLineErrors = 0;
+  OS << "Verifying .debug_line...\n";
+  verifyDebugLineStmtOffsets();
+  verifyDebugLineRows();
+  return NumDebugLineErrors == 0;
+}
+
+unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
+                                              DataExtractor *StrData,
+                                              const char *SectionName) {
+  unsigned NumErrors = 0;
+  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), *AccelSection,
+                                      DCtx.isLittleEndian(), 0);
+  AppleAcceleratorTable AccelTable(AccelSectionData, *StrData);
+
+  OS << "Verifying " << SectionName << "...\n";
+
+  // Verify that the fixed part of the header is not too short.
+  if (!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())) {
+    error() << "Section is too small to fit a section header.\n";
+    return 1;
+  }
+
+  // Verify that the section is not too short.
+  if (Error E = AccelTable.extract()) {
+    error() << toString(std::move(E)) << '\n';
+    return 1;
+  }
+
+  // Verify that all buckets have a valid hash index or are empty.
+  uint32_t NumBuckets = AccelTable.getNumBuckets();
+  uint32_t NumHashes = AccelTable.getNumHashes();
+
+  uint32_t BucketsOffset =
+      AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
+  uint32_t HashesBase = BucketsOffset + NumBuckets * 4;
+  uint32_t OffsetsBase = HashesBase + NumHashes * 4;
+  for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
+    uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
+    if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
+      error() << format("Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
+                        HashIdx);
+      ++NumErrors;
+    }
+  }
+  uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
+  if (NumAtoms == 0) {
+    error() << "No atoms: failed to read HashData.\n";
+    return 1;
+  }
+  if (!AccelTable.validateForms()) {
+    error() << "Unsupported form: failed to read HashData.\n";
+    return 1;
+  }
+
+  for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
+    uint32_t HashOffset = HashesBase + 4 * HashIdx;
+    uint32_t DataOffset = OffsetsBase + 4 * HashIdx;
+    uint32_t Hash = AccelSectionData.getU32(&HashOffset);
+    uint32_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
+    if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
+                                                     sizeof(uint64_t))) {
+      error() << format("Hash[%d] has invalid HashData offset: 0x%08x.\n",
+                        HashIdx, HashDataOffset);
+      ++NumErrors;
+    }
+
+    uint32_t StrpOffset;
+    uint32_t StringOffset;
+    uint32_t StringCount = 0;
+    unsigned Offset;
+    unsigned Tag;
+    while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
+      const uint32_t NumHashDataObjects =
+          AccelSectionData.getU32(&HashDataOffset);
+      for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
+           ++HashDataIdx) {
+        std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset);
+        auto Die = DCtx.getDIEForOffset(Offset);
+        if (!Die) {
+          const uint32_t BucketIdx =
+              NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
+          StringOffset = StrpOffset;
+          const char *Name = StrData->getCStr(&StringOffset);
+          if (!Name)
+            Name = "<NULL>";
+
+          error() << format(
+              "%s Bucket[%d] Hash[%d] = 0x%08x "
+              "Str[%u] = 0x%08x "
+              "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
+              SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
+              HashDataIdx, Offset, Name);
+
+          ++NumErrors;
+          continue;
+        }
+        if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
+          error() << "Tag " << dwarf::TagString(Tag)
+                  << " in accelerator table does not match Tag "
+                  << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
+                  << "].\n";
+          ++NumErrors;
+        }
+      }
+      ++StringCount;
+    }
+  }
+  return NumErrors;
+}
+
+unsigned
+DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
+  // A map from CU offset to the (first) Name Index offset which claims to index
+  // this CU.
+  DenseMap<uint32_t, uint32_t> CUMap;
+  const uint32_t NotIndexed = std::numeric_limits<uint32_t>::max();
+
+  CUMap.reserve(DCtx.getNumCompileUnits());
+  for (const auto &CU : DCtx.compile_units())
+    CUMap[CU->getOffset()] = NotIndexed;
+
+  unsigned NumErrors = 0;
+  for (const DWARFDebugNames::NameIndex &NI : AccelTable) {
+    if (NI.getCUCount() == 0) {
+      error() << formatv("Name Index @ {0:x} does not index any CU\n",
+                         NI.getUnitOffset());
+      ++NumErrors;
+      continue;
+    }
+    for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) {
+      uint32_t Offset = NI.getCUOffset(CU);
+      auto Iter = CUMap.find(Offset);
+
+      if (Iter == CUMap.end()) {
+        error() << formatv(
+            "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
+            NI.getUnitOffset(), Offset);
+        ++NumErrors;
+        continue;
+      }
+
+      if (Iter->second != NotIndexed) {
+        error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but "
+                           "this CU is already indexed by Name Index @ {2:x}\n",
+                           NI.getUnitOffset(), Offset, Iter->second);
+        continue;
+      }
+      Iter->second = NI.getUnitOffset();
+    }
+  }
+
+  for (const auto &KV : CUMap) {
+    if (KV.second == NotIndexed)
+      warn() << formatv("CU @ {0:x} not covered by any Name Index\n", KV.first);
+  }
+
+  return NumErrors;
+}
+
+unsigned
+DWARFVerifier::verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
+                                      const DataExtractor &StrData) {
+  struct BucketInfo {
+    uint32_t Bucket;
+    uint32_t Index;
+
+    constexpr BucketInfo(uint32_t Bucket, uint32_t Index)
+        : Bucket(Bucket), Index(Index) {}
+    bool operator<(const BucketInfo &RHS) const { return Index < RHS.Index; };
+  };
+
+  uint32_t NumErrors = 0;
+  if (NI.getBucketCount() == 0) {
+    warn() << formatv("Name Index @ {0:x} does not contain a hash table.\n",
+                      NI.getUnitOffset());
+    return NumErrors;
+  }
+
+  // Build up a list of (Bucket, Index) pairs. We use this later to verify that
+  // each Name is reachable from the appropriate bucket.
+  std::vector<BucketInfo> BucketStarts;
+  BucketStarts.reserve(NI.getBucketCount() + 1);
+  for (uint32_t Bucket = 0, End = NI.getBucketCount(); Bucket < End; ++Bucket) {
+    uint32_t Index = NI.getBucketArrayEntry(Bucket);
+    if (Index > NI.getNameCount()) {
+      error() << formatv("Bucket {0} of Name Index @ {1:x} contains invalid "
+                         "value {2}. Valid range is [0, {3}].\n",
+                         Bucket, NI.getUnitOffset(), Index, NI.getNameCount());
+      ++NumErrors;
+      continue;
+    }
+    if (Index > 0)
+      BucketStarts.emplace_back(Bucket, Index);
+  }
+
+  // If there were any buckets with invalid values, skip further checks as they
+  // will likely produce many errors which will only confuse the actual root
+  // problem.
+  if (NumErrors > 0)
+    return NumErrors;
+
+  // Sort the list in the order of increasing "Index" entries.
+  array_pod_sort(BucketStarts.begin(), BucketStarts.end());
+
+  // Insert a sentinel entry at the end, so we can check that the end of the
+  // table is covered in the loop below.
+  BucketStarts.emplace_back(NI.getBucketCount(), NI.getNameCount() + 1);
+
+  // Loop invariant: NextUncovered is the (1-based) index of the first Name
+  // which is not reachable by any of the buckets we processed so far (and
+  // hasn't been reported as uncovered).
+  uint32_t NextUncovered = 1;
+  for (const BucketInfo &B : BucketStarts) {
+    // Under normal circumstances B.Index be equal to NextUncovered, but it can
+    // be less if a bucket points to names which are already known to be in some
+    // bucket we processed earlier. In that case, we won't trigger this error,
+    // but report the mismatched hash value error instead. (We know the hash
+    // will not match because we have already verified that the name's hash
+    // puts it into the previous bucket.)
+    if (B.Index > NextUncovered) {
+      error() << formatv("Name Index @ {0:x}: Name table entries [{1}, {2}] "
+                         "are not covered by the hash table.\n",
+                         NI.getUnitOffset(), NextUncovered, B.Index - 1);
+      ++NumErrors;
+    }
+    uint32_t Idx = B.Index;
+
+    // The rest of the checks apply only to non-sentinel entries.
+    if (B.Bucket == NI.getBucketCount())
+      break;
+
+    // This triggers if a non-empty bucket points to a name with a mismatched
+    // hash. Clients are likely to interpret this as an empty bucket, because a
+    // mismatched hash signals the end of a bucket, but if this is indeed an
+    // empty bucket, the producer should have signalled this by marking the
+    // bucket as empty.
+    uint32_t FirstHash = NI.getHashArrayEntry(Idx);
+    if (FirstHash % NI.getBucketCount() != B.Bucket) {
+      error() << formatv(
+          "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
+          "mismatched hash value {2:x} (belonging to bucket {3}).\n",
+          NI.getUnitOffset(), B.Bucket, FirstHash,
+          FirstHash % NI.getBucketCount());
+      ++NumErrors;
+    }
+
+    // This find the end of this bucket and also verifies that all the hashes in
+    // this bucket are correct by comparing the stored hashes to the ones we
+    // compute ourselves.
+    while (Idx <= NI.getNameCount()) {
+      uint32_t Hash = NI.getHashArrayEntry(Idx);
+      if (Hash % NI.getBucketCount() != B.Bucket)
+        break;
+
+      const char *Str = NI.getNameTableEntry(Idx).getString();
+      if (caseFoldingDjbHash(Str) != Hash) {
+        error() << formatv("Name Index @ {0:x}: String ({1}) at index {2} "
+                           "hashes to {3:x}, but "
+                           "the Name Index hash is {4:x}\n",
+                           NI.getUnitOffset(), Str, Idx,
+                           caseFoldingDjbHash(Str), Hash);
+        ++NumErrors;
+      }
+
+      ++Idx;
+    }
+    NextUncovered = std::max(NextUncovered, Idx);
+  }
+  return NumErrors;
+}
+
+unsigned DWARFVerifier::verifyNameIndexAttribute(
+    const DWARFDebugNames::NameIndex &NI, const DWARFDebugNames::Abbrev &Abbr,
+    DWARFDebugNames::AttributeEncoding AttrEnc) {
+  StringRef FormName = dwarf::FormEncodingString(AttrEnc.Form);
+  if (FormName.empty()) {
+    error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
+                       "unknown form: {3}.\n",
+                       NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
+                       AttrEnc.Form);
+    return 1;
+  }
+
+  if (AttrEnc.Index == DW_IDX_type_hash) {
+    if (AttrEnc.Form != dwarf::DW_FORM_data8) {
+      error() << formatv(
+          "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
+          "uses an unexpected form {2} (should be {3}).\n",
+          NI.getUnitOffset(), Abbr.Code, AttrEnc.Form, dwarf::DW_FORM_data8);
+      return 1;
+    }
+  }
+
+  // A list of known index attributes and their expected form classes.
+  // DW_IDX_type_hash is handled specially in the check above, as it has a
+  // specific form (not just a form class) we should expect.
+  struct FormClassTable {
+    dwarf::Index Index;
+    DWARFFormValue::FormClass Class;
+    StringLiteral ClassName;
+  };
+  static constexpr FormClassTable Table[] = {
+      {dwarf::DW_IDX_compile_unit, DWARFFormValue::FC_Constant, {"constant"}},
+      {dwarf::DW_IDX_type_unit, DWARFFormValue::FC_Constant, {"constant"}},
+      {dwarf::DW_IDX_die_offset, DWARFFormValue::FC_Reference, {"reference"}},
+      {dwarf::DW_IDX_parent, DWARFFormValue::FC_Constant, {"constant"}},
+  };
+
+  ArrayRef<FormClassTable> TableRef(Table);
+  auto Iter = find_if(TableRef, [AttrEnc](const FormClassTable &T) {
+    return T.Index == AttrEnc.Index;
+  });
+  if (Iter == TableRef.end()) {
+    warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains an "
+                      "unknown index attribute: {2}.\n",
+                      NI.getUnitOffset(), Abbr.Code, AttrEnc.Index);
+    return 0;
+  }
+
+  if (!DWARFFormValue(AttrEnc.Form).isFormClass(Iter->Class)) {
+    error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
+                       "unexpected form {3} (expected form class {4}).\n",
+                       NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
+                       AttrEnc.Form, Iter->ClassName);
+    return 1;
+  }
+  return 0;
+}
+
+unsigned
+DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
+  if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0) {
+    warn() << formatv("Name Index @ {0:x}: Verifying indexes of type units is "
+                      "not currently supported.\n",
+                      NI.getUnitOffset());
+    return 0;
+  }
+
+  unsigned NumErrors = 0;
+  for (const auto &Abbrev : NI.getAbbrevs()) {
+    StringRef TagName = dwarf::TagString(Abbrev.Tag);
+    if (TagName.empty()) {
+      warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} references an "
+                        "unknown tag: {2}.\n",
+                        NI.getUnitOffset(), Abbrev.Code, Abbrev.Tag);
+    }
+    SmallSet<unsigned, 5> Attributes;
+    for (const auto &AttrEnc : Abbrev.Attributes) {
+      if (!Attributes.insert(AttrEnc.Index).second) {
+        error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains "
+                           "multiple {2} attributes.\n",
+                           NI.getUnitOffset(), Abbrev.Code, AttrEnc.Index);
+        ++NumErrors;
+        continue;
+      }
+      NumErrors += verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
+    }
+
+    if (NI.getCUCount() > 1 && !Attributes.count(dwarf::DW_IDX_compile_unit)) {
+      error() << formatv("NameIndex @ {0:x}: Indexing multiple compile units "
+                         "and abbreviation {1:x} has no {2} attribute.\n",
+                         NI.getUnitOffset(), Abbrev.Code,
+                         dwarf::DW_IDX_compile_unit);
+      ++NumErrors;
+    }
+    if (!Attributes.count(dwarf::DW_IDX_die_offset)) {
+      error() << formatv(
+          "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
+          NI.getUnitOffset(), Abbrev.Code, dwarf::DW_IDX_die_offset);
+      ++NumErrors;
+    }
+  }
+  return NumErrors;
+}
+
+static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE,
+                                          bool IncludeLinkageName = true) {
+  SmallVector<StringRef, 2> Result;
+  if (const char *Str = DIE.getName(DINameKind::ShortName))
+    Result.emplace_back(Str);
+  else if (DIE.getTag() == dwarf::DW_TAG_namespace)
+    Result.emplace_back("(anonymous namespace)");
+
+  if (IncludeLinkageName) {
+    if (const char *Str = DIE.getName(DINameKind::LinkageName)) {
+      if (Result.empty() || Result[0] != Str)
+        Result.emplace_back(Str);
+    }
+  }
+
+  return Result;
+}
+
+unsigned DWARFVerifier::verifyNameIndexEntries(
+    const DWARFDebugNames::NameIndex &NI,
+    const DWARFDebugNames::NameTableEntry &NTE) {
+  // Verifying type unit indexes not supported.
+  if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0)
+    return 0;
+
+  const char *CStr = NTE.getString();
+  if (!CStr) {
+    error() << formatv(
+        "Name Index @ {0:x}: Unable to get string associated with name {1}.\n",
+        NI.getUnitOffset(), NTE.getIndex());
+    return 1;
+  }
+  StringRef Str(CStr);
+
+  unsigned NumErrors = 0;
+  unsigned NumEntries = 0;
+  uint32_t EntryID = NTE.getEntryOffset();
+  uint32_t NextEntryID = EntryID;
+  Expected<DWARFDebugNames::Entry> EntryOr = NI.getEntry(&NextEntryID);
+  for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
+                                EntryOr = NI.getEntry(&NextEntryID)) {
+    uint32_t CUIndex = *EntryOr->getCUIndex();
+    if (CUIndex > NI.getCUCount()) {
+      error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
+                         "invalid CU index ({2}).\n",
+                         NI.getUnitOffset(), EntryID, CUIndex);
+      ++NumErrors;
+      continue;
+    }
+    uint32_t CUOffset = NI.getCUOffset(CUIndex);
+    uint64_t DIEOffset = CUOffset + *EntryOr->getDIEUnitOffset();
+    DWARFDie DIE = DCtx.getDIEForOffset(DIEOffset);
+    if (!DIE) {
+      error() << formatv("Name Index @ {0:x}: Entry @ {1:x} references a "
+                         "non-existing DIE @ {2:x}.\n",
+                         NI.getUnitOffset(), EntryID, DIEOffset);
+      ++NumErrors;
+      continue;
+    }
+    if (DIE.getDwarfUnit()->getOffset() != CUOffset) {
+      error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
+                         "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
+                         NI.getUnitOffset(), EntryID, DIEOffset, CUOffset,
+                         DIE.getDwarfUnit()->getOffset());
+      ++NumErrors;
+    }
+    if (DIE.getTag() != EntryOr->tag()) {
+      error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
+                         "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
+                         NI.getUnitOffset(), EntryID, DIEOffset, EntryOr->tag(),
+                         DIE.getTag());
+      ++NumErrors;
+    }
+
+    auto EntryNames = getNames(DIE);
+    if (!is_contained(EntryNames, Str)) {
+      error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
+                         "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
+                         NI.getUnitOffset(), EntryID, DIEOffset, Str,
+                         make_range(EntryNames.begin(), EntryNames.end()));
+      ++NumErrors;
+    }
+  }
+  handleAllErrors(EntryOr.takeError(),
+                  [&](const DWARFDebugNames::SentinelError &) {
+                    if (NumEntries > 0)
+                      return;
+                    error() << formatv("Name Index @ {0:x}: Name {1} ({2}) is "
+                                       "not associated with any entries.\n",
+                                       NI.getUnitOffset(), NTE.getIndex(), Str);
+                    ++NumErrors;
+                  },
+                  [&](const ErrorInfoBase &Info) {
+                    error()
+                        << formatv("Name Index @ {0:x}: Name {1} ({2}): {3}\n",
+                                   NI.getUnitOffset(), NTE.getIndex(), Str,
+                                   Info.message());
+                    ++NumErrors;
+                  });
+  return NumErrors;
+}
+
+static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) {
+  Optional<DWARFFormValue> Location = Die.findRecursively(DW_AT_location);
+  if (!Location)
+    return false;
+
+  auto ContainsInterestingOperators = [&](StringRef D) {
+    DWARFUnit *U = Die.getDwarfUnit();
+    DataExtractor Data(D, DCtx.isLittleEndian(), U->getAddressByteSize());
+    DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
+    return any_of(Expression, [](DWARFExpression::Operation &Op) {
+      return !Op.isError() && (Op.getCode() == DW_OP_addr ||
+                               Op.getCode() == DW_OP_form_tls_address ||
+                               Op.getCode() == DW_OP_GNU_push_tls_address);
+    });
+  };
+
+  if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {
+    // Inlined location.
+    if (ContainsInterestingOperators(toStringRef(*Expr)))
+      return true;
+  } else if (Optional<uint64_t> Offset = Location->getAsSectionOffset()) {
+    // Location list.
+    if (const DWARFDebugLoc *DebugLoc = DCtx.getDebugLoc()) {
+      if (const DWARFDebugLoc::LocationList *LocList =
+              DebugLoc->getLocationListAtOffset(*Offset)) {
+        if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) {
+              return ContainsInterestingOperators({E.Loc.data(), E.Loc.size()});
+            }))
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+unsigned DWARFVerifier::verifyNameIndexCompleteness(
+    const DWARFDie &Die, const DWARFDebugNames::NameIndex &NI) {
+
+  // First check, if the Die should be indexed. The code follows the DWARF v5
+  // wording as closely as possible.
+
+  // "All non-defining declarations (that is, debugging information entries
+  // with a DW_AT_declaration attribute) are excluded."
+  if (Die.find(DW_AT_declaration))
+    return 0;
+
+  // "DW_TAG_namespace debugging information entries without a DW_AT_name
+  // attribute are included with the name “(anonymous namespace)”.
+  // All other debugging information entries without a DW_AT_name attribute
+  // are excluded."
+  // "If a subprogram or inlined subroutine is included, and has a
+  // DW_AT_linkage_name attribute, there will be an additional index entry for
+  // the linkage name."
+  auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram ||
+                            Die.getTag() == DW_TAG_inlined_subroutine;
+  auto EntryNames = getNames(Die, IncludeLinkageName);
+  if (EntryNames.empty())
+    return 0;
+
+  // We deviate from the specification here, which says:
+  // "The name index must contain an entry for each debugging information entry
+  // that defines a named subprogram, label, variable, type, or namespace,
+  // subject to ..."
+  // Instead whitelisting all TAGs representing a "type" or a "subprogram", to
+  // make sure we catch any missing items, we instead blacklist all TAGs that we
+  // know shouldn't be indexed.
+  switch (Die.getTag()) {
+  // Compile units and modules have names but shouldn't be indexed.
+  case DW_TAG_compile_unit:
+  case DW_TAG_module:
+    return 0;
+
+  // Function and template parameters are not globally visible, so we shouldn't
+  // index them.
+  case DW_TAG_formal_parameter:
+  case DW_TAG_template_value_parameter:
+  case DW_TAG_template_type_parameter:
+  case DW_TAG_GNU_template_parameter_pack:
+  case DW_TAG_GNU_template_template_param:
+    return 0;
+
+  // Object members aren't globally visible.
+  case DW_TAG_member:
+    return 0;
+
+  // According to a strict reading of the specification, enumerators should not
+  // be indexed (and LLVM currently does not do that). However, this causes
+  // problems for the debuggers, so we may need to reconsider this.
+  case DW_TAG_enumerator:
+    return 0;
+
+  // Imported declarations should not be indexed according to the specification
+  // and LLVM currently does not do that.
+  case DW_TAG_imported_declaration:
+    return 0;
+
+  // "DW_TAG_subprogram, DW_TAG_inlined_subroutine, and DW_TAG_label debugging
+  // information entries without an address attribute (DW_AT_low_pc,
+  // DW_AT_high_pc, DW_AT_ranges, or DW_AT_entry_pc) are excluded."
+  case DW_TAG_subprogram:
+  case DW_TAG_inlined_subroutine:
+  case DW_TAG_label:
+    if (Die.findRecursively(
+            {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
+      break;
+    return 0;
+
+  // "DW_TAG_variable debugging information entries with a DW_AT_location
+  // attribute that includes a DW_OP_addr or DW_OP_form_tls_address operator are
+  // included; otherwise, they are excluded."
+  //
+  // LLVM extension: We also add DW_OP_GNU_push_tls_address to this list.
+  case DW_TAG_variable:
+    if (isVariableIndexable(Die, DCtx))
+      break;
+    return 0;
+
+  default:
+    break;
+  }
+
+  // Now we know that our Die should be present in the Index. Let's check if
+  // that's the case.
+  unsigned NumErrors = 0;
+  uint64_t DieUnitOffset = Die.getOffset() - Die.getDwarfUnit()->getOffset();
+  for (StringRef Name : EntryNames) {
+    if (none_of(NI.equal_range(Name), [&](const DWARFDebugNames::Entry &E) {
+          return E.getDIEUnitOffset() == DieUnitOffset;
+        })) {
+      error() << formatv("Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
+                         "name {3} missing.\n",
+                         NI.getUnitOffset(), Die.getOffset(), Die.getTag(),
+                         Name);
+      ++NumErrors;
+    }
+  }
+  return NumErrors;
+}
+
+unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
+                                         const DataExtractor &StrData) {
+  unsigned NumErrors = 0;
+  DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), AccelSection,
+                                      DCtx.isLittleEndian(), 0);
+  DWARFDebugNames AccelTable(AccelSectionData, StrData);
+
+  OS << "Verifying .debug_names...\n";
+
+  // This verifies that we can read individual name indices and their
+  // abbreviation tables.
+  if (Error E = AccelTable.extract()) {
+    error() << toString(std::move(E)) << '\n';
+    return 1;
+  }
+
+  NumErrors += verifyDebugNamesCULists(AccelTable);
+  for (const auto &NI : AccelTable)
+    NumErrors += verifyNameIndexBuckets(NI, StrData);
+  for (const auto &NI : AccelTable)
+    NumErrors += verifyNameIndexAbbrevs(NI);
+
+  // Don't attempt Entry validation if any of the previous checks found errors
+  if (NumErrors > 0)
+    return NumErrors;
+  for (const auto &NI : AccelTable)
+    for (DWARFDebugNames::NameTableEntry NTE : NI)
+      NumErrors += verifyNameIndexEntries(NI, NTE);
+
+  if (NumErrors > 0)
+    return NumErrors;
+
+  for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) {
+    if (const DWARFDebugNames::NameIndex *NI =
+            AccelTable.getCUNameIndex(U->getOffset())) {
+      auto *CU = cast<DWARFCompileUnit>(U.get());
+      for (const DWARFDebugInfoEntry &Die : CU->dies())
+        NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
+    }
+  }
+  return NumErrors;
+}
+
+bool DWARFVerifier::handleAccelTables() {
+  const DWARFObject &D = DCtx.getDWARFObj();
+  DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
+  unsigned NumErrors = 0;
+  if (!D.getAppleNamesSection().Data.empty())
+    NumErrors += verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData,
+                                       ".apple_names");
+  if (!D.getAppleTypesSection().Data.empty())
+    NumErrors += verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData,
+                                       ".apple_types");
+  if (!D.getAppleNamespacesSection().Data.empty())
+    NumErrors += verifyAppleAccelTable(&D.getAppleNamespacesSection(), &StrData,
+                                       ".apple_namespaces");
+  if (!D.getAppleObjCSection().Data.empty())
+    NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData,
+                                       ".apple_objc");
+
+  if (!D.getDebugNamesSection().Data.empty())
+    NumErrors += verifyDebugNames(D.getDebugNamesSection(), StrData);
+  return NumErrors == 0;
+}
+
+raw_ostream &DWARFVerifier::error() const { return WithColor::error(OS); }
+
+raw_ostream &DWARFVerifier::warn() const { return WithColor::warning(OS); }
+
+raw_ostream &DWARFVerifier::note() const { return WithColor::note(OS); }
+
+raw_ostream &DWARFVerifier::dump(const DWARFDie &Die, unsigned indent) const {
+  Die.dump(OS, indent, DumpOpts);
+  return OS;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
new file mode 100644
index 0000000..a212762
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/DebugInfo/DWARF/LLVMBuild.txt ----------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoDWARF
+parent = DebugInfo
+required_libraries = BinaryFormat Object MC Support
diff --git a/src/llvm-project/llvm/lib/DebugInfo/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/LLVMBuild.txt
new file mode 100644
index 0000000..86503e1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/LLVMBuild.txt
@@ -0,0 +1,24 @@
+;===- ./lib/DebugInfo/LLVMBuild.txt ----------------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[common]
+subdirectories = DWARF MSF CodeView PDB Symbolize
+
+[component_0]
+type = Group
+name = DebugInfo
+parent = $ROOT
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/MSF/CMakeLists.txt
new file mode 100644
index 0000000..6f38de3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_llvm_library(LLVMDebugInfoMSF
+  MappedBlockStream.cpp
+  MSFBuilder.cpp
+  MSFCommon.cpp
+  MSFError.cpp
+  ADDITIONAL_HEADER_DIRS
+  "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/MSF"
+  )
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/MSF/LLVMBuild.txt
new file mode 100644
index 0000000..391547c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/DebugInfo/MSF/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoMSF
+parent = DebugInfo
+required_libraries = Support
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
new file mode 100644
index 0000000..7160991
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
@@ -0,0 +1,382 @@
+//===- MSFBuilder.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+
+static const uint32_t kSuperBlockBlock = 0;
+static const uint32_t kFreePageMap0Block = 1;
+static const uint32_t kFreePageMap1Block = 2;
+static const uint32_t kNumReservedPages = 3;
+
+static const uint32_t kDefaultFreePageMap = kFreePageMap1Block;
+static const uint32_t kDefaultBlockMapAddr = kNumReservedPages;
+
+MSFBuilder::MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
+                       BumpPtrAllocator &Allocator)
+    : Allocator(Allocator), IsGrowable(CanGrow),
+      FreePageMap(kDefaultFreePageMap), BlockSize(BlockSize),
+      BlockMapAddr(kDefaultBlockMapAddr), FreeBlocks(MinBlockCount, true) {
+  FreeBlocks[kSuperBlockBlock] = false;
+  FreeBlocks[kFreePageMap0Block] = false;
+  FreeBlocks[kFreePageMap1Block] = false;
+  FreeBlocks[BlockMapAddr] = false;
+}
+
+Expected<MSFBuilder> MSFBuilder::create(BumpPtrAllocator &Allocator,
+                                        uint32_t BlockSize,
+                                        uint32_t MinBlockCount, bool CanGrow) {
+  if (!isValidBlockSize(BlockSize))
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "The requested block size is unsupported");
+
+  return MSFBuilder(BlockSize,
+                    std::max(MinBlockCount, msf::getMinimumBlockCount()),
+                    CanGrow, Allocator);
+}
+
+Error MSFBuilder::setBlockMapAddr(uint32_t Addr) {
+  if (Addr == BlockMapAddr)
+    return Error::success();
+
+  if (Addr >= FreeBlocks.size()) {
+    if (!IsGrowable)
+      return make_error<MSFError>(msf_error_code::insufficient_buffer,
+                                  "Cannot grow the number of blocks");
+    FreeBlocks.resize(Addr + 1, true);
+  }
+
+  if (!isBlockFree(Addr))
+    return make_error<MSFError>(
+        msf_error_code::block_in_use,
+        "Requested block map address is already in use");
+  FreeBlocks[BlockMapAddr] = true;
+  FreeBlocks[Addr] = false;
+  BlockMapAddr = Addr;
+  return Error::success();
+}
+
+void MSFBuilder::setFreePageMap(uint32_t Fpm) { FreePageMap = Fpm; }
+
+void MSFBuilder::setUnknown1(uint32_t Unk1) { Unknown1 = Unk1; }
+
+Error MSFBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
+  for (auto B : DirectoryBlocks)
+    FreeBlocks[B] = true;
+  for (auto B : DirBlocks) {
+    if (!isBlockFree(B)) {
+      return make_error<MSFError>(msf_error_code::unspecified,
+                                  "Attempt to reuse an allocated block");
+    }
+    FreeBlocks[B] = false;
+  }
+
+  DirectoryBlocks = DirBlocks;
+  return Error::success();
+}
+
+Error MSFBuilder::allocateBlocks(uint32_t NumBlocks,
+                                 MutableArrayRef<uint32_t> Blocks) {
+  if (NumBlocks == 0)
+    return Error::success();
+
+  uint32_t NumFreeBlocks = FreeBlocks.count();
+  if (NumFreeBlocks < NumBlocks) {
+    if (!IsGrowable)
+      return make_error<MSFError>(msf_error_code::insufficient_buffer,
+                                  "There are no free Blocks in the file");
+    uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
+    uint32_t OldBlockCount = FreeBlocks.size();
+    uint32_t NewBlockCount = AllocBlocks + OldBlockCount;
+    uint32_t NextFpmBlock = alignTo(OldBlockCount, BlockSize) + 1;
+    FreeBlocks.resize(NewBlockCount, true);
+    // If we crossed over an fpm page, we actually need to allocate 2 extra
+    // blocks for each FPM group crossed and mark both blocks from the group as
+    // used.  FPM blocks are marked as allocated regardless of whether or not
+    // they ultimately describe the status of blocks in the file.  This means
+    // that not only are extraneous blocks at the end of the main FPM marked as
+    // allocated, but also blocks from the alternate FPM are always marked as
+    // allocated.
+    while (NextFpmBlock < NewBlockCount) {
+      NewBlockCount += 2;
+      FreeBlocks.resize(NewBlockCount, true);
+      FreeBlocks.reset(NextFpmBlock, NextFpmBlock + 2);
+      NextFpmBlock += BlockSize;
+    }
+  }
+
+  int I = 0;
+  int Block = FreeBlocks.find_first();
+  do {
+    assert(Block != -1 && "We ran out of Blocks!");
+
+    uint32_t NextBlock = static_cast<uint32_t>(Block);
+    Blocks[I++] = NextBlock;
+    FreeBlocks.reset(NextBlock);
+    Block = FreeBlocks.find_next(Block);
+  } while (--NumBlocks > 0);
+  return Error::success();
+}
+
+uint32_t MSFBuilder::getNumUsedBlocks() const {
+  return getTotalBlockCount() - getNumFreeBlocks();
+}
+
+uint32_t MSFBuilder::getNumFreeBlocks() const { return FreeBlocks.count(); }
+
+uint32_t MSFBuilder::getTotalBlockCount() const { return FreeBlocks.size(); }
+
+bool MSFBuilder::isBlockFree(uint32_t Idx) const { return FreeBlocks[Idx]; }
+
+Expected<uint32_t> MSFBuilder::addStream(uint32_t Size,
+                                         ArrayRef<uint32_t> Blocks) {
+  // Add a new stream mapped to the specified blocks.  Verify that the specified
+  // blocks are both necessary and sufficient for holding the requested number
+  // of bytes, and verify that all requested blocks are free.
+  uint32_t ReqBlocks = bytesToBlocks(Size, BlockSize);
+  if (ReqBlocks != Blocks.size())
+    return make_error<MSFError>(
+        msf_error_code::invalid_format,
+        "Incorrect number of blocks for requested stream size");
+  for (auto Block : Blocks) {
+    if (Block >= FreeBlocks.size())
+      FreeBlocks.resize(Block + 1, true);
+
+    if (!FreeBlocks.test(Block))
+      return make_error<MSFError>(
+          msf_error_code::unspecified,
+          "Attempt to re-use an already allocated block");
+  }
+  // Mark all the blocks occupied by the new stream as not free.
+  for (auto Block : Blocks) {
+    FreeBlocks.reset(Block);
+  }
+  StreamData.push_back(std::make_pair(Size, Blocks));
+  return StreamData.size() - 1;
+}
+
+Expected<uint32_t> MSFBuilder::addStream(uint32_t Size) {
+  uint32_t ReqBlocks = bytesToBlocks(Size, BlockSize);
+  std::vector<uint32_t> NewBlocks;
+  NewBlocks.resize(ReqBlocks);
+  if (auto EC = allocateBlocks(ReqBlocks, NewBlocks))
+    return std::move(EC);
+  StreamData.push_back(std::make_pair(Size, NewBlocks));
+  return StreamData.size() - 1;
+}
+
+Error MSFBuilder::setStreamSize(uint32_t Idx, uint32_t Size) {
+  uint32_t OldSize = getStreamSize(Idx);
+  if (OldSize == Size)
+    return Error::success();
+
+  uint32_t NewBlocks = bytesToBlocks(Size, BlockSize);
+  uint32_t OldBlocks = bytesToBlocks(OldSize, BlockSize);
+
+  if (NewBlocks > OldBlocks) {
+    uint32_t AddedBlocks = NewBlocks - OldBlocks;
+    // If we're growing, we have to allocate new Blocks.
+    std::vector<uint32_t> AddedBlockList;
+    AddedBlockList.resize(AddedBlocks);
+    if (auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
+      return EC;
+    auto &CurrentBlocks = StreamData[Idx].second;
+    CurrentBlocks.insert(CurrentBlocks.end(), AddedBlockList.begin(),
+                         AddedBlockList.end());
+  } else if (OldBlocks > NewBlocks) {
+    // For shrinking, free all the Blocks in the Block map, update the stream
+    // data, then shrink the directory.
+    uint32_t RemovedBlocks = OldBlocks - NewBlocks;
+    auto CurrentBlocks = ArrayRef<uint32_t>(StreamData[Idx].second);
+    auto RemovedBlockList = CurrentBlocks.drop_front(NewBlocks);
+    for (auto P : RemovedBlockList)
+      FreeBlocks[P] = true;
+    StreamData[Idx].second = CurrentBlocks.drop_back(RemovedBlocks);
+  }
+
+  StreamData[Idx].first = Size;
+  return Error::success();
+}
+
+uint32_t MSFBuilder::getNumStreams() const { return StreamData.size(); }
+
+uint32_t MSFBuilder::getStreamSize(uint32_t StreamIdx) const {
+  return StreamData[StreamIdx].first;
+}
+
+ArrayRef<uint32_t> MSFBuilder::getStreamBlocks(uint32_t StreamIdx) const {
+  return StreamData[StreamIdx].second;
+}
+
+uint32_t MSFBuilder::computeDirectoryByteSize() const {
+  // The directory has the following layout, where each item is a ulittle32_t:
+  //    NumStreams
+  //    StreamSizes[NumStreams]
+  //    StreamBlocks[NumStreams][]
+  uint32_t Size = sizeof(ulittle32_t);             // NumStreams
+  Size += StreamData.size() * sizeof(ulittle32_t); // StreamSizes
+  for (const auto &D : StreamData) {
+    uint32_t ExpectedNumBlocks = bytesToBlocks(D.first, BlockSize);
+    assert(ExpectedNumBlocks == D.second.size() &&
+           "Unexpected number of blocks");
+    Size += ExpectedNumBlocks * sizeof(ulittle32_t);
+  }
+  return Size;
+}
+
+Expected<MSFLayout> MSFBuilder::generateLayout() {
+  SuperBlock *SB = Allocator.Allocate<SuperBlock>();
+  MSFLayout L;
+  L.SB = SB;
+
+  std::memcpy(SB->MagicBytes, Magic, sizeof(Magic));
+  SB->BlockMapAddr = BlockMapAddr;
+  SB->BlockSize = BlockSize;
+  SB->NumDirectoryBytes = computeDirectoryByteSize();
+  SB->FreeBlockMapBlock = FreePageMap;
+  SB->Unknown1 = Unknown1;
+
+  uint32_t NumDirectoryBlocks = bytesToBlocks(SB->NumDirectoryBytes, BlockSize);
+  if (NumDirectoryBlocks > DirectoryBlocks.size()) {
+    // Our hint wasn't enough to satisfy the entire directory.  Allocate
+    // remaining pages.
+    std::vector<uint32_t> ExtraBlocks;
+    uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
+    ExtraBlocks.resize(NumExtraBlocks);
+    if (auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
+      return std::move(EC);
+    DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(),
+                           ExtraBlocks.end());
+  } else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
+    uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
+    for (auto B :
+         ArrayRef<uint32_t>(DirectoryBlocks).drop_back(NumUnnecessaryBlocks))
+      FreeBlocks[B] = true;
+    DirectoryBlocks.resize(NumDirectoryBlocks);
+  }
+
+  // Don't set the number of blocks in the file until after allocating Blocks
+  // for the directory, since the allocation might cause the file to need to
+  // grow.
+  SB->NumBlocks = FreeBlocks.size();
+
+  ulittle32_t *DirBlocks = Allocator.Allocate<ulittle32_t>(NumDirectoryBlocks);
+  std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
+                            DirBlocks);
+  L.DirectoryBlocks = ArrayRef<ulittle32_t>(DirBlocks, NumDirectoryBlocks);
+
+  // The stream sizes should be re-allocated as a stable pointer and the stream
+  // map should have each of its entries allocated as a separate stable pointer.
+  if (!StreamData.empty()) {
+    ulittle32_t *Sizes = Allocator.Allocate<ulittle32_t>(StreamData.size());
+    L.StreamSizes = ArrayRef<ulittle32_t>(Sizes, StreamData.size());
+    L.StreamMap.resize(StreamData.size());
+    for (uint32_t I = 0; I < StreamData.size(); ++I) {
+      Sizes[I] = StreamData[I].first;
+      ulittle32_t *BlockList =
+          Allocator.Allocate<ulittle32_t>(StreamData[I].second.size());
+      std::uninitialized_copy_n(StreamData[I].second.begin(),
+                                StreamData[I].second.size(), BlockList);
+      L.StreamMap[I] =
+          ArrayRef<ulittle32_t>(BlockList, StreamData[I].second.size());
+    }
+  }
+
+  L.FreePageMap = FreeBlocks;
+
+  return L;
+}
+
+static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout,
+                      BumpPtrAllocator &Allocator) {
+  auto FpmStream =
+      WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
+
+  // We only need to create the alt fpm stream so that it gets initialized.
+  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
+                                             true);
+
+  uint32_t BI = 0;
+  BinaryStreamWriter FpmWriter(*FpmStream);
+  while (BI < Layout.SB->NumBlocks) {
+    uint8_t ThisByte = 0;
+    for (uint32_t I = 0; I < 8; ++I) {
+      bool IsFree =
+          (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
+      uint8_t Mask = uint8_t(IsFree) << I;
+      ThisByte |= Mask;
+      ++BI;
+    }
+    cantFail(FpmWriter.writeObject(ThisByte));
+  }
+  assert(FpmWriter.bytesRemaining() == 0);
+}
+
+Expected<FileBufferByteStream> MSFBuilder::commit(StringRef Path,
+                                                  MSFLayout &Layout) {
+  Expected<MSFLayout> L = generateLayout();
+  if (!L)
+    return L.takeError();
+
+  Layout = std::move(*L);
+
+  uint64_t FileSize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
+  auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
+  if (auto EC = OutFileOrError.takeError())
+    return std::move(EC);
+
+  FileBufferByteStream Buffer(std::move(*OutFileOrError),
+                              llvm::support::little);
+  BinaryStreamWriter Writer(Buffer);
+
+  if (auto EC = Writer.writeObject(*Layout.SB))
+    return std::move(EC);
+
+  commitFpm(Buffer, Layout, Allocator);
+
+  uint32_t BlockMapOffset =
+      msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
+  Writer.setOffset(BlockMapOffset);
+  if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
+    return std::move(EC);
+
+  auto DirStream = WritableMappedBlockStream::createDirectoryStream(
+      Layout, Buffer, Allocator);
+  BinaryStreamWriter DW(*DirStream);
+  if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
+    return std::move(EC);
+
+  if (auto EC = DW.writeArray(Layout.StreamSizes))
+    return std::move(EC);
+
+  for (const auto &Blocks : Layout.StreamMap) {
+    if (auto EC = DW.writeArray(Blocks))
+      return std::move(EC);
+  }
+
+  return std::move(Buffer);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFCommon.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
new file mode 100644
index 0000000..d398304
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
@@ -0,0 +1,83 @@
+//===- MSFCommon.cpp - Common types and functions for MSF files -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::msf;
+
+Error llvm::msf::validateSuperBlock(const SuperBlock &SB) {
+  // Check the magic bytes.
+  if (std::memcmp(SB.MagicBytes, Magic, sizeof(Magic)) != 0)
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "MSF magic header doesn't match");
+
+  if (!isValidBlockSize(SB.BlockSize))
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "Unsupported block size.");
+
+  // We don't support directories whose sizes aren't a multiple of four bytes.
+  if (SB.NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "Directory size is not multiple of 4.");
+
+  // The number of blocks which comprise the directory is a simple function of
+  // the number of bytes it contains.
+  uint64_t NumDirectoryBlocks =
+      bytesToBlocks(SB.NumDirectoryBytes, SB.BlockSize);
+
+  // The directory, as we understand it, is a block which consists of a list of
+  // block numbers.  It is unclear what would happen if the number of blocks
+  // couldn't fit on a single block.
+  if (NumDirectoryBlocks > SB.BlockSize / sizeof(support::ulittle32_t))
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "Too many directory blocks.");
+
+  if (SB.BlockMapAddr == 0)
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "Block 0 is reserved");
+
+  if (SB.BlockMapAddr >= SB.NumBlocks)
+    return make_error<MSFError>(msf_error_code::invalid_format,
+                                "Block map address is invalid.");
+
+  if (SB.FreeBlockMapBlock != 1 && SB.FreeBlockMapBlock != 2)
+    return make_error<MSFError>(
+        msf_error_code::invalid_format,
+        "The free block map isn't at block 1 or block 2.");
+
+  return Error::success();
+}
+
+MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf,
+                                              bool IncludeUnusedFpmData,
+                                              bool AltFpm) {
+  MSFStreamLayout FL;
+  uint32_t NumFpmIntervals =
+      getNumFpmIntervals(Msf, IncludeUnusedFpmData, AltFpm);
+
+  uint32_t FpmBlock = AltFpm ? Msf.alternateFpmBlock() : Msf.mainFpmBlock();
+
+  for (uint32_t I = 0; I < NumFpmIntervals; ++I) {
+    FL.Blocks.push_back(support::ulittle32_t(FpmBlock));
+    FpmBlock += msf::getFpmIntervalLength(Msf);
+  }
+
+  if (IncludeUnusedFpmData)
+    FL.Length = NumFpmIntervals * Msf.SB->BlockSize;
+  else
+    FL.Length = divideCeil(Msf.SB->NumBlocks, 8);
+
+  return FL;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp
new file mode 100644
index 0000000..bfac6be
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MSFError.cpp
@@ -0,0 +1,46 @@
+//===- MSFError.cpp - Error extensions for MSF files ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class MSFErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.msf"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<msf_error_code>(Condition)) {
+    case msf_error_code::unspecified:
+      return "An unknown error has occurred.";
+    case msf_error_code::insufficient_buffer:
+      return "The buffer is not large enough to read the requested number of "
+             "bytes.";
+    case msf_error_code::not_writable:
+      return "The specified stream is not writable.";
+    case msf_error_code::no_stream:
+      return "The specified stream does not exist.";
+    case msf_error_code::invalid_format:
+      return "The data is in an unexpected format.";
+    case msf_error_code::block_in_use:
+      return "The block is already in use.";
+    }
+    llvm_unreachable("Unrecognized msf_error_code");
+  }
+};
+
+static llvm::ManagedStatic<MSFErrorCategory> MSFCategory;
+const std::error_category &llvm::msf::MSFErrCategory() { return *MSFCategory; }
+
+char MSFError::ID;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
new file mode 100644
index 0000000..dec28eb
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
@@ -0,0 +1,422 @@
+//===- MappedBlockStream.cpp - Reads stream data from an MSF file ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::msf;
+
+namespace {
+
+template <typename Base> class MappedBlockStreamImpl : public Base {
+public:
+  template <typename... Args>
+  MappedBlockStreamImpl(Args &&... Params)
+      : Base(std::forward<Args>(Params)...) {}
+};
+
+} // end anonymous namespace
+
+using Interval = std::pair<uint32_t, uint32_t>;
+
+static Interval intersect(const Interval &I1, const Interval &I2) {
+  return std::make_pair(std::max(I1.first, I2.first),
+                        std::min(I1.second, I2.second));
+}
+
+MappedBlockStream::MappedBlockStream(uint32_t BlockSize,
+                                     const MSFStreamLayout &Layout,
+                                     BinaryStreamRef MsfData,
+                                     BumpPtrAllocator &Allocator)
+    : BlockSize(BlockSize), StreamLayout(Layout), MsfData(MsfData),
+      Allocator(Allocator) {}
+
+std::unique_ptr<MappedBlockStream> MappedBlockStream::createStream(
+    uint32_t BlockSize, const MSFStreamLayout &Layout, BinaryStreamRef MsfData,
+    BumpPtrAllocator &Allocator) {
+  return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
+      BlockSize, Layout, MsfData, Allocator);
+}
+
+std::unique_ptr<MappedBlockStream> MappedBlockStream::createIndexedStream(
+    const MSFLayout &Layout, BinaryStreamRef MsfData, uint32_t StreamIndex,
+    BumpPtrAllocator &Allocator) {
+  assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
+  MSFStreamLayout SL;
+  SL.Blocks = Layout.StreamMap[StreamIndex];
+  SL.Length = Layout.StreamSizes[StreamIndex];
+  return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
+      Layout.SB->BlockSize, SL, MsfData, Allocator);
+}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createDirectoryStream(const MSFLayout &Layout,
+                                         BinaryStreamRef MsfData,
+                                         BumpPtrAllocator &Allocator) {
+  MSFStreamLayout SL;
+  SL.Blocks = Layout.DirectoryBlocks;
+  SL.Length = Layout.SB->NumDirectoryBytes;
+  return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
+}
+
+std::unique_ptr<MappedBlockStream>
+MappedBlockStream::createFpmStream(const MSFLayout &Layout,
+                                   BinaryStreamRef MsfData,
+                                   BumpPtrAllocator &Allocator) {
+  MSFStreamLayout SL(getFpmStreamLayout(Layout));
+  return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
+}
+
+Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
+                                   ArrayRef<uint8_t> &Buffer) {
+  // Make sure we aren't trying to read beyond the end of the stream.
+  if (auto EC = checkOffsetForRead(Offset, Size))
+    return EC;
+
+  if (tryReadContiguously(Offset, Size, Buffer))
+    return Error::success();
+
+  auto CacheIter = CacheMap.find(Offset);
+  if (CacheIter != CacheMap.end()) {
+    // Try to find an alloc that was large enough for this request.
+    for (auto &Entry : CacheIter->second) {
+      if (Entry.size() >= Size) {
+        Buffer = Entry.slice(0, Size);
+        return Error::success();
+      }
+    }
+  }
+
+  // We couldn't find a buffer that started at the correct offset (the most
+  // common scenario).  Try to see if there is a buffer that starts at some
+  // other offset but overlaps the desired range.
+  for (auto &CacheItem : CacheMap) {
+    Interval RequestExtent = std::make_pair(Offset, Offset + Size);
+
+    // We already checked this one on the fast path above.
+    if (CacheItem.first == Offset)
+      continue;
+    // If the initial extent of the cached item is beyond the ending extent
+    // of the request, there is no overlap.
+    if (CacheItem.first >= Offset + Size)
+      continue;
+
+    // We really only have to check the last item in the list, since we append
+    // in order of increasing length.
+    if (CacheItem.second.empty())
+      continue;
+
+    auto CachedAlloc = CacheItem.second.back();
+    // If the initial extent of the request is beyond the ending extent of
+    // the cached item, there is no overlap.
+    Interval CachedExtent =
+        std::make_pair(CacheItem.first, CacheItem.first + CachedAlloc.size());
+    if (RequestExtent.first >= CachedExtent.first + CachedExtent.second)
+      continue;
+
+    Interval Intersection = intersect(CachedExtent, RequestExtent);
+    // Only use this if the entire request extent is contained in the cached
+    // extent.
+    if (Intersection != RequestExtent)
+      continue;
+
+    uint32_t CacheRangeOffset =
+        AbsoluteDifference(CachedExtent.first, Intersection.first);
+    Buffer = CachedAlloc.slice(CacheRangeOffset, Size);
+    return Error::success();
+  }
+
+  // Otherwise allocate a large enough buffer in the pool, memcpy the data
+  // into it, and return an ArrayRef to that.  Do not touch existing pool
+  // allocations, as existing clients may be holding a pointer which must
+  // not be invalidated.
+  uint8_t *WriteBuffer = static_cast<uint8_t *>(Allocator.Allocate(Size, 8));
+  if (auto EC = readBytes(Offset, MutableArrayRef<uint8_t>(WriteBuffer, Size)))
+    return EC;
+
+  if (CacheIter != CacheMap.end()) {
+    CacheIter->second.emplace_back(WriteBuffer, Size);
+  } else {
+    std::vector<CacheEntry> List;
+    List.emplace_back(WriteBuffer, Size);
+    CacheMap.insert(std::make_pair(Offset, List));
+  }
+  Buffer = ArrayRef<uint8_t>(WriteBuffer, Size);
+  return Error::success();
+}
+
+Error MappedBlockStream::readLongestContiguousChunk(uint32_t Offset,
+                                                    ArrayRef<uint8_t> &Buffer) {
+  // Make sure we aren't trying to read beyond the end of the stream.
+  if (auto EC = checkOffsetForRead(Offset, 1))
+    return EC;
+
+  uint32_t First = Offset / BlockSize;
+  uint32_t Last = First;
+
+  while (Last < getNumBlocks() - 1) {
+    if (StreamLayout.Blocks[Last] != StreamLayout.Blocks[Last + 1] - 1)
+      break;
+    ++Last;
+  }
+
+  uint32_t OffsetInFirstBlock = Offset % BlockSize;
+  uint32_t BytesFromFirstBlock = BlockSize - OffsetInFirstBlock;
+  uint32_t BlockSpan = Last - First + 1;
+  uint32_t ByteSpan = BytesFromFirstBlock + (BlockSpan - 1) * BlockSize;
+
+  ArrayRef<uint8_t> BlockData;
+  uint32_t MsfOffset = blockToOffset(StreamLayout.Blocks[First], BlockSize);
+  if (auto EC = MsfData.readBytes(MsfOffset, BlockSize, BlockData))
+    return EC;
+
+  BlockData = BlockData.drop_front(OffsetInFirstBlock);
+  Buffer = ArrayRef<uint8_t>(BlockData.data(), ByteSpan);
+  return Error::success();
+}
+
+uint32_t MappedBlockStream::getLength() { return StreamLayout.Length; }
+
+bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,
+                                            ArrayRef<uint8_t> &Buffer) {
+  if (Size == 0) {
+    Buffer = ArrayRef<uint8_t>();
+    return true;
+  }
+  // Attempt to fulfill the request with a reference directly into the stream.
+  // This can work even if the request crosses a block boundary, provided that
+  // all subsequent blocks are contiguous.  For example, a 10k read with a 4k
+  // block size can be filled with a reference if, from the starting offset,
+  // 3 blocks in a row are contiguous.
+  uint32_t BlockNum = Offset / BlockSize;
+  uint32_t OffsetInBlock = Offset % BlockSize;
+  uint32_t BytesFromFirstBlock = std::min(Size, BlockSize - OffsetInBlock);
+  uint32_t NumAdditionalBlocks =
+      alignTo(Size - BytesFromFirstBlock, BlockSize) / BlockSize;
+
+  uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
+  uint32_t E = StreamLayout.Blocks[BlockNum];
+  for (uint32_t I = 0; I < RequiredContiguousBlocks; ++I, ++E) {
+    if (StreamLayout.Blocks[I + BlockNum] != E)
+      return false;
+  }
+
+  // Read out the entire block where the requested offset starts.  Then drop
+  // bytes from the beginning so that the actual starting byte lines up with
+  // the requested starting byte.  Then, since we know this is a contiguous
+  // cross-block span, explicitly resize the ArrayRef to cover the entire
+  // request length.
+  ArrayRef<uint8_t> BlockData;
+  uint32_t FirstBlockAddr = StreamLayout.Blocks[BlockNum];
+  uint32_t MsfOffset = blockToOffset(FirstBlockAddr, BlockSize);
+  if (auto EC = MsfData.readBytes(MsfOffset, BlockSize, BlockData)) {
+    consumeError(std::move(EC));
+    return false;
+  }
+  BlockData = BlockData.drop_front(OffsetInBlock);
+  Buffer = ArrayRef<uint8_t>(BlockData.data(), Size);
+  return true;
+}
+
+Error MappedBlockStream::readBytes(uint32_t Offset,
+                                   MutableArrayRef<uint8_t> Buffer) {
+  uint32_t BlockNum = Offset / BlockSize;
+  uint32_t OffsetInBlock = Offset % BlockSize;
+
+  // Make sure we aren't trying to read beyond the end of the stream.
+  if (auto EC = checkOffsetForRead(Offset, Buffer.size()))
+    return EC;
+
+  uint32_t BytesLeft = Buffer.size();
+  uint32_t BytesWritten = 0;
+  uint8_t *WriteBuffer = Buffer.data();
+  while (BytesLeft > 0) {
+    uint32_t StreamBlockAddr = StreamLayout.Blocks[BlockNum];
+
+    ArrayRef<uint8_t> BlockData;
+    uint32_t Offset = blockToOffset(StreamBlockAddr, BlockSize);
+    if (auto EC = MsfData.readBytes(Offset, BlockSize, BlockData))
+      return EC;
+
+    const uint8_t *ChunkStart = BlockData.data() + OffsetInBlock;
+    uint32_t BytesInChunk = std::min(BytesLeft, BlockSize - OffsetInBlock);
+    ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
+
+    BytesWritten += BytesInChunk;
+    BytesLeft -= BytesInChunk;
+    ++BlockNum;
+    OffsetInBlock = 0;
+  }
+
+  return Error::success();
+}
+
+void MappedBlockStream::invalidateCache() { CacheMap.shrink_and_clear(); }
+
+void MappedBlockStream::fixCacheAfterWrite(uint32_t Offset,
+                                           ArrayRef<uint8_t> Data) const {
+  // If this write overlapped a read which previously came from the pool,
+  // someone may still be holding a pointer to that alloc which is now invalid.
+  // Compute the overlapping range and update the cache entry, so any
+  // outstanding buffers are automatically updated.
+  for (const auto &MapEntry : CacheMap) {
+    // If the end of the written extent precedes the beginning of the cached
+    // extent, ignore this map entry.
+    if (Offset + Data.size() < MapEntry.first)
+      continue;
+    for (const auto &Alloc : MapEntry.second) {
+      // If the end of the cached extent precedes the beginning of the written
+      // extent, ignore this alloc.
+      if (MapEntry.first + Alloc.size() < Offset)
+        continue;
+
+      // If we get here, they are guaranteed to overlap.
+      Interval WriteInterval = std::make_pair(Offset, Offset + Data.size());
+      Interval CachedInterval =
+          std::make_pair(MapEntry.first, MapEntry.first + Alloc.size());
+      // If they overlap, we need to write the new data into the overlapping
+      // range.
+      auto Intersection = intersect(WriteInterval, CachedInterval);
+      assert(Intersection.first <= Intersection.second);
+
+      uint32_t Length = Intersection.second - Intersection.first;
+      uint32_t SrcOffset =
+          AbsoluteDifference(WriteInterval.first, Intersection.first);
+      uint32_t DestOffset =
+          AbsoluteDifference(CachedInterval.first, Intersection.first);
+      ::memcpy(Alloc.data() + DestOffset, Data.data() + SrcOffset, Length);
+    }
+  }
+}
+
+WritableMappedBlockStream::WritableMappedBlockStream(
+    uint32_t BlockSize, const MSFStreamLayout &Layout,
+    WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator)
+    : ReadInterface(BlockSize, Layout, MsfData, Allocator),
+      WriteInterface(MsfData) {}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createStream(uint32_t BlockSize,
+                                        const MSFStreamLayout &Layout,
+                                        WritableBinaryStreamRef MsfData,
+                                        BumpPtrAllocator &Allocator) {
+  return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>(
+      BlockSize, Layout, MsfData, Allocator);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout,
+                                               WritableBinaryStreamRef MsfData,
+                                               uint32_t StreamIndex,
+                                               BumpPtrAllocator &Allocator) {
+  assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index");
+  MSFStreamLayout SL;
+  SL.Blocks = Layout.StreamMap[StreamIndex];
+  SL.Length = Layout.StreamSizes[StreamIndex];
+  return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createDirectoryStream(
+    const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
+    BumpPtrAllocator &Allocator) {
+  MSFStreamLayout SL;
+  SL.Blocks = Layout.DirectoryBlocks;
+  SL.Length = Layout.SB->NumDirectoryBytes;
+  return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
+}
+
+std::unique_ptr<WritableMappedBlockStream>
+WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
+                                           WritableBinaryStreamRef MsfData,
+                                           BumpPtrAllocator &Allocator,
+                                           bool AltFpm) {
+  // We only want to give the user a stream containing the bytes of the FPM that
+  // are actually valid, but we want to initialize all of the bytes, even those
+  // that come from reserved FPM blocks where the entire block is unused.  To do
+  // this, we first create the full layout, which gives us a stream with all
+  // bytes and all blocks, and initialize everything to 0xFF (all blocks in the
+  // file are unused).  Then we create the minimal layout (which contains only a
+  // subset of the bytes previously initialized), and return that to the user.
+  MSFStreamLayout MinLayout(getFpmStreamLayout(Layout, false, AltFpm));
+
+  MSFStreamLayout FullLayout(getFpmStreamLayout(Layout, true, AltFpm));
+  auto Result =
+      createStream(Layout.SB->BlockSize, FullLayout, MsfData, Allocator);
+  if (!Result)
+    return Result;
+  std::vector<uint8_t> InitData(Layout.SB->BlockSize, 0xFF);
+  BinaryStreamWriter Initializer(*Result);
+  while (Initializer.bytesRemaining() > 0)
+    cantFail(Initializer.writeBytes(InitData));
+  return createStream(Layout.SB->BlockSize, MinLayout, MsfData, Allocator);
+}
+
+Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,
+                                           ArrayRef<uint8_t> &Buffer) {
+  return ReadInterface.readBytes(Offset, Size, Buffer);
+}
+
+Error WritableMappedBlockStream::readLongestContiguousChunk(
+    uint32_t Offset, ArrayRef<uint8_t> &Buffer) {
+  return ReadInterface.readLongestContiguousChunk(Offset, Buffer);
+}
+
+uint32_t WritableMappedBlockStream::getLength() {
+  return ReadInterface.getLength();
+}
+
+Error WritableMappedBlockStream::writeBytes(uint32_t Offset,
+                                            ArrayRef<uint8_t> Buffer) {
+  // Make sure we aren't trying to write beyond the end of the stream.
+  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
+    return EC;
+
+  uint32_t BlockNum = Offset / getBlockSize();
+  uint32_t OffsetInBlock = Offset % getBlockSize();
+
+  uint32_t BytesLeft = Buffer.size();
+  uint32_t BytesWritten = 0;
+  while (BytesLeft > 0) {
+    uint32_t StreamBlockAddr = getStreamLayout().Blocks[BlockNum];
+    uint32_t BytesToWriteInChunk =
+        std::min(BytesLeft, getBlockSize() - OffsetInBlock);
+
+    const uint8_t *Chunk = Buffer.data() + BytesWritten;
+    ArrayRef<uint8_t> ChunkData(Chunk, BytesToWriteInChunk);
+    uint32_t MsfOffset = blockToOffset(StreamBlockAddr, getBlockSize());
+    MsfOffset += OffsetInBlock;
+    if (auto EC = WriteInterface.writeBytes(MsfOffset, ChunkData))
+      return EC;
+
+    BytesLeft -= BytesToWriteInChunk;
+    BytesWritten += BytesToWriteInChunk;
+    ++BlockNum;
+    OffsetInBlock = 0;
+  }
+
+  ReadInterface.fixCacheAfterWrite(Offset, Buffer);
+
+  return Error::success();
+}
+
+Error WritableMappedBlockStream::commit() { return WriteInterface.commit(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/PDB/CMakeLists.txt
new file mode 100644
index 0000000..d9d379f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -0,0 +1,132 @@
+macro(add_pdb_impl_folder group)
+  list(APPEND PDB_IMPL_SOURCES ${ARGN})
+  source_group(${group} FILES ${ARGN})
+endmacro()
+
+if(LLVM_ENABLE_DIA_SDK)
+  include_directories(${MSVC_DIA_SDK_DIR}/include)
+  set(LIBPDB_LINK_FOLDERS "${MSVC_DIA_SDK_DIR}\\lib")
+  if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+    set(LIBPDB_LINK_FOLDERS "${LIBPDB_LINK_FOLDERS}\\amd64")
+  endif()
+  file(TO_CMAKE_PATH "${LIBPDB_LINK_FOLDERS}\\diaguids.lib" LIBPDB_ADDITIONAL_LIBRARIES)
+
+  add_pdb_impl_folder(DIA
+    DIA/DIADataStream.cpp
+    DIA/DIAEnumDebugStreams.cpp
+    DIA/DIAEnumFrameData.cpp
+    DIA/DIAEnumInjectedSources.cpp
+    DIA/DIAEnumLineNumbers.cpp
+    DIA/DIAEnumSectionContribs.cpp
+    DIA/DIAEnumSourceFiles.cpp
+    DIA/DIAEnumSymbols.cpp
+    DIA/DIAEnumTables.cpp
+    DIA/DIAError.cpp
+    DIA/DIAFrameData.cpp
+    DIA/DIAInjectedSource.cpp
+    DIA/DIALineNumber.cpp
+    DIA/DIARawSymbol.cpp
+    DIA/DIASectionContrib.cpp
+    DIA/DIASession.cpp
+    DIA/DIASourceFile.cpp
+    DIA/DIATable.cpp
+    )
+
+    set(LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/DIA")
+endif()
+
+add_pdb_impl_folder(Native
+  Native/DbiModuleDescriptor.cpp
+  Native/DbiModuleDescriptorBuilder.cpp
+  Native/DbiModuleList.cpp
+  Native/DbiStream.cpp
+  Native/DbiStreamBuilder.cpp
+  Native/EnumTables.cpp
+  Native/GlobalsStream.cpp
+  Native/Hash.cpp
+  Native/HashTable.cpp
+  Native/InfoStream.cpp
+  Native/InfoStreamBuilder.cpp
+  Native/ModuleDebugStream.cpp
+  Native/NativeCompilandSymbol.cpp
+  Native/NativeEnumGlobals.cpp
+  Native/NativeEnumModules.cpp
+  Native/NativeEnumTypes.cpp
+  Native/NativeExeSymbol.cpp
+  Native/NativeRawSymbol.cpp
+  Native/NativeSymbolEnumerator.cpp
+  Native/NativeTypeArray.cpp
+  Native/NativeTypeBuiltin.cpp
+  Native/NativeTypeEnum.cpp
+  Native/NativeTypeFunctionSig.cpp
+  Native/NativeTypePointer.cpp
+  Native/NativeTypeTypedef.cpp
+  Native/NativeTypeUDT.cpp
+  Native/NativeTypeVTShape.cpp
+  Native/NamedStreamMap.cpp
+  Native/NativeSession.cpp
+  Native/PDBFile.cpp
+  Native/PDBFileBuilder.cpp
+  Native/PDBStringTable.cpp
+  Native/PDBStringTableBuilder.cpp
+  Native/PublicsStream.cpp
+  Native/GSIStreamBuilder.cpp
+  Native/RawError.cpp
+  Native/SymbolCache.cpp
+  Native/SymbolStream.cpp
+  Native/TpiHashing.cpp
+  Native/TpiStream.cpp
+  Native/TpiStreamBuilder.cpp
+  )
+
+list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/Native")
+list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB")
+
+add_llvm_library(LLVMDebugInfoPDB
+  GenericError.cpp
+  IPDBSourceFile.cpp
+  PDB.cpp
+  PDBContext.cpp
+  PDBExtras.cpp
+  PDBInterfaceAnchors.cpp
+  PDBSymbol.cpp
+  PDBSymbolAnnotation.cpp
+  PDBSymbolBlock.cpp
+  PDBSymbolCompiland.cpp
+  PDBSymbolCompilandDetails.cpp
+  PDBSymbolCompilandEnv.cpp
+  PDBSymbolCustom.cpp
+  PDBSymbolData.cpp
+  PDBSymbolExe.cpp
+  PDBSymbolFunc.cpp
+  PDBSymbolFuncDebugEnd.cpp
+  PDBSymbolFuncDebugStart.cpp
+  PDBSymbolLabel.cpp
+  PDBSymbolPublicSymbol.cpp
+  PDBSymbolThunk.cpp
+  PDBSymbolTypeArray.cpp
+  PDBSymbolTypeBaseClass.cpp
+  PDBSymbolTypeBuiltin.cpp
+  PDBSymbolTypeCustom.cpp
+  PDBSymbolTypeDimension.cpp
+  PDBSymbolTypeEnum.cpp
+  PDBSymbolTypeFriend.cpp
+  PDBSymbolTypeFunctionArg.cpp
+  PDBSymbolTypeFunctionSig.cpp
+  PDBSymbolTypeManaged.cpp
+  PDBSymbolTypePointer.cpp
+  PDBSymbolTypeTypedef.cpp
+  PDBSymbolTypeUDT.cpp
+  PDBSymbolTypeVTable.cpp
+  PDBSymbolTypeVTableShape.cpp
+  PDBSymbolUnknown.cpp
+  PDBSymbolUsingNamespace.cpp
+  PDBSymDumper.cpp
+  UDTLayout.cpp
+  ${PDB_IMPL_SOURCES}
+
+  ADDITIONAL_HEADER_DIRS
+  ${LIBPDB_ADDITIONAL_HEADER_DIRS}
+  )
+
+target_link_libraries(LLVMDebugInfoPDB INTERFACE "${LIBPDB_ADDITIONAL_LIBRARIES}")
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp
new file mode 100644
index 0000000..6a10513
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp
@@ -0,0 +1,57 @@
+//===- DIADataStream.cpp - DIA implementation of IPDBDataStream -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIADataStream::DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData)
+    : StreamData(DiaStreamData) {}
+
+uint32_t DIADataStream::getRecordCount() const {
+  LONG Count = 0;
+  return (S_OK == StreamData->get_Count(&Count)) ? Count : 0;
+}
+
+std::string DIADataStream::getName() const {
+  return invokeBstrMethod(*StreamData, &IDiaEnumDebugStreamData::get_name);
+}
+
+llvm::Optional<DIADataStream::RecordType>
+DIADataStream::getItemAtIndex(uint32_t Index) const {
+  RecordType Record;
+  DWORD RecordSize = 0;
+  StreamData->Item(Index, 0, &RecordSize, nullptr);
+  if (RecordSize == 0)
+    return llvm::Optional<RecordType>();
+
+  Record.resize(RecordSize);
+  if (S_OK != StreamData->Item(Index, RecordSize, &RecordSize, &Record[0]))
+    return llvm::Optional<RecordType>();
+  return Record;
+}
+
+bool DIADataStream::getNext(RecordType &Record) {
+  Record.clear();
+  DWORD RecordSize = 0;
+  ULONG CountFetched = 0;
+  StreamData->Next(1, 0, &RecordSize, nullptr, &CountFetched);
+  if (RecordSize == 0)
+    return false;
+
+  Record.resize(RecordSize);
+  if (S_OK ==
+      StreamData->Next(1, RecordSize, &RecordSize, &Record[0], &CountFetched))
+    return false;
+  return true;
+}
+
+void DIADataStream::reset() { StreamData->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp
new file mode 100644
index 0000000..d2451f1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp
@@ -0,0 +1,47 @@
+//==- DIAEnumDebugStreams.cpp - DIA Debug Stream Enumerator impl -*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumDebugStreams::DIAEnumDebugStreams(
+    CComPtr<IDiaEnumDebugStreams> DiaEnumerator)
+    : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumDebugStreams::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBDataStream>
+DIAEnumDebugStreams::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaEnumDebugStreamData> Item;
+  VARIANT VarIndex;
+  VarIndex.vt = VT_I4;
+  VarIndex.lVal = Index;
+  if (S_OK != Enumerator->Item(VarIndex, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBDataStream>(new DIADataStream(Item));
+}
+
+std::unique_ptr<IPDBDataStream> DIAEnumDebugStreams::getNext() {
+  CComPtr<IDiaEnumDebugStreamData> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBDataStream>(new DIADataStream(Item));
+}
+
+void DIAEnumDebugStreams::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp
new file mode 100644
index 0000000..f873f35
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp
@@ -0,0 +1,42 @@
+//==- DIAEnumFrameData.cpp ---------------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAFrameData.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+
+using namespace llvm::pdb;
+
+DIAEnumFrameData::DIAEnumFrameData(CComPtr<IDiaEnumFrameData> DiaEnumerator)
+    : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumFrameData::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBFrameData>
+DIAEnumFrameData::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaFrameData> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBFrameData>(new DIAFrameData(Item));
+}
+
+std::unique_ptr<IPDBFrameData> DIAEnumFrameData::getNext() {
+  CComPtr<IDiaFrameData> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBFrameData>(new DIAFrameData(Item));
+}
+
+void DIAEnumFrameData::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
new file mode 100644
index 0000000..6c361b8
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
@@ -0,0 +1,44 @@
+//==- DIAEnumSourceFiles.cpp - DIA Source File Enumerator impl ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumInjectedSources::DIAEnumInjectedSources(
+    CComPtr<IDiaEnumInjectedSources> DiaEnumerator)
+    : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumInjectedSources::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBInjectedSource>
+DIAEnumInjectedSources::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaInjectedSource> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
+}
+
+std::unique_ptr<IPDBInjectedSource> DIAEnumInjectedSources::getNext() {
+  CComPtr<IDiaInjectedSource> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
+}
+
+void DIAEnumInjectedSources::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp
new file mode 100644
index 0000000..0820d9d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp
@@ -0,0 +1,44 @@
+//==- DIAEnumLineNumbers.cpp - DIA Line Number Enumerator impl ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumLineNumbers::DIAEnumLineNumbers(
+    CComPtr<IDiaEnumLineNumbers> DiaEnumerator)
+    : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumLineNumbers::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBLineNumber>
+DIAEnumLineNumbers::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaLineNumber> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBLineNumber>(new DIALineNumber(Item));
+}
+
+std::unique_ptr<IPDBLineNumber> DIAEnumLineNumbers::getNext() {
+  CComPtr<IDiaLineNumber> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBLineNumber>(new DIALineNumber(Item));
+}
+
+void DIAEnumLineNumbers::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp
new file mode 100644
index 0000000..90c857a
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp
@@ -0,0 +1,47 @@
+//==- DIAEnumSectionContribs.cpp ---------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASectionContrib.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumSectionContribs::DIAEnumSectionContribs(
+    const DIASession &PDBSession,
+    CComPtr<IDiaEnumSectionContribs> DiaEnumerator)
+    : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSectionContribs::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBSectionContrib>
+DIAEnumSectionContribs::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaSectionContrib> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBSectionContrib>(
+      new DIASectionContrib(Session, Item));
+}
+
+std::unique_ptr<IPDBSectionContrib> DIAEnumSectionContribs::getNext() {
+  CComPtr<IDiaSectionContrib> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBSectionContrib>(
+      new DIASectionContrib(Session, Item));
+}
+
+void DIAEnumSectionContribs::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp
new file mode 100644
index 0000000..06595e7
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp
@@ -0,0 +1,44 @@
+//==- DIAEnumSourceFiles.cpp - DIA Source File Enumerator impl ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumSourceFiles::DIAEnumSourceFiles(
+    const DIASession &PDBSession, CComPtr<IDiaEnumSourceFiles> DiaEnumerator)
+    : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSourceFiles::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBSourceFile>
+DIAEnumSourceFiles::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaSourceFile> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBSourceFile>(new DIASourceFile(Session, Item));
+}
+
+std::unique_ptr<IPDBSourceFile> DIAEnumSourceFiles::getNext() {
+  CComPtr<IDiaSourceFile> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBSourceFile>(new DIASourceFile(Session, Item));
+}
+
+void DIAEnumSourceFiles::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp
new file mode 100644
index 0000000..48bc327
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp
@@ -0,0 +1,48 @@
+//==- DIAEnumSymbols.cpp - DIA Symbol Enumerator impl ------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumSymbols::DIAEnumSymbols(const DIASession &PDBSession,
+                               CComPtr<IDiaEnumSymbols> DiaEnumerator)
+    : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSymbols::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<PDBSymbol>
+DIAEnumSymbols::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaSymbol> Item;
+  if (S_OK != Enumerator->Item(Index, &Item))
+    return nullptr;
+
+  std::unique_ptr<DIARawSymbol> RawSymbol(new DIARawSymbol(Session, Item));
+  return std::unique_ptr<PDBSymbol>(PDBSymbol::create(Session, std::move(RawSymbol)));
+}
+
+std::unique_ptr<PDBSymbol> DIAEnumSymbols::getNext() {
+  CComPtr<IDiaSymbol> Item;
+  ULONG NumFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+    return nullptr;
+
+  std::unique_ptr<DIARawSymbol> RawSymbol(new DIARawSymbol(Session, Item));
+  return std::unique_ptr<PDBSymbol>(
+      PDBSymbol::create(Session, std::move(RawSymbol)));
+}
+
+void DIAEnumSymbols::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp
new file mode 100644
index 0000000..6fa0961
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp
@@ -0,0 +1,45 @@
+//===- DIAEnumTables.cpp - DIA Table Enumerator Impl ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h"
+#include "llvm/DebugInfo/PDB/DIA/DIATable.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumTables::DIAEnumTables(CComPtr<IDiaEnumTables> DiaEnumerator)
+    : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumTables::getChildCount() const {
+  LONG Count = 0;
+  return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBTable>
+DIAEnumTables::getChildAtIndex(uint32_t Index) const {
+  CComPtr<IDiaTable> Item;
+  VARIANT Var;
+  Var.vt = VT_UINT;
+  Var.uintVal = Index;
+  if (S_OK != Enumerator->Item(Var, &Item))
+    return nullptr;
+
+  return std::unique_ptr<IPDBTable>(new DIATable(Item));
+}
+
+std::unique_ptr<IPDBTable> DIAEnumTables::getNext() {
+  CComPtr<IDiaTable> Item;
+  ULONG CeltFetched = 0;
+  if (S_OK != Enumerator->Next(1, &Item, &CeltFetched))
+    return nullptr;
+
+  return std::unique_ptr<IPDBTable>(new DIATable(Item));
+}
+
+void DIAEnumTables::reset() { Enumerator->Reset(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp
new file mode 100644
index 0000000..819651f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAError.cpp
@@ -0,0 +1,37 @@
+#include "llvm/DebugInfo/PDB/DIA/DIAError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class DIAErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.pdb.dia"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<dia_error_code>(Condition)) {
+    case dia_error_code::could_not_create_impl:
+      return "Failed to connect to DIA at runtime. Verify that Visual Studio "
+             "is properly installed, or that msdiaXX.dll is in your PATH.";
+    case dia_error_code::invalid_file_format:
+      return "Unable to load PDB. The file has an unrecognized format.";
+    case dia_error_code::invalid_parameter:
+      return "The parameter is incorrect.";
+    case dia_error_code::already_loaded:
+      return "Unable to load the PDB or EXE, because it is already loaded.";
+    case dia_error_code::debug_info_mismatch:
+      return "The PDB file and the EXE file do not match.";
+    case dia_error_code::unspecified:
+      return "An unknown error has occurred.";
+    }
+    llvm_unreachable("Unrecognized DIAErrorCode");
+  }
+};
+
+static llvm::ManagedStatic<DIAErrorCategory> DIACategory;
+const std::error_category &llvm::pdb::DIAErrCategory() { return *DIACategory; }
+
+char DIAError::ID;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp
new file mode 100644
index 0000000..533cce7
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp
@@ -0,0 +1,53 @@
+//===- DIAFrameData.cpp - DIA impl. of IPDBFrameData -------------- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAFrameData.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+
+using namespace llvm::pdb;
+
+DIAFrameData::DIAFrameData(CComPtr<IDiaFrameData> DiaFrameData)
+    : FrameData(DiaFrameData) {}
+
+template <typename ArgType>
+ArgType
+PrivateGetDIAValue(IDiaFrameData *FrameData,
+                   HRESULT (__stdcall IDiaFrameData::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (FrameData->*Method)(&Value))
+    return static_cast<ArgType>(Value);
+
+  return ArgType();
+}
+
+uint32_t DIAFrameData::getAddressOffset() const {
+  return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_addressOffset);
+}
+
+uint32_t DIAFrameData::getAddressSection() const {
+  return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_addressSection);
+}
+
+uint32_t DIAFrameData::getLengthBlock() const {
+  return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_lengthBlock);
+}
+
+std::string DIAFrameData::getProgram() const {
+  return invokeBstrMethod(*FrameData, &IDiaFrameData::get_program);
+}
+
+uint32_t DIAFrameData::getRelativeVirtualAddress() const {
+  return PrivateGetDIAValue(FrameData,
+                            &IDiaFrameData::get_relativeVirtualAddress);
+}
+
+uint64_t DIAFrameData::getVirtualAddress() const {
+  return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_virtualAddress);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
new file mode 100644
index 0000000..1d642f2
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
@@ -0,0 +1,63 @@
+//===- DIAInjectedSource.cpp - DIA impl for IPDBInjectedSource --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAInjectedSource::DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile)
+    : SourceFile(DiaSourceFile) {}
+
+uint32_t DIAInjectedSource::getCrc32() const {
+  DWORD Crc;
+  return (S_OK == SourceFile->get_crc(&Crc)) ? Crc : 0;
+}
+
+uint64_t DIAInjectedSource::getCodeByteSize() const {
+  ULONGLONG Size;
+  return (S_OK == SourceFile->get_length(&Size)) ? Size : 0;
+}
+
+std::string DIAInjectedSource::getFileName() const {
+  return invokeBstrMethod(*SourceFile, &IDiaInjectedSource::get_filename);
+}
+
+std::string DIAInjectedSource::getObjectFileName() const {
+  return invokeBstrMethod(*SourceFile, &IDiaInjectedSource::get_objectFilename);
+}
+
+std::string DIAInjectedSource::getVirtualFileName() const {
+  return invokeBstrMethod(*SourceFile,
+                          &IDiaInjectedSource::get_virtualFilename);
+}
+
+PDB_SourceCompression DIAInjectedSource::getCompression() const {
+  DWORD Compression = 0;
+  if (S_OK != SourceFile->get_sourceCompression(&Compression))
+    return PDB_SourceCompression::None;
+  return static_cast<PDB_SourceCompression>(Compression);
+}
+
+std::string DIAInjectedSource::getCode() const {
+  DWORD DataSize;
+  if (S_OK != SourceFile->get_source(0, &DataSize, nullptr))
+    return "";
+
+  std::vector<uint8_t> Buffer(DataSize);
+  if (S_OK != SourceFile->get_source(DataSize, &DataSize, Buffer.data()))
+    return "";
+  assert(Buffer.size() == DataSize);
+  return std::string(reinterpret_cast<const char *>(Buffer.data()),
+                     Buffer.size());
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp
new file mode 100644
index 0000000..b19be6b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp
@@ -0,0 +1,76 @@
+//===- DIALineNumber.cpp - DIA implementation of IPDBLineNumber -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIALineNumber::DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber)
+    : LineNumber(DiaLineNumber) {}
+
+uint32_t DIALineNumber::getLineNumber() const {
+  DWORD Line = 0;
+  return (S_OK == LineNumber->get_lineNumber(&Line)) ? Line : 0;
+}
+
+uint32_t DIALineNumber::getLineNumberEnd() const {
+  DWORD LineEnd = 0;
+  return (S_OK == LineNumber->get_lineNumberEnd(&LineEnd)) ? LineEnd : 0;
+}
+
+uint32_t DIALineNumber::getColumnNumber() const {
+  DWORD Column = 0;
+  return (S_OK == LineNumber->get_columnNumber(&Column)) ? Column : 0;
+}
+
+uint32_t DIALineNumber::getColumnNumberEnd() const {
+  DWORD ColumnEnd = 0;
+  return (S_OK == LineNumber->get_columnNumberEnd(&ColumnEnd)) ? ColumnEnd : 0;
+}
+
+uint32_t DIALineNumber::getAddressSection() const {
+  DWORD Section = 0;
+  return (S_OK == LineNumber->get_addressSection(&Section)) ? Section : 0;
+}
+
+uint32_t DIALineNumber::getAddressOffset() const {
+  DWORD Offset = 0;
+  return (S_OK == LineNumber->get_addressOffset(&Offset)) ? Offset : 0;
+}
+
+uint32_t DIALineNumber::getRelativeVirtualAddress() const {
+  DWORD RVA = 0;
+  return (S_OK == LineNumber->get_relativeVirtualAddress(&RVA)) ? RVA : 0;
+}
+
+uint64_t DIALineNumber::getVirtualAddress() const {
+  ULONGLONG Addr = 0;
+  return (S_OK == LineNumber->get_virtualAddress(&Addr)) ? Addr : 0;
+}
+
+uint32_t DIALineNumber::getLength() const {
+  DWORD Length = 0;
+  return (S_OK == LineNumber->get_length(&Length)) ? Length : 0;
+}
+
+uint32_t DIALineNumber::getSourceFileId() const {
+  DWORD Id = 0;
+  return (S_OK == LineNumber->get_sourceFileId(&Id)) ? Id : 0;
+}
+
+uint32_t DIALineNumber::getCompilandId() const {
+  DWORD Id = 0;
+  return (S_OK == LineNumber->get_compilandId(&Id)) ? Id : 0;
+}
+
+bool DIALineNumber::isStatement() const {
+  BOOL Statement = 0;
+  return (S_OK == LineNumber->get_statement(&Statement)) ? Statement : false;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
new file mode 100644
index 0000000..cd4d00a
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -0,0 +1,1271 @@
+//===- DIARawSymbol.cpp - DIA implementation of IPDBRawSymbol ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace {
+Variant VariantFromVARIANT(const VARIANT &V) {
+  Variant Result;
+  switch (V.vt) {
+  case VT_I1:
+    Result.Value.Int8 = V.cVal;
+    Result.Type = PDB_VariantType::Int8;
+    break;
+  case VT_I2:
+    Result.Value.Int16 = V.iVal;
+    Result.Type = PDB_VariantType::Int16;
+    break;
+  case VT_I4:
+    Result.Value.Int32 = V.intVal;
+    Result.Type = PDB_VariantType::Int32;
+    break;
+  case VT_I8:
+    Result.Value.Int64 = V.llVal;
+    Result.Type = PDB_VariantType::Int64;
+    break;
+  case VT_UI1:
+    Result.Value.UInt8 = V.bVal;
+    Result.Type = PDB_VariantType::UInt8;
+    break;
+  case VT_UI2:
+    Result.Value.UInt16 = V.uiVal;
+    Result.Type = PDB_VariantType::UInt16;
+    break;
+  case VT_UI4:
+    Result.Value.UInt32 = V.uintVal;
+    Result.Type = PDB_VariantType::UInt32;
+    break;
+  case VT_UI8:
+    Result.Value.UInt64 = V.ullVal;
+    Result.Type = PDB_VariantType::UInt64;
+    break;
+  case VT_BOOL:
+    Result.Value.Bool = (V.boolVal == VARIANT_TRUE) ? true : false;
+    Result.Type = PDB_VariantType::Bool;
+    break;
+  case VT_R4:
+    Result.Value.Single = V.fltVal;
+    Result.Type = PDB_VariantType::Single;
+    break;
+  case VT_R8:
+    Result.Value.Double = V.dblVal;
+    Result.Type = PDB_VariantType::Double;
+    break;
+  case VT_BSTR: {
+    const char *SrcBytes = reinterpret_cast<const char *>(V.bstrVal);
+    llvm::ArrayRef<char> SrcByteArray(SrcBytes, SysStringByteLen(V.bstrVal));
+    std::string Result8;
+    if (!llvm::convertUTF16ToUTF8String(SrcByteArray, Result8))
+      Result.Value.String = nullptr;
+    Result.Value.String = new char[Result8.length() + 1];
+    ::strcpy(Result.Value.String, Result8.c_str());
+    Result.Type = PDB_VariantType::String;
+    break;
+  }
+  default:
+    Result.Type = PDB_VariantType::Unknown;
+    break;
+  }
+  return Result;
+}
+
+template <typename ArgType>
+ArgType PrivateGetDIAValue(IDiaSymbol *Symbol,
+                           HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    return static_cast<ArgType>(Value);
+
+  return ArgType();
+}
+
+template <typename ArgType, typename RetType>
+RetType PrivateGetDIAValue(IDiaSymbol *Symbol,
+                           HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    return static_cast<RetType>(Value);
+
+  return RetType();
+}
+
+std::string
+PrivateGetDIAValue(IDiaSymbol *Symbol,
+                   HRESULT (__stdcall IDiaSymbol::*Method)(BSTR *)) {
+  return invokeBstrMethod(*Symbol, Method);
+}
+
+codeview::GUID
+PrivateGetDIAValue(IDiaSymbol *Symbol,
+                   HRESULT (__stdcall IDiaSymbol::*Method)(GUID *)) {
+  GUID Result;
+  if (S_OK != (Symbol->*Method)(&Result))
+    return codeview::GUID();
+
+  static_assert(sizeof(codeview::GUID) == sizeof(GUID),
+                "GUID is the wrong size!");
+  codeview::GUID IdResult;
+  ::memcpy(&IdResult, &Result, sizeof(GUID));
+  return IdResult;
+}
+
+template <typename PrintType, typename ArgType>
+void DumpDIAValueAs(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                    IDiaSymbol *Symbol,
+                    HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    dumpSymbolField(OS, Name, static_cast<PrintType>(Value), Indent);
+}
+
+void DumpDIAIdValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                    IDiaSymbol *Symbol,
+                    HRESULT (__stdcall IDiaSymbol::*Method)(DWORD *),
+                    const IPDBSession &Session, PdbSymbolIdField FieldId,
+                    PdbSymbolIdField ShowFlags, PdbSymbolIdField RecurseFlags) {
+  DWORD Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    dumpSymbolIdField(OS, Name, Value, Indent, Session, FieldId, ShowFlags,
+                      RecurseFlags);
+}
+
+template <typename ArgType>
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                  IDiaSymbol *Symbol,
+                  HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    dumpSymbolField(OS, Name, Value, Indent);
+}
+
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                  IDiaSymbol *Symbol,
+                  HRESULT (__stdcall IDiaSymbol::*Method)(BSTR *)) {
+  BSTR Value = nullptr;
+  if (S_OK != (Symbol->*Method)(&Value))
+    return;
+  const char *Bytes = reinterpret_cast<const char *>(Value);
+  ArrayRef<char> ByteArray(Bytes, ::SysStringByteLen(Value));
+  std::string Result;
+  if (llvm::convertUTF16ToUTF8String(ByteArray, Result))
+    dumpSymbolField(OS, Name, Result, Indent);
+  ::SysFreeString(Value);
+}
+
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                  IDiaSymbol *Symbol,
+                  HRESULT (__stdcall IDiaSymbol::*Method)(VARIANT *)) {
+  VARIANT Value;
+  Value.vt = VT_EMPTY;
+  if (S_OK != (Symbol->*Method)(&Value))
+    return;
+  Variant V = VariantFromVARIANT(Value);
+
+  dumpSymbolField(OS, Name, V, Indent);
+}
+} // namespace
+
+namespace llvm {
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GUID &G) {
+  StringRef GuidBytes(reinterpret_cast<const char *>(&G), sizeof(G));
+  codeview::detail::GuidAdapter A(GuidBytes);
+  A.format(OS, "");
+  return OS;
+}
+} // namespace llvm
+
+DIARawSymbol::DIARawSymbol(const DIASession &PDBSession,
+                           CComPtr<IDiaSymbol> DiaSymbol)
+    : Session(PDBSession), Symbol(DiaSymbol) {}
+
+#define RAW_ID_METHOD_DUMP(Stream, Method, Session, FieldId, ShowFlags,        \
+                           RecurseFlags)                                       \
+  DumpDIAIdValue(Stream, Indent, StringRef{#Method}, Symbol,                   \
+                 &IDiaSymbol::get_##Method, Session, FieldId, ShowFlags,       \
+                 RecurseFlags);
+
+#define RAW_METHOD_DUMP(Stream, Method)                                        \
+  DumpDIAValue(Stream, Indent, StringRef{#Method}, Symbol,                     \
+               &IDiaSymbol::get_##Method);
+
+#define RAW_METHOD_DUMP_AS(Stream, Method, Type)                               \
+  DumpDIAValueAs<Type>(Stream, Indent, StringRef{#Method}, Symbol,             \
+                       &IDiaSymbol::get_##Method);
+
+void DIARawSymbol::dump(raw_ostream &OS, int Indent,
+                        PdbSymbolIdField ShowIdFields,
+                        PdbSymbolIdField RecurseIdFields) const {
+  RAW_ID_METHOD_DUMP(OS, symIndexId, Session, PdbSymbolIdField::SymIndexId,
+                     ShowIdFields, RecurseIdFields);
+  RAW_METHOD_DUMP_AS(OS, symTag, PDB_SymType);
+
+  RAW_METHOD_DUMP(OS, access);
+  RAW_METHOD_DUMP(OS, addressOffset);
+  RAW_METHOD_DUMP(OS, addressSection);
+  RAW_METHOD_DUMP(OS, age);
+  RAW_METHOD_DUMP(OS, arrayIndexTypeId);
+  RAW_METHOD_DUMP(OS, backEndMajor);
+  RAW_METHOD_DUMP(OS, backEndMinor);
+  RAW_METHOD_DUMP(OS, backEndBuild);
+  RAW_METHOD_DUMP(OS, backEndQFE);
+  RAW_METHOD_DUMP(OS, baseDataOffset);
+  RAW_METHOD_DUMP(OS, baseDataSlot);
+  RAW_METHOD_DUMP(OS, baseSymbolId);
+  RAW_METHOD_DUMP_AS(OS, baseType, PDB_BuiltinType);
+  RAW_METHOD_DUMP(OS, bitPosition);
+  RAW_METHOD_DUMP_AS(OS, callingConvention, PDB_CallingConv);
+  RAW_ID_METHOD_DUMP(OS, classParentId, Session, PdbSymbolIdField::ClassParent,
+                     ShowIdFields, RecurseIdFields);
+  RAW_METHOD_DUMP(OS, compilerName);
+  RAW_METHOD_DUMP(OS, count);
+  RAW_METHOD_DUMP(OS, countLiveRanges);
+  RAW_METHOD_DUMP(OS, frontEndMajor);
+  RAW_METHOD_DUMP(OS, frontEndMinor);
+  RAW_METHOD_DUMP(OS, frontEndBuild);
+  RAW_METHOD_DUMP(OS, frontEndQFE);
+  RAW_ID_METHOD_DUMP(OS, lexicalParentId, Session,
+                     PdbSymbolIdField::LexicalParent, ShowIdFields,
+                     RecurseIdFields);
+  RAW_METHOD_DUMP(OS, libraryName);
+  RAW_METHOD_DUMP(OS, liveRangeStartAddressOffset);
+  RAW_METHOD_DUMP(OS, liveRangeStartAddressSection);
+  RAW_METHOD_DUMP(OS, liveRangeStartRelativeVirtualAddress);
+  RAW_METHOD_DUMP(OS, localBasePointerRegisterId);
+  RAW_METHOD_DUMP(OS, lowerBoundId);
+  RAW_METHOD_DUMP(OS, memorySpaceKind);
+  RAW_METHOD_DUMP(OS, name);
+  RAW_METHOD_DUMP(OS, numberOfAcceleratorPointerTags);
+  RAW_METHOD_DUMP(OS, numberOfColumns);
+  RAW_METHOD_DUMP(OS, numberOfModifiers);
+  RAW_METHOD_DUMP(OS, numberOfRegisterIndices);
+  RAW_METHOD_DUMP(OS, numberOfRows);
+  RAW_METHOD_DUMP(OS, objectFileName);
+  RAW_METHOD_DUMP(OS, oemId);
+  RAW_METHOD_DUMP(OS, oemSymbolId);
+  RAW_METHOD_DUMP(OS, offsetInUdt);
+  RAW_METHOD_DUMP(OS, platform);
+  RAW_METHOD_DUMP(OS, rank);
+  RAW_METHOD_DUMP(OS, registerId);
+  RAW_METHOD_DUMP(OS, registerType);
+  RAW_METHOD_DUMP(OS, relativeVirtualAddress);
+  RAW_METHOD_DUMP(OS, samplerSlot);
+  RAW_METHOD_DUMP(OS, signature);
+  RAW_METHOD_DUMP(OS, sizeInUdt);
+  RAW_METHOD_DUMP(OS, slot);
+  RAW_METHOD_DUMP(OS, sourceFileName);
+  RAW_METHOD_DUMP(OS, stride);
+  RAW_METHOD_DUMP(OS, subTypeId);
+  RAW_METHOD_DUMP(OS, symbolsFileName);
+  RAW_METHOD_DUMP(OS, targetOffset);
+  RAW_METHOD_DUMP(OS, targetRelativeVirtualAddress);
+  RAW_METHOD_DUMP(OS, targetVirtualAddress);
+  RAW_METHOD_DUMP(OS, targetSection);
+  RAW_METHOD_DUMP(OS, textureSlot);
+  RAW_METHOD_DUMP(OS, timeStamp);
+  RAW_METHOD_DUMP(OS, token);
+  RAW_ID_METHOD_DUMP(OS, typeId, Session, PdbSymbolIdField::Type, ShowIdFields,
+                     RecurseIdFields);
+  RAW_METHOD_DUMP(OS, uavSlot);
+  RAW_METHOD_DUMP(OS, undecoratedName);
+  RAW_ID_METHOD_DUMP(OS, unmodifiedTypeId, Session,
+                     PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+                     RecurseIdFields);
+  RAW_METHOD_DUMP(OS, upperBoundId);
+  RAW_METHOD_DUMP(OS, virtualBaseDispIndex);
+  RAW_METHOD_DUMP(OS, virtualBaseOffset);
+  RAW_METHOD_DUMP(OS, virtualTableShapeId);
+  RAW_METHOD_DUMP_AS(OS, dataKind, PDB_DataKind);
+  RAW_METHOD_DUMP(OS, guid);
+  RAW_METHOD_DUMP(OS, offset);
+  RAW_METHOD_DUMP(OS, thisAdjust);
+  RAW_METHOD_DUMP(OS, virtualBasePointerOffset);
+  RAW_METHOD_DUMP_AS(OS, locationType, PDB_LocType);
+  RAW_METHOD_DUMP(OS, machineType);
+  RAW_METHOD_DUMP(OS, thunkOrdinal);
+  RAW_METHOD_DUMP(OS, length);
+  RAW_METHOD_DUMP(OS, liveRangeLength);
+  RAW_METHOD_DUMP(OS, virtualAddress);
+  RAW_METHOD_DUMP_AS(OS, udtKind, PDB_UdtType);
+  RAW_METHOD_DUMP(OS, constructor);
+  RAW_METHOD_DUMP(OS, customCallingConvention);
+  RAW_METHOD_DUMP(OS, farReturn);
+  RAW_METHOD_DUMP(OS, code);
+  RAW_METHOD_DUMP(OS, compilerGenerated);
+  RAW_METHOD_DUMP(OS, constType);
+  RAW_METHOD_DUMP(OS, editAndContinueEnabled);
+  RAW_METHOD_DUMP(OS, function);
+  RAW_METHOD_DUMP(OS, stride);
+  RAW_METHOD_DUMP(OS, noStackOrdering);
+  RAW_METHOD_DUMP(OS, hasAlloca);
+  RAW_METHOD_DUMP(OS, hasAssignmentOperator);
+  RAW_METHOD_DUMP(OS, isCTypes);
+  RAW_METHOD_DUMP(OS, hasCastOperator);
+  RAW_METHOD_DUMP(OS, hasDebugInfo);
+  RAW_METHOD_DUMP(OS, hasEH);
+  RAW_METHOD_DUMP(OS, hasEHa);
+  RAW_METHOD_DUMP(OS, hasInlAsm);
+  RAW_METHOD_DUMP(OS, framePointerPresent);
+  RAW_METHOD_DUMP(OS, inlSpec);
+  RAW_METHOD_DUMP(OS, interruptReturn);
+  RAW_METHOD_DUMP(OS, hasLongJump);
+  RAW_METHOD_DUMP(OS, hasManagedCode);
+  RAW_METHOD_DUMP(OS, hasNestedTypes);
+  RAW_METHOD_DUMP(OS, noInline);
+  RAW_METHOD_DUMP(OS, noReturn);
+  RAW_METHOD_DUMP(OS, optimizedCodeDebugInfo);
+  RAW_METHOD_DUMP(OS, overloadedOperator);
+  RAW_METHOD_DUMP(OS, hasSEH);
+  RAW_METHOD_DUMP(OS, hasSecurityChecks);
+  RAW_METHOD_DUMP(OS, hasSetJump);
+  RAW_METHOD_DUMP(OS, strictGSCheck);
+  RAW_METHOD_DUMP(OS, isAcceleratorGroupSharedLocal);
+  RAW_METHOD_DUMP(OS, isAcceleratorPointerTagLiveRange);
+  RAW_METHOD_DUMP(OS, isAcceleratorStubFunction);
+  RAW_METHOD_DUMP(OS, isAggregated);
+  RAW_METHOD_DUMP(OS, intro);
+  RAW_METHOD_DUMP(OS, isCVTCIL);
+  RAW_METHOD_DUMP(OS, isConstructorVirtualBase);
+  RAW_METHOD_DUMP(OS, isCxxReturnUdt);
+  RAW_METHOD_DUMP(OS, isDataAligned);
+  RAW_METHOD_DUMP(OS, isHLSLData);
+  RAW_METHOD_DUMP(OS, isHotpatchable);
+  RAW_METHOD_DUMP(OS, indirectVirtualBaseClass);
+  RAW_METHOD_DUMP(OS, isInterfaceUdt);
+  RAW_METHOD_DUMP(OS, intrinsic);
+  RAW_METHOD_DUMP(OS, isLTCG);
+  RAW_METHOD_DUMP(OS, isLocationControlFlowDependent);
+  RAW_METHOD_DUMP(OS, isMSILNetmodule);
+  RAW_METHOD_DUMP(OS, isMatrixRowMajor);
+  RAW_METHOD_DUMP(OS, managed);
+  RAW_METHOD_DUMP(OS, msil);
+  RAW_METHOD_DUMP(OS, isMultipleInheritance);
+  RAW_METHOD_DUMP(OS, isNaked);
+  RAW_METHOD_DUMP(OS, nested);
+  RAW_METHOD_DUMP(OS, isOptimizedAway);
+  RAW_METHOD_DUMP(OS, packed);
+  RAW_METHOD_DUMP(OS, isPointerBasedOnSymbolValue);
+  RAW_METHOD_DUMP(OS, isPointerToDataMember);
+  RAW_METHOD_DUMP(OS, isPointerToMemberFunction);
+  RAW_METHOD_DUMP(OS, pure);
+  RAW_METHOD_DUMP(OS, RValueReference);
+  RAW_METHOD_DUMP(OS, isRefUdt);
+  RAW_METHOD_DUMP(OS, reference);
+  RAW_METHOD_DUMP(OS, restrictedType);
+  RAW_METHOD_DUMP(OS, isReturnValue);
+  RAW_METHOD_DUMP(OS, isSafeBuffers);
+  RAW_METHOD_DUMP(OS, scoped);
+  RAW_METHOD_DUMP(OS, isSdl);
+  RAW_METHOD_DUMP(OS, isSingleInheritance);
+  RAW_METHOD_DUMP(OS, isSplitted);
+  RAW_METHOD_DUMP(OS, isStatic);
+  RAW_METHOD_DUMP(OS, isStripped);
+  RAW_METHOD_DUMP(OS, unalignedType);
+  RAW_METHOD_DUMP(OS, notReached);
+  RAW_METHOD_DUMP(OS, isValueUdt);
+  RAW_METHOD_DUMP(OS, virtual);
+  RAW_METHOD_DUMP(OS, virtualBaseClass);
+  RAW_METHOD_DUMP(OS, isVirtualInheritance);
+  RAW_METHOD_DUMP(OS, volatileType);
+  RAW_METHOD_DUMP(OS, wasInlined);
+  RAW_METHOD_DUMP(OS, unused);
+  RAW_METHOD_DUMP(OS, value);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildren(PDB_SymType Type) const {
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK !=
+      Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) {
+    if (S_OK != Symbol->findChildren(EnumVal, nullptr, nsNone, &DiaEnumerator))
+      return nullptr;
+  }
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildren(PDB_SymType Type, StringRef Name,
+                           PDB_NameSearchFlags Flags) const {
+  llvm::SmallVector<UTF16, 32> Name16;
+  llvm::convertUTF8ToUTF16String(Name, Name16);
+
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+  DWORD CompareFlags = static_cast<DWORD>(Flags);
+  wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK !=
+      Symbol->findChildrenEx(EnumVal, Name16Str, CompareFlags, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
+                                 PDB_NameSearchFlags Flags, uint32_t Section,
+                                 uint32_t Offset) const {
+  llvm::SmallVector<UTF16, 32> Name16;
+  llvm::convertUTF8ToUTF16String(Name, Name16);
+
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  DWORD CompareFlags = static_cast<DWORD>(Flags);
+  wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findChildrenExByAddr(EnumVal, Name16Str, CompareFlags,
+                                           Section, Offset, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
+                               PDB_NameSearchFlags Flags, uint64_t VA) const {
+  llvm::SmallVector<UTF16, 32> Name16;
+  llvm::convertUTF8ToUTF16String(Name, Name16);
+
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  DWORD CompareFlags = static_cast<DWORD>(Flags);
+  wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findChildrenExByVA(EnumVal, Name16Str, CompareFlags, VA,
+                                         &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+                                PDB_NameSearchFlags Flags, uint32_t RVA) const {
+  llvm::SmallVector<UTF16, 32> Name16;
+  llvm::convertUTF8ToUTF16String(Name, Name16);
+
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+  DWORD CompareFlags = static_cast<DWORD>(Flags);
+  wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findChildrenExByRVA(EnumVal, Name16Str, CompareFlags, RVA,
+                                          &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const {
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findInlineFramesByAddr(Section, Offset, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findInlineFramesByRVA(RVA, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByVA(uint64_t VA) const {
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  if (S_OK != Symbol->findInlineFramesByVA(VA, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers> DIARawSymbol::findInlineeLines() const {
+  CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+  if (S_OK != Symbol->findInlineeLines(&DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+                                     uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+  if (S_OK !=
+      Symbol->findInlineeLinesByAddr(Section, Offset, Length, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+  if (S_OK != Symbol->findInlineeLinesByRVA(RVA, Length, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+  if (S_OK != Symbol->findInlineeLinesByVA(VA, Length, &DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+void DIARawSymbol::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const {
+  bytes.clear();
+
+  DWORD DataSize = 0;
+  Symbol->get_dataBytes(0, &DataSize, nullptr);
+  if (DataSize == 0)
+    return;
+
+  bytes.resize(DataSize);
+  Symbol->get_dataBytes(DataSize, &DataSize, bytes.data());
+}
+
+std::string DIARawSymbol::getUndecoratedNameEx(PDB_UndnameFlags Flags) const {
+  CComBSTR Result16;
+  if (S_OK != Symbol->get_undecoratedNameEx((DWORD)Flags, &Result16))
+    return std::string();
+
+  const char *SrcBytes = reinterpret_cast<const char *>(Result16.m_str);
+  llvm::ArrayRef<char> SrcByteArray(SrcBytes, Result16.ByteLength());
+  std::string Result8;
+  if (!llvm::convertUTF16ToUTF8String(SrcByteArray, Result8))
+    return std::string();
+  return Result8;
+}
+
+PDB_MemberAccess DIARawSymbol::getAccess() const {
+  return PrivateGetDIAValue<DWORD, PDB_MemberAccess>(Symbol,
+                                                     &IDiaSymbol::get_access);
+}
+
+uint32_t DIARawSymbol::getAddressOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressOffset);
+}
+
+uint32_t DIARawSymbol::getAddressSection() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressSection);
+}
+
+uint32_t DIARawSymbol::getAge() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_age);
+}
+
+SymIndexId DIARawSymbol::getArrayIndexTypeId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_arrayIndexTypeId);
+}
+
+void DIARawSymbol::getBackEndVersion(VersionInfo &Version) const {
+  Version.Major = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndMajor);
+  Version.Minor = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndMinor);
+  Version.Build = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndBuild);
+  Version.QFE = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndQFE);
+}
+
+uint32_t DIARawSymbol::getBaseDataOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseDataOffset);
+}
+
+uint32_t DIARawSymbol::getBaseDataSlot() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseDataSlot);
+}
+
+SymIndexId DIARawSymbol::getBaseSymbolId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseSymbolId);
+}
+
+PDB_BuiltinType DIARawSymbol::getBuiltinType() const {
+  return PrivateGetDIAValue<DWORD, PDB_BuiltinType>(Symbol,
+                                                    &IDiaSymbol::get_baseType);
+}
+
+uint32_t DIARawSymbol::getBitPosition() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_bitPosition);
+}
+
+PDB_CallingConv DIARawSymbol::getCallingConvention() const {
+  return PrivateGetDIAValue<DWORD, PDB_CallingConv>(
+      Symbol, &IDiaSymbol::get_callingConvention);
+}
+
+SymIndexId DIARawSymbol::getClassParentId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_classParentId);
+}
+
+std::string DIARawSymbol::getCompilerName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_compilerName);
+}
+
+uint32_t DIARawSymbol::getCount() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_count);
+}
+
+uint32_t DIARawSymbol::getCountLiveRanges() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_countLiveRanges);
+}
+
+void DIARawSymbol::getFrontEndVersion(VersionInfo &Version) const {
+  Version.Major = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndMajor);
+  Version.Minor = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndMinor);
+  Version.Build = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndBuild);
+  Version.QFE = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndQFE);
+}
+
+PDB_Lang DIARawSymbol::getLanguage() const {
+  return PrivateGetDIAValue<DWORD, PDB_Lang>(Symbol, &IDiaSymbol::get_language);
+}
+
+SymIndexId DIARawSymbol::getLexicalParentId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lexicalParentId);
+}
+
+std::string DIARawSymbol::getLibraryName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_libraryName);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartAddressOffset() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_liveRangeStartAddressOffset);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartAddressSection() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_liveRangeStartAddressSection);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
+  return PrivateGetDIAValue(
+      Symbol, &IDiaSymbol::get_liveRangeStartRelativeVirtualAddress);
+}
+
+codeview::RegisterId DIARawSymbol::getLocalBasePointerRegisterId() const {
+  return PrivateGetDIAValue<DWORD, codeview::RegisterId>(
+      Symbol, &IDiaSymbol::get_localBasePointerRegisterId);
+}
+
+SymIndexId DIARawSymbol::getLowerBoundId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lowerBoundId);
+}
+
+uint32_t DIARawSymbol::getMemorySpaceKind() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_memorySpaceKind);
+}
+
+std::string DIARawSymbol::getName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_name);
+}
+
+uint32_t DIARawSymbol::getNumberOfAcceleratorPointerTags() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_numberOfAcceleratorPointerTags);
+}
+
+uint32_t DIARawSymbol::getNumberOfColumns() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfColumns);
+}
+
+uint32_t DIARawSymbol::getNumberOfModifiers() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfModifiers);
+}
+
+uint32_t DIARawSymbol::getNumberOfRegisterIndices() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfRegisterIndices);
+}
+
+uint32_t DIARawSymbol::getNumberOfRows() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfRows);
+}
+
+std::string DIARawSymbol::getObjectFileName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_objectFileName);
+}
+
+uint32_t DIARawSymbol::getOemId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemId);
+}
+
+SymIndexId DIARawSymbol::getOemSymbolId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemSymbolId);
+}
+
+uint32_t DIARawSymbol::getOffsetInUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_offsetInUdt);
+}
+
+PDB_Cpu DIARawSymbol::getPlatform() const {
+  return PrivateGetDIAValue<DWORD, PDB_Cpu>(Symbol, &IDiaSymbol::get_platform);
+}
+
+uint32_t DIARawSymbol::getRank() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_rank);
+}
+
+codeview::RegisterId DIARawSymbol::getRegisterId() const {
+  return PrivateGetDIAValue<DWORD, codeview::RegisterId>(
+      Symbol, &IDiaSymbol::get_registerId);
+}
+
+uint32_t DIARawSymbol::getRegisterType() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_registerType);
+}
+
+uint32_t DIARawSymbol::getRelativeVirtualAddress() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_relativeVirtualAddress);
+}
+
+uint32_t DIARawSymbol::getSamplerSlot() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_samplerSlot);
+}
+
+uint32_t DIARawSymbol::getSignature() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_signature);
+}
+
+uint32_t DIARawSymbol::getSizeInUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sizeInUdt);
+}
+
+uint32_t DIARawSymbol::getSlot() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_slot);
+}
+
+std::string DIARawSymbol::getSourceFileName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sourceFileName);
+}
+
+std::unique_ptr<IPDBLineNumber> DIARawSymbol::getSrcLineOnTypeDefn() const {
+  CComPtr<IDiaLineNumber> LineNumber;
+  if (FAILED(Symbol->getSrcLineOnTypeDefn(&LineNumber)) || !LineNumber)
+    return nullptr;
+
+  return llvm::make_unique<DIALineNumber>(LineNumber);
+}
+
+uint32_t DIARawSymbol::getStride() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_stride);
+}
+
+SymIndexId DIARawSymbol::getSubTypeId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_subTypeId);
+}
+
+std::string DIARawSymbol::getSymbolsFileName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symbolsFileName);
+}
+
+SymIndexId DIARawSymbol::getSymIndexId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symIndexId);
+}
+
+uint32_t DIARawSymbol::getTargetOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetOffset);
+}
+
+uint32_t DIARawSymbol::getTargetRelativeVirtualAddress() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_targetRelativeVirtualAddress);
+}
+
+uint64_t DIARawSymbol::getTargetVirtualAddress() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetVirtualAddress);
+}
+
+uint32_t DIARawSymbol::getTargetSection() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetSection);
+}
+
+uint32_t DIARawSymbol::getTextureSlot() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_textureSlot);
+}
+
+uint32_t DIARawSymbol::getTimeStamp() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_timeStamp);
+}
+
+uint32_t DIARawSymbol::getToken() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_token);
+}
+
+SymIndexId DIARawSymbol::getTypeId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_typeId);
+}
+
+uint32_t DIARawSymbol::getUavSlot() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_uavSlot);
+}
+
+std::string DIARawSymbol::getUndecoratedName() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_undecoratedName);
+}
+
+SymIndexId DIARawSymbol::getUnmodifiedTypeId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unmodifiedTypeId);
+}
+
+SymIndexId DIARawSymbol::getUpperBoundId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_upperBoundId);
+}
+
+Variant DIARawSymbol::getValue() const {
+  VARIANT Value;
+  Value.vt = VT_EMPTY;
+  if (S_OK != Symbol->get_value(&Value))
+    return Variant();
+
+  return VariantFromVARIANT(Value);
+}
+
+uint32_t DIARawSymbol::getVirtualBaseDispIndex() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseDispIndex);
+}
+
+uint32_t DIARawSymbol::getVirtualBaseOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseOffset);
+}
+
+SymIndexId DIARawSymbol::getVirtualTableShapeId() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId);
+}
+
+std::unique_ptr<PDBSymbolTypeBuiltin>
+DIARawSymbol::getVirtualBaseTableType() const {
+  CComPtr<IDiaSymbol> TableType;
+  if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType)
+    return nullptr;
+
+  auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType);
+  auto Pointer =
+      PDBSymbol::createAs<PDBSymbolTypePointer>(Session, std::move(RawVT));
+  return unique_dyn_cast<PDBSymbolTypeBuiltin>(Pointer->getPointeeType());
+}
+
+PDB_DataKind DIARawSymbol::getDataKind() const {
+  return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol,
+                                                 &IDiaSymbol::get_dataKind);
+}
+
+PDB_SymType DIARawSymbol::getSymTag() const {
+  return PrivateGetDIAValue<DWORD, PDB_SymType>(Symbol,
+                                                &IDiaSymbol::get_symTag);
+}
+
+codeview::GUID DIARawSymbol::getGuid() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_guid);
+}
+
+int32_t DIARawSymbol::getOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_offset);
+}
+
+int32_t DIARawSymbol::getThisAdjust() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_thisAdjust);
+}
+
+int32_t DIARawSymbol::getVirtualBasePointerOffset() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBasePointerOffset);
+}
+
+PDB_LocType DIARawSymbol::getLocationType() const {
+  return PrivateGetDIAValue<DWORD, PDB_LocType>(Symbol,
+                                                &IDiaSymbol::get_locationType);
+}
+
+PDB_Machine DIARawSymbol::getMachineType() const {
+  return PrivateGetDIAValue<DWORD, PDB_Machine>(Symbol,
+                                                &IDiaSymbol::get_machineType);
+}
+
+codeview::ThunkOrdinal DIARawSymbol::getThunkOrdinal() const {
+  return PrivateGetDIAValue<DWORD, codeview::ThunkOrdinal>(
+      Symbol, &IDiaSymbol::get_thunkOrdinal);
+}
+
+uint64_t DIARawSymbol::getLength() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_length);
+}
+
+uint64_t DIARawSymbol::getLiveRangeLength() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_liveRangeLength);
+}
+
+uint64_t DIARawSymbol::getVirtualAddress() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualAddress);
+}
+
+PDB_UdtType DIARawSymbol::getUdtKind() const {
+  return PrivateGetDIAValue<DWORD, PDB_UdtType>(Symbol,
+                                                &IDiaSymbol::get_udtKind);
+}
+
+bool DIARawSymbol::hasConstructor() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_constructor);
+}
+
+bool DIARawSymbol::hasCustomCallingConvention() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_customCallingConvention);
+}
+
+bool DIARawSymbol::hasFarReturn() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_farReturn);
+}
+
+bool DIARawSymbol::isCode() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_code);
+}
+
+bool DIARawSymbol::isCompilerGenerated() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_compilerGenerated);
+}
+
+bool DIARawSymbol::isConstType() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_constType);
+}
+
+bool DIARawSymbol::isEditAndContinueEnabled() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_editAndContinueEnabled);
+}
+
+bool DIARawSymbol::isFunction() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_function);
+}
+
+bool DIARawSymbol::getAddressTaken() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressTaken);
+}
+
+bool DIARawSymbol::getNoStackOrdering() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noStackOrdering);
+}
+
+bool DIARawSymbol::hasAlloca() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasAlloca);
+}
+
+bool DIARawSymbol::hasAssignmentOperator() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasAssignmentOperator);
+}
+
+bool DIARawSymbol::hasCTypes() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCTypes);
+}
+
+bool DIARawSymbol::hasCastOperator() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasCastOperator);
+}
+
+bool DIARawSymbol::hasDebugInfo() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasDebugInfo);
+}
+
+bool DIARawSymbol::hasEH() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasEH);
+}
+
+bool DIARawSymbol::hasEHa() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasEHa);
+}
+
+bool DIARawSymbol::hasInlAsm() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasInlAsm);
+}
+
+bool DIARawSymbol::hasInlineAttribute() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_inlSpec);
+}
+
+bool DIARawSymbol::hasInterruptReturn() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_interruptReturn);
+}
+
+bool DIARawSymbol::hasFramePointer() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_framePointerPresent);
+}
+
+bool DIARawSymbol::hasLongJump() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasLongJump);
+}
+
+bool DIARawSymbol::hasManagedCode() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasManagedCode);
+}
+
+bool DIARawSymbol::hasNestedTypes() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasNestedTypes);
+}
+
+bool DIARawSymbol::hasNoInlineAttribute() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noInline);
+}
+
+bool DIARawSymbol::hasNoReturnAttribute() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noReturn);
+}
+
+bool DIARawSymbol::hasOptimizedCodeDebugInfo() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_optimizedCodeDebugInfo);
+}
+
+bool DIARawSymbol::hasOverloadedOperator() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_overloadedOperator);
+}
+
+bool DIARawSymbol::hasSEH() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSEH);
+}
+
+bool DIARawSymbol::hasSecurityChecks() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSecurityChecks);
+}
+
+bool DIARawSymbol::hasSetJump() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSetJump);
+}
+
+bool DIARawSymbol::hasStrictGSCheck() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_strictGSCheck);
+}
+
+bool DIARawSymbol::isAcceleratorGroupSharedLocal() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_isAcceleratorGroupSharedLocal);
+}
+
+bool DIARawSymbol::isAcceleratorPointerTagLiveRange() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_isAcceleratorPointerTagLiveRange);
+}
+
+bool DIARawSymbol::isAcceleratorStubFunction() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isAcceleratorStubFunction);
+}
+
+bool DIARawSymbol::isAggregated() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isAggregated);
+}
+
+bool DIARawSymbol::isIntroVirtualFunction() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_intro);
+}
+
+bool DIARawSymbol::isCVTCIL() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCVTCIL);
+}
+
+bool DIARawSymbol::isConstructorVirtualBase() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isConstructorVirtualBase);
+}
+
+bool DIARawSymbol::isCxxReturnUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCxxReturnUdt);
+}
+
+bool DIARawSymbol::isDataAligned() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isDataAligned);
+}
+
+bool DIARawSymbol::isHLSLData() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isHLSLData);
+}
+
+bool DIARawSymbol::isHotpatchable() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isHotpatchable);
+}
+
+bool DIARawSymbol::isIndirectVirtualBaseClass() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_indirectVirtualBaseClass);
+}
+
+bool DIARawSymbol::isInterfaceUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isInterfaceUdt);
+}
+
+bool DIARawSymbol::isIntrinsic() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_intrinsic);
+}
+
+bool DIARawSymbol::isLTCG() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isLTCG);
+}
+
+bool DIARawSymbol::isLocationControlFlowDependent() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_isLocationControlFlowDependent);
+}
+
+bool DIARawSymbol::isMSILNetmodule() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMSILNetmodule);
+}
+
+bool DIARawSymbol::isMatrixRowMajor() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMatrixRowMajor);
+}
+
+bool DIARawSymbol::isManagedCode() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_managed);
+}
+
+bool DIARawSymbol::isMSILCode() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_msil);
+}
+
+bool DIARawSymbol::isMultipleInheritance() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMultipleInheritance);
+}
+
+bool DIARawSymbol::isNaked() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isNaked);
+}
+
+bool DIARawSymbol::isNested() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_nested);
+}
+
+bool DIARawSymbol::isOptimizedAway() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isOptimizedAway);
+}
+
+bool DIARawSymbol::isPacked() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_packed);
+}
+
+bool DIARawSymbol::isPointerBasedOnSymbolValue() const {
+  return PrivateGetDIAValue(Symbol,
+                            &IDiaSymbol::get_isPointerBasedOnSymbolValue);
+}
+
+bool DIARawSymbol::isPointerToDataMember() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isPointerToDataMember);
+}
+
+bool DIARawSymbol::isPointerToMemberFunction() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isPointerToMemberFunction);
+}
+
+bool DIARawSymbol::isPureVirtual() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_pure);
+}
+
+bool DIARawSymbol::isRValueReference() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_RValueReference);
+}
+
+bool DIARawSymbol::isRefUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isRefUdt);
+}
+
+bool DIARawSymbol::isReference() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_reference);
+}
+
+bool DIARawSymbol::isRestrictedType() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_restrictedType);
+}
+
+bool DIARawSymbol::isReturnValue() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isReturnValue);
+}
+
+bool DIARawSymbol::isSafeBuffers() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSafeBuffers);
+}
+
+bool DIARawSymbol::isScoped() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_scoped);
+}
+
+bool DIARawSymbol::isSdl() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSdl);
+}
+
+bool DIARawSymbol::isSingleInheritance() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSingleInheritance);
+}
+
+bool DIARawSymbol::isSplitted() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSplitted);
+}
+
+bool DIARawSymbol::isStatic() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isStatic);
+}
+
+bool DIARawSymbol::hasPrivateSymbols() const {
+  // hasPrivateSymbols is the opposite of isStripped, but we expose
+  // hasPrivateSymbols as a more intuitive interface.
+  return !PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isStripped);
+}
+
+bool DIARawSymbol::isUnalignedType() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unalignedType);
+}
+
+bool DIARawSymbol::isUnreached() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_notReached);
+}
+
+bool DIARawSymbol::isValueUdt() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isValueUdt);
+}
+
+bool DIARawSymbol::isVirtual() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtual);
+}
+
+bool DIARawSymbol::isVirtualBaseClass() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseClass);
+}
+
+bool DIARawSymbol::isVirtualInheritance() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isVirtualInheritance);
+}
+
+bool DIARawSymbol::isVolatileType() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_volatileType);
+}
+
+bool DIARawSymbol::wasInlined() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_wasInlined);
+}
+
+std::string DIARawSymbol::getUnused() const {
+  return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unused);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp
new file mode 100644
index 0000000..8e233ca
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp
@@ -0,0 +1,126 @@
+//===- DIASectionContrib.cpp - DIA impl. of IPDBSectionContrib ---- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIASectionContrib.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIASectionContrib::DIASectionContrib(const DIASession &PDBSession,
+                                     CComPtr<IDiaSectionContrib> DiaSection)
+  : Session(PDBSession), Section(DiaSection) {}
+
+std::unique_ptr<PDBSymbolCompiland> DIASectionContrib::getCompiland() const {
+  CComPtr<IDiaSymbol> Symbol;
+  if (FAILED(Section->get_compiland(&Symbol)))
+    return nullptr;
+
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(Session, Symbol);
+  return PDBSymbol::createAs<PDBSymbolCompiland>(Session, std::move(RawSymbol));
+}
+
+template <typename ArgType>
+ArgType
+PrivateGetDIAValue(IDiaSectionContrib *Section,
+                   HRESULT (__stdcall IDiaSectionContrib::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Section->*Method)(&Value))
+    return static_cast<ArgType>(Value);
+
+  return ArgType();
+}
+
+uint32_t DIASectionContrib::getAddressSection() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_addressSection);
+}
+
+uint32_t DIASectionContrib::getAddressOffset() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_addressOffset);
+}
+
+uint64_t DIASectionContrib::getVirtualAddress() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_virtualAddress);
+}
+
+uint32_t DIASectionContrib::getRelativeVirtualAddress() const {
+  return PrivateGetDIAValue(Section,
+                            &IDiaSectionContrib::get_relativeVirtualAddress);
+}
+
+uint32_t DIASectionContrib::getLength() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_length);
+}
+
+bool DIASectionContrib::isNotPaged() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_notPaged);
+}
+
+bool DIASectionContrib::hasCode() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_code);
+}
+
+bool DIASectionContrib::hasCode16Bit() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_code16bit);
+}
+
+bool DIASectionContrib::hasInitializedData() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_initializedData);
+}
+
+bool DIASectionContrib::hasUninitializedData() const {
+  return PrivateGetDIAValue(Section,
+                            &IDiaSectionContrib::get_uninitializedData);
+}
+
+bool DIASectionContrib::isRemoved() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_remove);
+}
+
+bool DIASectionContrib::hasComdat() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_comdat);
+}
+
+bool DIASectionContrib::isDiscardable() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_discardable);
+}
+
+bool DIASectionContrib::isNotCached() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_notCached);
+}
+
+bool DIASectionContrib::isShared() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_share);
+}
+
+bool DIASectionContrib::isExecutable() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_execute);
+}
+
+bool DIASectionContrib::isReadable() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_read);
+}
+
+bool DIASectionContrib::isWritable() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_write);
+}
+
+uint32_t DIASectionContrib::getDataCrc32() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_dataCrc);
+}
+
+uint32_t DIASectionContrib::getRelocationsCrc32() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_relocationsCrc);
+}
+
+uint32_t DIASectionContrib::getCompilandId() const {
+  return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_compilandId);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
new file mode 100644
index 0000000..bd375e1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -0,0 +1,432 @@
+//===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAError.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASupport.h"
+#include "llvm/DebugInfo/PDB/GenericError.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+template <typename... Ts>
+static Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) {
+  SmallString<64> MessageStorage;
+  StringRef Context;
+  if (sizeof...(Args) > 0) {
+    MessageStorage = formatv(Str, std::forward<Ts>(Args)...).str();
+    Context = MessageStorage;
+  } else
+    Context = Str;
+
+  switch (Result) {
+  case E_PDB_NOT_FOUND:
+    return errorCodeToError(std::error_code(ENOENT, std::generic_category()));
+  case E_PDB_FORMAT:
+    return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
+  case E_INVALIDARG:
+    return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
+  case E_UNEXPECTED:
+    return make_error<DIAError>(dia_error_code::already_loaded, Context);
+  case E_PDB_INVALID_SIG:
+  case E_PDB_INVALID_AGE:
+    return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
+  default: {
+    std::string S;
+    raw_string_ostream OS(S);
+    OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
+       << ": " << Context;
+    return make_error<DIAError>(dia_error_code::unspecified, OS.str());
+  }
+  }
+}
+
+static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
+  if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
+                                 IID_IDiaDataSource,
+                                 reinterpret_cast<LPVOID *>(&DiaDataSource))))
+    return Error::success();
+
+// If the CoCreateInstance call above failed, msdia*.dll is not registered.
+// Try loading the DLL corresponding to the #included DIA SDK.
+#if !defined(_MSC_VER)
+  return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading);
+#else
+  const wchar_t *msdia_dll = nullptr;
+#if _MSC_VER >= 1900 && _MSC_VER < 2000
+  msdia_dll = L"msdia140.dll"; // VS2015
+#elif _MSC_VER >= 1800
+  msdia_dll = L"msdia120.dll"; // VS2013
+#else
+#error "Unknown Visual Studio version."
+#endif
+
+  HRESULT HR;
+  if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
+                                reinterpret_cast<LPVOID *>(&DiaDataSource))))
+    return ErrorFromHResult(HR, "Calling NoRegCoCreate");
+  return Error::success();
+#endif
+}
+
+DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
+
+Error DIASession::createFromPdb(StringRef Path,
+                                std::unique_ptr<IPDBSession> &Session) {
+  CComPtr<IDiaDataSource> DiaDataSource;
+  CComPtr<IDiaSession> DiaSession;
+
+  // We assume that CoInitializeEx has already been called by the executable.
+  if (auto E = LoadDIA(DiaDataSource))
+    return E;
+
+  llvm::SmallVector<UTF16, 128> Path16;
+  if (!llvm::convertUTF8ToUTF16String(Path, Path16))
+    return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
+
+  const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
+  HRESULT HR;
+  if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) {
+    return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path);
+  }
+
+  if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
+    return ErrorFromHResult(HR, "Calling openSession");
+
+  Session.reset(new DIASession(DiaSession));
+  return Error::success();
+}
+
+Error DIASession::createFromExe(StringRef Path,
+                                std::unique_ptr<IPDBSession> &Session) {
+  CComPtr<IDiaDataSource> DiaDataSource;
+  CComPtr<IDiaSession> DiaSession;
+
+  // We assume that CoInitializeEx has already been called by the executable.
+  if (auto EC = LoadDIA(DiaDataSource))
+    return EC;
+
+  llvm::SmallVector<UTF16, 128> Path16;
+  if (!llvm::convertUTF8ToUTF16String(Path, Path16))
+    return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
+
+  const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
+  HRESULT HR;
+  if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
+    return ErrorFromHResult(HR, "Calling loadDataForExe");
+
+  if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
+    return ErrorFromHResult(HR, "Calling openSession");
+
+  Session.reset(new DIASession(DiaSession));
+  return Error::success();
+}
+
+uint64_t DIASession::getLoadAddress() const {
+  uint64_t LoadAddress;
+  bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
+  return (success) ? LoadAddress : 0;
+}
+
+bool DIASession::setLoadAddress(uint64_t Address) {
+  return (S_OK == Session->put_loadAddress(Address));
+}
+
+std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
+  CComPtr<IDiaSymbol> GlobalScope;
+  if (S_OK != Session->get_globalScope(&GlobalScope))
+    return nullptr;
+
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
+  auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
+  std::unique_ptr<PDBSymbolExe> ExeSymbol(
+      static_cast<PDBSymbolExe *>(PdbSymbol.release()));
+  return ExeSymbol;
+}
+
+bool DIASession::addressForVA(uint64_t VA, uint32_t &Section,
+                              uint32_t &Offset) const {
+  DWORD ArgSection, ArgOffset = 0;
+  if (S_OK == Session->addressForVA(VA, &ArgSection, &ArgOffset)) {
+    Section = static_cast<uint32_t>(ArgSection);
+    Offset = static_cast<uint32_t>(ArgOffset);
+    return true;
+  }
+  return false;
+}
+
+bool DIASession::addressForRVA(uint32_t RVA, uint32_t &Section,
+                               uint32_t &Offset) const {
+  DWORD ArgSection, ArgOffset = 0;
+  if (S_OK == Session->addressForRVA(RVA, &ArgSection, &ArgOffset)) {
+    Section = static_cast<uint32_t>(ArgSection);
+    Offset = static_cast<uint32_t>(ArgOffset);
+    return true;
+  }
+  return false;
+}
+
+std::unique_ptr<PDBSymbol>
+DIASession::getSymbolById(SymIndexId SymbolId) const {
+  CComPtr<IDiaSymbol> LocatedSymbol;
+  if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
+    return nullptr;
+
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
+  return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<PDBSymbol>
+DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  CComPtr<IDiaSymbol> Symbol;
+  if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
+    ULONGLONG LoadAddr = 0;
+    if (S_OK != Session->get_loadAddress(&LoadAddr))
+      return nullptr;
+    DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
+    if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
+      return nullptr;
+  }
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+  return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
+                                                       PDB_SymType Type) const {
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  CComPtr<IDiaSymbol> Symbol;
+  if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
+    return nullptr;
+
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+  return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<PDBSymbol>
+DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+                                   PDB_SymType Type) const {
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+  CComPtr<IDiaSymbol> Symbol;
+  if (S_OK != Session->findSymbolByAddr(Sect, Offset, EnumVal, &Symbol))
+    return nullptr;
+
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+  return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
+                            const IPDBSourceFile &File) const {
+  const DIARawSymbol &RawCompiland =
+      static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
+  const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
+
+  CComPtr<IDiaEnumLineNumbers> LineNumbers;
+  if (S_OK != Session->findLines(RawCompiland.getDiaSymbol(),
+                                 RawFile.getDiaFile(), &LineNumbers))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> LineNumbers;
+  if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) {
+    ULONGLONG LoadAddr = 0;
+    if (S_OK != Session->get_loadAddress(&LoadAddr))
+      return nullptr;
+    DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
+    if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
+      return nullptr;
+  }
+  return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> LineNumbers;
+  if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+                                        uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> LineNumbers;
+  if (S_OK != Session->findLinesByAddr(Section, Offset, Length, &LineNumbers))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumSourceFiles>
+DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
+                            llvm::StringRef Pattern,
+                            PDB_NameSearchFlags Flags) const {
+  IDiaSymbol *DiaCompiland = nullptr;
+  CComBSTR Utf16Pattern;
+  if (!Pattern.empty())
+    Utf16Pattern = CComBSTR(Pattern.data());
+
+  if (Compiland)
+    DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
+                       .getDiaSymbol();
+
+  Flags = static_cast<PDB_NameSearchFlags>(
+      Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
+  CComPtr<IDiaEnumSourceFiles> SourceFiles;
+  if (S_OK !=
+      Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
+    return nullptr;
+  return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
+}
+
+std::unique_ptr<IPDBSourceFile>
+DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
+                              llvm::StringRef Pattern,
+                              PDB_NameSearchFlags Flags) const {
+  auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
+  if (!SourceFiles || SourceFiles->getChildCount() == 0)
+    return nullptr;
+  return SourceFiles->getNext();
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
+                                        PDB_NameSearchFlags Flags) const {
+  auto File = findOneSourceFile(nullptr, Pattern, Flags);
+  if (!File)
+    return nullptr;
+  return File->getCompilands();
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
+                                          PDB_NameSearchFlags Flags) const {
+  auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
+  if (!Compilands || Compilands->getChildCount() == 0)
+    return nullptr;
+  return Compilands->getNext();
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
+  CComPtr<IDiaEnumSourceFiles> Files;
+  if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
+    const PDBSymbolCompiland &Compiland) const {
+  CComPtr<IDiaEnumSourceFiles> Files;
+
+  const DIARawSymbol &RawSymbol =
+      static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
+  if (S_OK !=
+      Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
+}
+
+std::unique_ptr<IPDBSourceFile>
+DIASession::getSourceFileById(uint32_t FileId) const {
+  CComPtr<IDiaSourceFile> LocatedFile;
+  if (S_OK != Session->findFileById(FileId, &LocatedFile))
+    return nullptr;
+
+  return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
+}
+
+std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
+  CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
+  if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const {
+  CComPtr<IDiaEnumTables> DiaEnumerator;
+  if (S_OK != Session->getEnumTables(&DiaEnumerator))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumTables>(DiaEnumerator);
+}
+
+template <class T> static CComPtr<T> getTableEnumerator(IDiaSession &Session) {
+  CComPtr<T> Enumerator;
+  CComPtr<IDiaEnumTables> ET;
+  CComPtr<IDiaTable> Table;
+  ULONG Count = 0;
+
+  if (Session.getEnumTables(&ET) != S_OK)
+    return nullptr;
+
+  while (ET->Next(1, &Table, &Count) == S_OK && Count == 1) {
+    // There is only one table that matches the given iid
+    if (S_OK == Table->QueryInterface(__uuidof(T), (void **)&Enumerator))
+      break;
+    Table.Release();
+  }
+  return Enumerator;
+}
+std::unique_ptr<IPDBEnumInjectedSources>
+DIASession::getInjectedSources() const {
+  CComPtr<IDiaEnumInjectedSources> Files =
+      getTableEnumerator<IDiaEnumInjectedSources>(*Session);
+  if (!Files)
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumInjectedSources>(Files);
+}
+
+std::unique_ptr<IPDBEnumSectionContribs>
+DIASession::getSectionContribs() const {
+  CComPtr<IDiaEnumSectionContribs> Sections =
+      getTableEnumerator<IDiaEnumSectionContribs>(*Session);
+  if (!Sections)
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumSectionContribs>(*this, Sections);
+}
+
+std::unique_ptr<IPDBEnumFrameData>
+DIASession::getFrameData() const {
+  CComPtr<IDiaEnumFrameData> FD =
+      getTableEnumerator<IDiaEnumFrameData>(*Session);
+  if (!FD)
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumFrameData>(FD);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp
new file mode 100644
index 0000000..d3e4081
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp
@@ -0,0 +1,64 @@
+//===- DIASourceFile.cpp - DIA implementation of IPDBSourceFile -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIASourceFile::DIASourceFile(const DIASession &PDBSession,
+                             CComPtr<IDiaSourceFile> DiaSourceFile)
+    : Session(PDBSession), SourceFile(DiaSourceFile) {}
+
+std::string DIASourceFile::getFileName() const {
+  return invokeBstrMethod(*SourceFile, &IDiaSourceFile::get_fileName);
+}
+
+uint32_t DIASourceFile::getUniqueId() const {
+  DWORD Id;
+  return (S_OK == SourceFile->get_uniqueId(&Id)) ? Id : 0;
+}
+
+std::string DIASourceFile::getChecksum() const {
+  DWORD ByteSize = 0;
+  HRESULT Result = SourceFile->get_checksum(0, &ByteSize, nullptr);
+  if (ByteSize == 0)
+    return std::string();
+  std::vector<BYTE> ChecksumBytes(ByteSize);
+  Result = SourceFile->get_checksum(ByteSize, &ByteSize, &ChecksumBytes[0]);
+  if (S_OK != Result)
+    return std::string();
+  return std::string(ChecksumBytes.begin(), ChecksumBytes.end());
+}
+
+PDB_Checksum DIASourceFile::getChecksumType() const {
+  DWORD Type;
+  HRESULT Result = SourceFile->get_checksumType(&Type);
+  if (S_OK != Result)
+    return PDB_Checksum::None;
+  return static_cast<PDB_Checksum>(Type);
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+DIASourceFile::getCompilands() const {
+  CComPtr<IDiaEnumSymbols> DiaEnumerator;
+  HRESULT Result = SourceFile->get_compilands(&DiaEnumerator);
+  if (S_OK != Result)
+    return nullptr;
+
+  auto Enumerator = std::unique_ptr<IPDBEnumSymbols>(
+      new DIAEnumSymbols(Session, DiaEnumerator));
+  return std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>(
+      new ConcreteSymbolEnumerator<PDBSymbolCompiland>(std::move(Enumerator)));
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIATable.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIATable.cpp
new file mode 100644
index 0000000..6017081
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIATable.cpp
@@ -0,0 +1,51 @@
+//===- DIATable.cpp - DIA implementation of IPDBTable -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIATable.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIATable::DIATable(CComPtr<IDiaTable> DiaTable) : Table(DiaTable) {}
+
+uint32_t DIATable::getItemCount() const {
+  LONG Count = 0;
+  return (S_OK == Table->get_Count(&Count)) ? Count : 0;
+}
+
+std::string DIATable::getName() const {
+  return invokeBstrMethod(*Table, &IDiaTable::get_name);
+}
+
+PDB_TableType DIATable::getTableType() const {
+  CComBSTR Name16;
+  if (S_OK != Table->get_name(&Name16))
+    return PDB_TableType::TableInvalid;
+
+  if (Name16 == DiaTable_Symbols)
+    return PDB_TableType::Symbols;
+  if (Name16 == DiaTable_SrcFiles)
+    return PDB_TableType::SourceFiles;
+  if (Name16 == DiaTable_Sections)
+    return PDB_TableType::SectionContribs;
+  if (Name16 == DiaTable_LineNums)
+    return PDB_TableType::LineNumbers;
+  if (Name16 == DiaTable_SegMap)
+    return PDB_TableType::Segments;
+  if (Name16 == DiaTable_InjSrc)
+    return PDB_TableType::InjectedSources;
+  if (Name16 == DiaTable_FrameData)
+    return PDB_TableType::FrameData;
+  if (Name16 == DiaTable_InputAssemblyFiles)
+    return PDB_TableType::InputAssemblyFiles;
+  if (Name16 == DiaTable_Dbg)
+    return PDB_TableType::Dbg;
+  return PDB_TableType::TableInvalid;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/GenericError.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/GenericError.cpp
new file mode 100644
index 0000000..2569520
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/GenericError.cpp
@@ -0,0 +1,47 @@
+//===- Error.cpp - system_error extensions for PDB --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/GenericError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class PDBErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.pdb"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<pdb_error_code>(Condition)) {
+    case pdb_error_code::unspecified:
+      return "An unknown error has occurred.";
+    case pdb_error_code::dia_sdk_not_present:
+      return "LLVM was not compiled with support for DIA. This usually means "
+             "that you are not using MSVC, or your Visual Studio "
+             "installation is corrupt.";
+    case pdb_error_code::dia_failed_loading:
+      return "DIA is only supported when using MSVC.";
+    case pdb_error_code::invalid_utf8_path:
+      return "The PDB file path is an invalid UTF8 sequence.";
+    case pdb_error_code::signature_out_of_date:
+      return "The signature does not match; the file(s) might be out of date.";
+    case pdb_error_code::external_cmdline_ref:
+      return "The path to this file must be provided on the command-line.";
+    }
+    llvm_unreachable("Unrecognized generic_error_code");
+  }
+};
+
+static llvm::ManagedStatic<PDBErrorCategory> PDBCategory;
+const std::error_category &llvm::pdb::PDBErrCategory() { return *PDBCategory; }
+
+char PDBError::ID;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
new file mode 100644
index 0000000..8cb1fbe
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
@@ -0,0 +1,35 @@
+//===- IPDBSourceFile.cpp - base interface for a PDB source file ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <string>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+IPDBSourceFile::~IPDBSourceFile() = default;
+
+void IPDBSourceFile::dump(raw_ostream &OS, int Indent) const {
+  OS.indent(Indent);
+  PDB_Checksum ChecksumType = getChecksumType();
+  OS << "[";
+  if (ChecksumType != PDB_Checksum::None) {
+    OS << ChecksumType << ": ";
+    std::string Checksum = getChecksum();
+    for (uint8_t c : Checksum)
+      OS << format_hex_no_prefix(c, 2, true);
+  } else
+    OS << "No checksum";
+  OS << "] " << getFileName() << "\n";
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/PDB/LLVMBuild.txt
new file mode 100644
index 0000000..d9af656
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/LLVMBuild.txt
@@ -0,0 +1,23 @@
+;===- ./lib/DebugInfo/PDB/LLVMBuild.txt ------------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = DebugInfoPDB
+parent = DebugInfo
+required_libraries = Object Support DebugInfoCodeView DebugInfoMSF
+
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
new file mode 100644
index 0000000..931ac7b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
@@ -0,0 +1,94 @@
+//===- DbiModuleDescriptor.cpp - PDB module information -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+DbiModuleDescriptor::DbiModuleDescriptor() = default;
+
+DbiModuleDescriptor::DbiModuleDescriptor(const DbiModuleDescriptor &Info) =
+    default;
+
+DbiModuleDescriptor::~DbiModuleDescriptor() = default;
+
+Error DbiModuleDescriptor::initialize(BinaryStreamRef Stream,
+                                      DbiModuleDescriptor &Info) {
+  BinaryStreamReader Reader(Stream);
+  if (auto EC = Reader.readObject(Info.Layout))
+    return EC;
+
+  if (auto EC = Reader.readCString(Info.ModuleName))
+    return EC;
+
+  if (auto EC = Reader.readCString(Info.ObjFileName))
+    return EC;
+  return Error::success();
+}
+
+bool DbiModuleDescriptor::hasECInfo() const {
+  return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0;
+}
+
+uint16_t DbiModuleDescriptor::getTypeServerIndex() const {
+  return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >>
+         ModInfoFlags::TypeServerIndexShift;
+}
+
+const SectionContrib &DbiModuleDescriptor::getSectionContrib() const {
+  return Layout->SC;
+}
+
+uint16_t DbiModuleDescriptor::getModuleStreamIndex() const {
+  return Layout->ModDiStream;
+}
+
+uint32_t DbiModuleDescriptor::getSymbolDebugInfoByteSize() const {
+  return Layout->SymBytes;
+}
+
+uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const {
+  return Layout->C11Bytes;
+}
+
+uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const {
+  return Layout->C13Bytes;
+}
+
+uint32_t DbiModuleDescriptor::getNumberOfFiles() const {
+  return Layout->NumFiles;
+}
+
+uint32_t DbiModuleDescriptor::getSourceFileNameIndex() const {
+  return Layout->SrcFileNameNI;
+}
+
+uint32_t DbiModuleDescriptor::getPdbFilePathNameIndex() const {
+  return Layout->PdbFilePathNI;
+}
+
+StringRef DbiModuleDescriptor::getModuleName() const { return ModuleName; }
+
+StringRef DbiModuleDescriptor::getObjFileName() const { return ObjFileName; }
+
+uint32_t DbiModuleDescriptor::getRecordLength() const {
+  uint32_t M = ModuleName.str().size() + 1;
+  uint32_t O = ObjFileName.str().size() + 1;
+  uint32_t Size = sizeof(ModuleInfoHeader) + M + O;
+  Size = alignTo(Size, 4);
+  return Size;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
new file mode 100644
index 0000000..ab93efc
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -0,0 +1,190 @@
+//===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
+                                            uint32_t C13Size) {
+  uint32_t Size = sizeof(uint32_t);   // Signature
+  Size += alignTo(SymbolByteSize, 4); // Symbol Data
+  Size += 0;                          // TODO: Layout.C11Bytes
+  Size += C13Size;                    // C13 Debug Info Size
+  Size += sizeof(uint32_t);           // GlobalRefs substream size (always 0)
+  Size += 0;                          // GlobalRefs substream bytes
+  return Size;
+}
+
+DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
+                                                       uint32_t ModIndex,
+                                                       msf::MSFBuilder &Msf)
+    : MSF(Msf), ModuleName(ModuleName) {
+  ::memset(&Layout, 0, sizeof(Layout));
+  Layout.Mod = ModIndex;
+}
+
+DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
+
+uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
+  return Layout.ModDiStream;
+}
+
+void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
+  ObjFileName = Name;
+}
+
+void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
+  PdbFilePathNI = NI;
+}
+
+void DbiModuleDescriptorBuilder::setFirstSectionContrib(
+    const SectionContrib &SC) {
+  Layout.SC = SC;
+}
+
+void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
+  // Defer to the bulk API. It does the same thing.
+  addSymbolsInBulk(Symbol.data());
+}
+
+void DbiModuleDescriptorBuilder::addSymbolsInBulk(
+    ArrayRef<uint8_t> BulkSymbols) {
+  // Do nothing for empty runs of symbols.
+  if (BulkSymbols.empty())
+    return;
+
+  Symbols.push_back(BulkSymbols);
+  // Symbols written to a PDB file are required to be 4 byte aligned. The same
+  // is not true of object files.
+  assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
+         "Invalid Symbol alignment!");
+  SymbolByteSize += BulkSymbols.size();
+}
+
+void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
+  SourceFiles.push_back(Path);
+}
+
+uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
+  uint32_t Result = 0;
+  for (const auto &Builder : C13Builders) {
+    assert(Builder && "Empty C13 Fragment Builder!");
+    Result += Builder->calculateSerializedLength();
+  }
+  return Result;
+}
+
+uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
+  uint32_t L = sizeof(Layout);
+  uint32_t M = ModuleName.size() + 1;
+  uint32_t O = ObjFileName.size() + 1;
+  return alignTo(L + M + O, sizeof(uint32_t));
+}
+
+void DbiModuleDescriptorBuilder::finalize() {
+  Layout.SC.Imod = Layout.Mod;
+  Layout.FileNameOffs = 0; // TODO: Fix this
+  Layout.Flags = 0;        // TODO: Fix this
+  Layout.C11Bytes = 0;
+  Layout.C13Bytes = calculateC13DebugInfoSize();
+  (void)Layout.Mod;         // Set in constructor
+  (void)Layout.ModDiStream; // Set in finalizeMsfLayout
+  Layout.NumFiles = SourceFiles.size();
+  Layout.PdbFilePathNI = PdbFilePathNI;
+  Layout.SrcFileNameNI = 0;
+
+  // This value includes both the signature field as well as the record bytes
+  // from the symbol stream.
+  Layout.SymBytes = SymbolByteSize + sizeof(uint32_t);
+}
+
+Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
+  this->Layout.ModDiStream = kInvalidStreamIndex;
+  uint32_t C13Size = calculateC13DebugInfoSize();
+  auto ExpectedSN =
+      MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
+  if (!ExpectedSN)
+    return ExpectedSN.takeError();
+  Layout.ModDiStream = *ExpectedSN;
+  return Error::success();
+}
+
+Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
+                                         const msf::MSFLayout &MsfLayout,
+                                         WritableBinaryStreamRef MsfBuffer) {
+  // We write the Modi record to the `ModiWriter`, but we additionally write its
+  // symbol stream to a brand new stream.
+  if (auto EC = ModiWriter.writeObject(Layout))
+    return EC;
+  if (auto EC = ModiWriter.writeCString(ModuleName))
+    return EC;
+  if (auto EC = ModiWriter.writeCString(ObjFileName))
+    return EC;
+  if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
+    return EC;
+
+  if (Layout.ModDiStream != kInvalidStreamIndex) {
+    auto NS = WritableMappedBlockStream::createIndexedStream(
+        MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
+    WritableBinaryStreamRef Ref(*NS);
+    BinaryStreamWriter SymbolWriter(Ref);
+    // Write the symbols.
+    if (auto EC =
+            SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
+      return EC;
+    for (ArrayRef<uint8_t> Syms : Symbols) {
+      if (auto EC = SymbolWriter.writeBytes(Syms))
+        return EC;
+    }
+    assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
+           "Invalid debug section alignment!");
+    // TODO: Write C11 Line data
+    for (const auto &Builder : C13Builders) {
+      assert(Builder && "Empty C13 Fragment Builder!");
+      if (auto EC = Builder->commit(SymbolWriter))
+        return EC;
+    }
+
+    // TODO: Figure out what GlobalRefs substream actually is and populate it.
+    if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
+      return EC;
+    if (SymbolWriter.bytesRemaining() > 0)
+      return make_error<RawError>(raw_error_code::stream_too_long);
+  }
+  return Error::success();
+}
+
+void DbiModuleDescriptorBuilder::addDebugSubsection(
+    std::shared_ptr<DebugSubsection> Subsection) {
+  assert(Subsection);
+  C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
+      std::move(Subsection), CodeViewContainer::Pdb));
+}
+
+void DbiModuleDescriptorBuilder::addDebugSubsection(
+    const DebugSubsectionRecord &SubsectionContents) {
+  C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
+      SubsectionContents, CodeViewContainer::Pdb));
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp
new file mode 100644
index 0000000..eea70b2
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp
@@ -0,0 +1,280 @@
+//===- DbiModuleList.cpp - PDB module information list --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator(
+    const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
+    : Modules(&Modules), Modi(Modi), Filei(Filei) {
+  setValue();
+}
+
+bool DbiModuleSourceFilesIterator::
+operator==(const DbiModuleSourceFilesIterator &R) const {
+  // incompatible iterators are never equal
+  if (!isCompatible(R))
+    return false;
+
+  // If they're compatible, and they're both ends, then they're equal.
+  if (isEnd() && R.isEnd())
+    return true;
+
+  // If one is an end and the other is not, they're not equal.
+  if (isEnd() != R.isEnd())
+    return false;
+
+  // Now we know:
+  // - They're compatible
+  // - They're not *both* end iterators
+  // - Their endness is the same.
+  // Thus, they're compatible iterators pointing to a valid file on the same
+  // module.  All we need to check are the file indices.
+  assert(Modules == R.Modules);
+  assert(Modi == R.Modi);
+  assert(!isEnd());
+  assert(!R.isEnd());
+
+  return (Filei == R.Filei);
+}
+
+bool DbiModuleSourceFilesIterator::
+operator<(const DbiModuleSourceFilesIterator &R) const {
+  assert(isCompatible(R));
+
+  // It's not sufficient to compare the file indices, because default
+  // constructed iterators could be equal to iterators with valid indices.  To
+  // account for this, early-out if they're equal.
+  if (*this == R)
+    return false;
+
+  return Filei < R.Filei;
+}
+
+std::ptrdiff_t DbiModuleSourceFilesIterator::
+operator-(const DbiModuleSourceFilesIterator &R) const {
+  assert(isCompatible(R));
+  assert(!(*this < R));
+
+  // If they're both end iterators, the distance is 0.
+  if (isEnd() && R.isEnd())
+    return 0;
+
+  assert(!R.isEnd());
+
+  // At this point, R cannot be end, but *this can, which means that *this
+  // might be a universal end iterator with none of its fields set.  So in that
+  // case have to rely on R as the authority to figure out how many files there
+  // are to compute the distance.
+  uint32_t Thisi = Filei;
+  if (isEnd()) {
+    uint32_t RealModi = R.Modi;
+    Thisi = R.Modules->getSourceFileCount(RealModi);
+  }
+
+  assert(Thisi >= R.Filei);
+  return Thisi - R.Filei;
+}
+
+DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
+operator+=(std::ptrdiff_t N) {
+  assert(!isEnd());
+
+  Filei += N;
+  assert(Filei <= Modules->getSourceFileCount(Modi));
+  setValue();
+  return *this;
+}
+
+DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
+operator-=(std::ptrdiff_t N) {
+  // Note that we can subtract from an end iterator, but not a universal end
+  // iterator.
+  assert(!isUniversalEnd());
+
+  assert(N <= Filei);
+
+  Filei -= N;
+  return *this;
+}
+
+void DbiModuleSourceFilesIterator::setValue() {
+  if (isEnd()) {
+    ThisValue = "";
+    return;
+  }
+
+  uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
+  auto ExpectedValue = Modules->getFileName(Off);
+  if (!ExpectedValue) {
+    consumeError(ExpectedValue.takeError());
+    Filei = Modules->getSourceFileCount(Modi);
+  } else
+    ThisValue = *ExpectedValue;
+}
+
+bool DbiModuleSourceFilesIterator::isEnd() const {
+  if (isUniversalEnd())
+    return true;
+
+  assert(Modules);
+  assert(Modi <= Modules->getModuleCount());
+  assert(Filei <= Modules->getSourceFileCount(Modi));
+
+  if (Modi == Modules->getModuleCount())
+    return true;
+  if (Filei == Modules->getSourceFileCount(Modi))
+    return true;
+  return false;
+}
+
+bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
+
+bool DbiModuleSourceFilesIterator::isCompatible(
+    const DbiModuleSourceFilesIterator &R) const {
+  // Universal iterators are compatible with any other iterator.
+  if (isUniversalEnd() || R.isUniversalEnd())
+    return true;
+
+  // At this point, neither iterator is a universal end iterator, although one
+  // or both might be non-universal end iterators.  Regardless, the module index
+  // is valid, so they are compatible if and only if they refer to the same
+  // module.
+  return Modi == R.Modi;
+}
+
+Error DbiModuleList::initialize(BinaryStreamRef ModInfo,
+                                BinaryStreamRef FileInfo) {
+  if (auto EC = initializeModInfo(ModInfo))
+    return EC;
+  if (auto EC = initializeFileInfo(FileInfo))
+    return EC;
+
+  return Error::success();
+}
+
+Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
+  ModInfoSubstream = ModInfo;
+
+  if (ModInfo.getLength() == 0)
+    return Error::success();
+
+  BinaryStreamReader Reader(ModInfo);
+
+  if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
+    return EC;
+
+  return Error::success();
+}
+
+Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
+  FileInfoSubstream = FileInfo;
+
+  if (FileInfo.getLength() == 0)
+    return Error::success();
+
+  BinaryStreamReader FISR(FileInfo);
+  if (auto EC = FISR.readObject(FileInfoHeader))
+    return EC;
+
+  // First is an array of `NumModules` module indices.  This does not seem to be
+  // used for anything meaningful, so we ignore it.
+  FixedStreamArray<support::ulittle16_t> ModuleIndices;
+  if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
+    return EC;
+  if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules))
+    return EC;
+
+  // Compute the real number of source files.  We can't trust the value in
+  // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all
+  // source file counts might be larger than a unit16.  So we compute the real
+  // count by summing up the individual counts.
+  uint32_t NumSourceFiles = 0;
+  for (auto Count : ModFileCountArray)
+    NumSourceFiles += Count;
+
+  // In the reference implementation, this array is where the pointer documented
+  // at the definition of ModuleInfoHeader::FileNameOffs points to.  Note that
+  // although the field in ModuleInfoHeader is ignored this array is not, as it
+  // is the authority on where each filename begins in the names buffer.
+  if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
+    return EC;
+
+  if (auto EC = FISR.readStreamRef(NamesBuffer))
+    return EC;
+
+  auto DescriptorIter = Descriptors.begin();
+  uint32_t NextFileIndex = 0;
+  ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
+  ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
+  for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
+    assert(DescriptorIter != Descriptors.end());
+    ModuleInitialFileIndex[I] = NextFileIndex;
+    ModuleDescriptorOffsets[I] = DescriptorIter.offset();
+
+    NextFileIndex += ModFileCountArray[I];
+    ++DescriptorIter;
+  }
+
+  assert(DescriptorIter == Descriptors.end());
+  assert(NextFileIndex == NumSourceFiles);
+
+  return Error::success();
+}
+
+uint32_t DbiModuleList::getModuleCount() const {
+  return FileInfoHeader->NumModules;
+}
+
+uint32_t DbiModuleList::getSourceFileCount() const {
+  return FileNameOffsets.size();
+}
+
+uint16_t DbiModuleList::getSourceFileCount(uint32_t Modi) const {
+  return ModFileCountArray[Modi];
+}
+
+DbiModuleDescriptor DbiModuleList::getModuleDescriptor(uint32_t Modi) const {
+  assert(Modi < getModuleCount());
+  uint32_t Offset = ModuleDescriptorOffsets[Modi];
+  auto Iter = Descriptors.at(Offset);
+  assert(Iter != Descriptors.end());
+  return *Iter;
+}
+
+iterator_range<DbiModuleSourceFilesIterator>
+DbiModuleList::source_files(uint32_t Modi) const {
+  return make_range<DbiModuleSourceFilesIterator>(
+      DbiModuleSourceFilesIterator(*this, Modi, 0),
+      DbiModuleSourceFilesIterator());
+}
+
+Expected<StringRef> DbiModuleList::getFileName(uint32_t Index) const {
+  BinaryStreamReader Names(NamesBuffer);
+  if (Index >= getSourceFileCount())
+    return make_error<RawError>(raw_error_code::index_out_of_bounds);
+
+  uint32_t FileOffset = FileNameOffsets[Index];
+  Names.setOffset(FileOffset);
+  StringRef Name;
+  if (auto EC = Names.readCString(Name))
+    return std::move(EC);
+  return Name;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
new file mode 100644
index 0000000..60ac17b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -0,0 +1,355 @@
+//===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+template <typename ContribType>
+static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
+                                 BinaryStreamReader &Reader) {
+  if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
+    return make_error<RawError>(
+        raw_error_code::corrupt_file,
+        "Invalid number of bytes of section contributions");
+
+  uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
+  if (auto EC = Reader.readArray(Output, Count))
+    return EC;
+  return Error::success();
+}
+
+DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
+    : Stream(std::move(Stream)), Header(nullptr) {}
+
+DbiStream::~DbiStream() = default;
+
+Error DbiStream::reload(PDBFile *Pdb) {
+  BinaryStreamReader Reader(*Stream);
+
+  if (Stream->getLength() < sizeof(DbiStreamHeader))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI Stream does not contain a header.");
+  if (auto EC = Reader.readObject(Header))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI Stream does not contain a header.");
+
+  if (Header->VersionSignature != -1)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Invalid DBI version signature.");
+
+  // Require at least version 7, which should be present in all PDBs
+  // produced in the last decade and allows us to avoid having to
+  // special case all kinds of complicated arcane formats.
+  if (Header->VersionHeader < PdbDbiV70)
+    return make_error<RawError>(raw_error_code::feature_unsupported,
+                                "Unsupported DBI version.");
+
+  if (Stream->getLength() !=
+      sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
+          Header->SecContrSubstreamSize + Header->SectionMapSize +
+          Header->FileInfoSize + Header->TypeServerSize +
+          Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI Length does not equal sum of substreams.");
+
+  // Only certain substreams are guaranteed to be aligned.  Validate
+  // them here.
+  if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI MODI substream not aligned.");
+  if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
+    return make_error<RawError>(
+        raw_error_code::corrupt_file,
+        "DBI section contribution substream not aligned.");
+  if (Header->SectionMapSize % sizeof(uint32_t) != 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI section map substream not aligned.");
+  if (Header->FileInfoSize % sizeof(uint32_t) != 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI file info substream not aligned.");
+  if (Header->TypeServerSize % sizeof(uint32_t) != 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "DBI type server substream not aligned.");
+
+  if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
+    return EC;
+
+  if (auto EC = Reader.readSubstream(SecContrSubstream,
+                                     Header->SecContrSubstreamSize))
+    return EC;
+  if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
+    return EC;
+  if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
+    return EC;
+  if (auto EC =
+          Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
+    return EC;
+  if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
+    return EC;
+  if (auto EC = Reader.readArray(
+          DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
+    return EC;
+
+  if (auto EC = Modules.initialize(ModiSubstream.StreamData,
+                                   FileInfoSubstream.StreamData))
+    return EC;
+
+  if (auto EC = initializeSectionContributionData())
+    return EC;
+  if (auto EC = initializeSectionHeadersData(Pdb))
+    return EC;
+  if (auto EC = initializeSectionMapData())
+    return EC;
+  if (auto EC = initializeFpoRecords(Pdb))
+    return EC;
+
+  if (Reader.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Found unexpected bytes in DBI Stream.");
+
+  if (!ECSubstream.empty()) {
+    BinaryStreamReader ECReader(ECSubstream.StreamData);
+    if (auto EC = ECNames.reload(ECReader))
+      return EC;
+  }
+
+  return Error::success();
+}
+
+PdbRaw_DbiVer DbiStream::getDbiVersion() const {
+  uint32_t Value = Header->VersionHeader;
+  return static_cast<PdbRaw_DbiVer>(Value);
+}
+
+uint32_t DbiStream::getAge() const { return Header->Age; }
+
+uint16_t DbiStream::getPublicSymbolStreamIndex() const {
+  return Header->PublicSymbolStreamIndex;
+}
+
+uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
+  return Header->GlobalSymbolStreamIndex;
+}
+
+uint16_t DbiStream::getFlags() const { return Header->Flags; }
+
+bool DbiStream::isIncrementallyLinked() const {
+  return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
+}
+
+bool DbiStream::hasCTypes() const {
+  return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
+}
+
+bool DbiStream::isStripped() const {
+  return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
+}
+
+uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
+
+uint16_t DbiStream::getBuildMajorVersion() const {
+  return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
+         DbiBuildNo::BuildMajorShift;
+}
+
+uint16_t DbiStream::getBuildMinorVersion() const {
+  return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
+         DbiBuildNo::BuildMinorShift;
+}
+
+uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
+
+uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
+
+uint32_t DbiStream::getSymRecordStreamIndex() const {
+  return Header->SymRecordStreamIndex;
+}
+
+PDB_Machine DbiStream::getMachineType() const {
+  uint16_t Machine = Header->MachineType;
+  return static_cast<PDB_Machine>(Machine);
+}
+
+FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
+  return SectionHeaders;
+}
+
+FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
+  return FpoRecords;
+}
+
+const DbiModuleList &DbiStream::modules() const { return Modules; }
+
+FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
+  return SectionMap;
+}
+
+void DbiStream::visitSectionContributions(
+    ISectionContribVisitor &Visitor) const {
+  if (!SectionContribs.empty()) {
+    assert(SectionContribVersion == DbiSecContribVer60);
+    for (auto &SC : SectionContribs)
+      Visitor.visit(SC);
+  } else if (!SectionContribs2.empty()) {
+    assert(SectionContribVersion == DbiSecContribV2);
+    for (auto &SC : SectionContribs2)
+      Visitor.visit(SC);
+  }
+}
+
+Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
+  return ECNames.getStringForID(NI);
+}
+
+Error DbiStream::initializeSectionContributionData() {
+  if (SecContrSubstream.empty())
+    return Error::success();
+
+  BinaryStreamReader SCReader(SecContrSubstream.StreamData);
+  if (auto EC = SCReader.readEnum(SectionContribVersion))
+    return EC;
+
+  if (SectionContribVersion == DbiSecContribVer60)
+    return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
+  if (SectionContribVersion == DbiSecContribV2)
+    return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
+
+  return make_error<RawError>(raw_error_code::feature_unsupported,
+                              "Unsupported DBI Section Contribution version");
+}
+
+// Initializes this->SectionHeaders.
+Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
+  if (!Pdb)
+    return Error::success();
+
+  if (DbgStreams.size() == 0)
+    return Error::success();
+
+  uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
+  if (StreamNum == kInvalidStreamIndex)
+    return Error::success();
+
+  if (StreamNum >= Pdb->getNumStreams())
+    return make_error<RawError>(raw_error_code::no_stream);
+
+  auto SHS = MappedBlockStream::createIndexedStream(
+      Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
+
+  size_t StreamLen = SHS->getLength();
+  if (StreamLen % sizeof(object::coff_section))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupted section header stream.");
+
+  size_t NumSections = StreamLen / sizeof(object::coff_section);
+  BinaryStreamReader Reader(*SHS);
+  if (auto EC = Reader.readArray(SectionHeaders, NumSections))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Could not read a bitmap.");
+
+  SectionHeaderStream = std::move(SHS);
+  return Error::success();
+}
+
+// Initializes this->Fpos.
+Error DbiStream::initializeFpoRecords(PDBFile *Pdb) {
+  if (!Pdb)
+    return Error::success();
+
+  if (DbgStreams.size() == 0)
+    return Error::success();
+
+  uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
+
+  // This means there is no FPO data.
+  if (StreamNum == kInvalidStreamIndex)
+    return Error::success();
+
+  if (StreamNum >= Pdb->getNumStreams())
+    return make_error<RawError>(raw_error_code::no_stream);
+
+  auto FS = MappedBlockStream::createIndexedStream(
+      Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
+
+  size_t StreamLen = FS->getLength();
+  if (StreamLen % sizeof(object::FpoData))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupted New FPO stream.");
+
+  size_t NumRecords = StreamLen / sizeof(object::FpoData);
+  BinaryStreamReader Reader(*FS);
+  if (auto EC = Reader.readArray(FpoRecords, NumRecords))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupted New FPO stream.");
+  FpoStream = std::move(FS);
+  return Error::success();
+}
+
+BinarySubstreamRef DbiStream::getSectionContributionData() const {
+  return SecContrSubstream;
+}
+
+BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
+  return SecMapSubstream;
+}
+
+BinarySubstreamRef DbiStream::getModiSubstreamData() const {
+  return ModiSubstream;
+}
+
+BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
+  return FileInfoSubstream;
+}
+
+BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
+  return TypeServerMapSubstream;
+}
+
+BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
+
+Error DbiStream::initializeSectionMapData() {
+  if (SecMapSubstream.empty())
+    return Error::success();
+
+  BinaryStreamReader SMReader(SecMapSubstream.StreamData);
+  const SecMapHeader *Header;
+  if (auto EC = SMReader.readObject(Header))
+    return EC;
+  if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
+    return EC;
+  return Error::success();
+}
+
+uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
+  uint16_t T = static_cast<uint16_t>(Type);
+  if (T >= DbgStreams.size())
+    return kInvalidStreamIndex;
+  return DbgStreams[T];
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
new file mode 100644
index 0000000..094216e
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -0,0 +1,456 @@
+//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
+    : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
+      PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
+      Header(nullptr) {}
+
+DbiStreamBuilder::~DbiStreamBuilder() {}
+
+void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
+
+void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
+
+void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
+
+void DbiStreamBuilder::setBuildNumber(uint8_t Major, uint8_t Minor) {
+  BuildNumber = (uint16_t(Major) << DbiBuildNo::BuildMajorShift) &
+                DbiBuildNo::BuildMajorMask;
+  BuildNumber |= (uint16_t(Minor) << DbiBuildNo::BuildMinorShift) &
+                 DbiBuildNo::BuildMinorMask;
+  BuildNumber |= DbiBuildNo::NewVersionFormatMask;
+}
+
+void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
+
+void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
+
+void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
+
+void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
+
+void DbiStreamBuilder::setMachineType(COFF::MachineTypes M) {
+  // These enums are mirrors of each other, so we can just cast the value.
+  MachineType = static_cast<pdb::PDB_Machine>(static_cast<unsigned>(M));
+}
+
+void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
+  SectionMap = SecMap;
+}
+
+void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) {
+  GlobalsStreamIndex = Index;
+}
+
+void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) {
+  SymRecordStreamIndex = Index;
+}
+
+void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
+  PublicsStreamIndex = Index;
+}
+
+void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
+  if (!NewFpoData.hasValue())
+    NewFpoData.emplace(false);
+
+  NewFpoData->addFrameData(FD);
+}
+
+void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
+  OldFpoData.push_back(FD);
+}
+
+Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
+                                     ArrayRef<uint8_t> Data) {
+  assert(Type != DbgHeaderType::NewFPO &&
+         "NewFPO data should be written via addFrameData()!");
+
+  DbgStreams[(int)Type].emplace();
+  DbgStreams[(int)Type]->Size = Data.size();
+  DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
+    return Writer.writeArray(Data);
+  };
+  return Error::success();
+}
+
+uint32_t DbiStreamBuilder::addECName(StringRef Name) {
+  return ECNamesBuilder.insert(Name);
+}
+
+uint32_t DbiStreamBuilder::calculateSerializedLength() const {
+  // For now we only support serializing the header.
+  return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
+         calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
+         calculateSectionMapStreamSize() + calculateDbgStreamsSize() +
+         ECNamesBuilder.calculateSerializedSize();
+}
+
+Expected<DbiModuleDescriptorBuilder &>
+DbiStreamBuilder::addModuleInfo(StringRef ModuleName) {
+  uint32_t Index = ModiList.size();
+  ModiList.push_back(
+      llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf));
+  return *ModiList.back();
+}
+
+Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module,
+                                            StringRef File) {
+  uint32_t Index = SourceFileNames.size();
+  SourceFileNames.insert(std::make_pair(File, Index));
+  Module.addSourceFile(File);
+  return Error::success();
+}
+
+Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
+  auto NameIter = SourceFileNames.find(File);
+  if (NameIter == SourceFileNames.end())
+    return make_error<RawError>(raw_error_code::no_entry,
+                                "The specified source file was not found");
+  return NameIter->getValue();
+}
+
+uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
+  uint32_t Size = 0;
+  for (const auto &M : ModiList)
+    Size += M->calculateSerializedLength();
+  return Size;
+}
+
+uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const {
+  if (SectionContribs.empty())
+    return 0;
+  return sizeof(enum PdbRaw_DbiSecContribVer) +
+         sizeof(SectionContribs[0]) * SectionContribs.size();
+}
+
+uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const {
+  if (SectionMap.empty())
+    return 0;
+  return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size();
+}
+
+uint32_t DbiStreamBuilder::calculateNamesOffset() const {
+  uint32_t Offset = 0;
+  Offset += sizeof(ulittle16_t);                         // NumModules
+  Offset += sizeof(ulittle16_t);                         // NumSourceFiles
+  Offset += ModiList.size() * sizeof(ulittle16_t);       // ModIndices
+  Offset += ModiList.size() * sizeof(ulittle16_t);       // ModFileCounts
+  uint32_t NumFileInfos = 0;
+  for (const auto &M : ModiList)
+    NumFileInfos += M->source_files().size();
+  Offset += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
+  return Offset;
+}
+
+uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const {
+  uint32_t Size = calculateNamesOffset();
+  Size += calculateNamesBufferSize();
+  return alignTo(Size, sizeof(uint32_t));
+}
+
+uint32_t DbiStreamBuilder::calculateNamesBufferSize() const {
+  uint32_t Size = 0;
+  for (const auto &F : SourceFileNames) {
+    Size += F.getKeyLength() + 1; // Names[I];
+  }
+  return Size;
+}
+
+uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const {
+  return DbgStreams.size() * sizeof(uint16_t);
+}
+
+Error DbiStreamBuilder::generateFileInfoSubstream() {
+  uint32_t Size = calculateFileInfoSubstreamSize();
+  auto Data = Allocator.Allocate<uint8_t>(Size);
+  uint32_t NamesOffset = calculateNamesOffset();
+
+  FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size),
+                                           llvm::support::little);
+
+  WritableBinaryStreamRef MetadataBuffer =
+      WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset);
+  BinaryStreamWriter MetadataWriter(MetadataBuffer);
+
+  uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModiList.size());
+  uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
+  if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
+    return EC;
+  if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
+    return EC;
+  for (uint16_t I = 0; I < ModiCount; ++I) {
+    if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
+      return EC;
+  }
+  for (const auto &MI : ModiList) {
+    FileCount = static_cast<uint16_t>(MI->source_files().size());
+    if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
+      return EC;
+  }
+
+  // Before writing the FileNameOffsets array, write the NamesBuffer array.
+  // A side effect of this is that this will actually compute the various
+  // file name offsets, so we can then go back and write the FileNameOffsets
+  // array to the other substream.
+  NamesBuffer = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset);
+  BinaryStreamWriter NameBufferWriter(NamesBuffer);
+  for (auto &Name : SourceFileNames) {
+    Name.second = NameBufferWriter.getOffset();
+    if (auto EC = NameBufferWriter.writeCString(Name.getKey()))
+      return EC;
+  }
+
+  for (const auto &MI : ModiList) {
+    for (StringRef Name : MI->source_files()) {
+      auto Result = SourceFileNames.find(Name);
+      if (Result == SourceFileNames.end())
+        return make_error<RawError>(raw_error_code::no_entry,
+                                    "The source file was not found.");
+      if (auto EC = MetadataWriter.writeInteger(Result->second))
+        return EC;
+    }
+  }
+
+  if (auto EC = NameBufferWriter.padToAlignment(sizeof(uint32_t)))
+    return EC;
+
+  if (NameBufferWriter.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::invalid_format,
+                                "The names buffer contained unexpected data.");
+
+  if (MetadataWriter.bytesRemaining() > sizeof(uint32_t))
+    return make_error<RawError>(
+        raw_error_code::invalid_format,
+        "The metadata buffer contained unexpected data.");
+
+  return Error::success();
+}
+
+Error DbiStreamBuilder::finalize() {
+  if (Header)
+    return Error::success();
+
+  for (auto &MI : ModiList)
+    MI->finalize();
+
+  if (auto EC = generateFileInfoSubstream())
+    return EC;
+
+  DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
+  ::memset(H, 0, sizeof(DbiStreamHeader));
+  H->VersionHeader = *VerHeader;
+  H->VersionSignature = -1;
+  H->Age = Age;
+  H->BuildNumber = BuildNumber;
+  H->Flags = Flags;
+  H->PdbDllRbld = PdbDllRbld;
+  H->PdbDllVersion = PdbDllVersion;
+  H->MachineType = static_cast<uint16_t>(MachineType);
+
+  H->ECSubstreamSize = ECNamesBuilder.calculateSerializedSize();
+  H->FileInfoSize = FileInfoBuffer.getLength();
+  H->ModiSubstreamSize = calculateModiSubstreamSize();
+  H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
+  H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
+  H->SectionMapSize = calculateSectionMapStreamSize();
+  H->TypeServerSize = 0;
+  H->SymRecordStreamIndex = SymRecordStreamIndex;
+  H->PublicSymbolStreamIndex = PublicsStreamIndex;
+  H->MFCTypeServerIndex = 0; // Not sure what this is, but link.exe writes 0.
+  H->GlobalSymbolStreamIndex = GlobalsStreamIndex;
+
+  Header = H;
+  return Error::success();
+}
+
+Error DbiStreamBuilder::finalizeMsfLayout() {
+  if (NewFpoData.hasValue()) {
+    DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
+    DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
+        NewFpoData->calculateSerializedSize();
+    DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
+        [this](BinaryStreamWriter &Writer) {
+          return NewFpoData->commit(Writer);
+        };
+  }
+
+  if (!OldFpoData.empty()) {
+    DbgStreams[(int)DbgHeaderType::FPO].emplace();
+    DbgStreams[(int)DbgHeaderType::FPO]->Size =
+        sizeof(object::FpoData) * OldFpoData.size();
+    DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
+        [this](BinaryStreamWriter &Writer) {
+          return Writer.writeArray(makeArrayRef(OldFpoData));
+        };
+  }
+
+  for (auto &S : DbgStreams) {
+    if (!S.hasValue())
+      continue;
+    auto ExpectedIndex = Msf.addStream(S->Size);
+    if (!ExpectedIndex)
+      return ExpectedIndex.takeError();
+    S->StreamNumber = *ExpectedIndex;
+  }
+
+  for (auto &MI : ModiList) {
+    if (auto EC = MI->finalizeMsfLayout())
+      return EC;
+  }
+
+  uint32_t Length = calculateSerializedLength();
+  if (auto EC = Msf.setStreamSize(StreamDBI, Length))
+    return EC;
+  return Error::success();
+}
+
+static uint16_t toSecMapFlags(uint32_t Flags) {
+  uint16_t Ret = 0;
+  if (Flags & COFF::IMAGE_SCN_MEM_READ)
+    Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read);
+  if (Flags & COFF::IMAGE_SCN_MEM_WRITE)
+    Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write);
+  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+    Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
+  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+    Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
+  if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT))
+    Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit);
+
+  // This seems always 1.
+  Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector);
+
+  return Ret;
+}
+
+// A utility function to create a Section Map for a given list of COFF sections.
+//
+// A Section Map seem to be a copy of a COFF section list in other format.
+// I don't know why a PDB file contains both a COFF section header and
+// a Section Map, but it seems it must be present in a PDB.
+std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap(
+    ArrayRef<llvm::object::coff_section> SecHdrs) {
+  std::vector<SecMapEntry> Ret;
+  int Idx = 0;
+
+  auto Add = [&]() -> SecMapEntry & {
+    Ret.emplace_back();
+    auto &Entry = Ret.back();
+    memset(&Entry, 0, sizeof(Entry));
+
+    Entry.Frame = Idx + 1;
+
+    // We don't know the meaning of these fields yet.
+    Entry.SecName = UINT16_MAX;
+    Entry.ClassName = UINT16_MAX;
+
+    return Entry;
+  };
+
+  for (auto &Hdr : SecHdrs) {
+    auto &Entry = Add();
+    Entry.Flags = toSecMapFlags(Hdr.Characteristics);
+    Entry.SecByteLength = Hdr.VirtualSize;
+    ++Idx;
+  }
+
+  // The last entry is for absolute symbols.
+  auto &Entry = Add();
+  Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) |
+                static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress);
+  Entry.SecByteLength = UINT32_MAX;
+
+  return Ret;
+}
+
+Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
+                               WritableBinaryStreamRef MsfBuffer) {
+  if (auto EC = finalize())
+    return EC;
+
+  auto DbiS = WritableMappedBlockStream::createIndexedStream(
+      Layout, MsfBuffer, StreamDBI, Allocator);
+
+  BinaryStreamWriter Writer(*DbiS);
+  if (auto EC = Writer.writeObject(*Header))
+    return EC;
+
+  for (auto &M : ModiList) {
+    if (auto EC = M->commit(Writer, Layout, MsfBuffer))
+      return EC;
+  }
+
+  if (!SectionContribs.empty()) {
+    if (auto EC = Writer.writeEnum(DbiSecContribVer60))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs)))
+      return EC;
+  }
+
+  if (!SectionMap.empty()) {
+    ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size());
+    SecMapHeader SMHeader = {Size, Size};
+    if (auto EC = Writer.writeObject(SMHeader))
+      return EC;
+    if (auto EC = Writer.writeArray(SectionMap))
+      return EC;
+  }
+
+  if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
+    return EC;
+
+  if (auto EC = ECNamesBuilder.commit(Writer))
+    return EC;
+
+  for (auto &Stream : DbgStreams) {
+    uint16_t StreamNumber = kInvalidStreamIndex;
+    if (Stream.hasValue())
+      StreamNumber = Stream->StreamNumber;
+    if (auto EC = Writer.writeInteger(StreamNumber))
+      return EC;
+  }
+
+  for (auto &Stream : DbgStreams) {
+    if (!Stream.hasValue())
+      continue;
+    assert(Stream->StreamNumber != kInvalidStreamIndex);
+
+    auto WritableStream = WritableMappedBlockStream::createIndexedStream(
+        Layout, MsfBuffer, Stream->StreamNumber, Allocator);
+    BinaryStreamWriter DbgStreamWriter(*WritableStream);
+
+    if (auto EC = Stream->WriteFn(DbgStreamWriter))
+      return EC;
+  }
+
+  if (Writer.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::invalid_format,
+                                "Unexpected bytes found in DBI Stream");
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp
new file mode 100644
index 0000000..b3837dc
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp
@@ -0,0 +1,38 @@
+//===- EnumTables.cpp - Enum to string conversion tables --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+#define PDB_ENUM_CLASS_ENT(enum_class, enum)                                   \
+  { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
+
+#define PDB_ENUM_ENT(ns, enum)                                                 \
+  { #enum, ns::enum }
+
+static const EnumEntry<uint16_t> OMFSegMapDescFlagNames[] = {
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Read),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Write),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Execute),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, AddressIs32Bit),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsSelector),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsAbsoluteAddress),
+    PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsGroup),
+};
+
+namespace llvm {
+namespace pdb {
+ArrayRef<EnumEntry<uint16_t>> getOMFSegMapDescFlagNames() {
+  return makeArrayRef(OMFSegMapDescFlagNames);
+}
+}
+}
\ No newline at end of file
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
new file mode 100644
index 0000000..57da700
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -0,0 +1,380 @@
+//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/Support/BinaryItemStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/xxhash.h"
+#include <algorithm>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::codeview;
+
+struct llvm::pdb::GSIHashStreamBuilder {
+  struct UdtDenseMapInfo {
+    static inline CVSymbol getEmptyKey() {
+      static CVSymbol Empty;
+      return Empty;
+    }
+    static inline CVSymbol getTombstoneKey() {
+      static CVSymbol Tombstone(static_cast<SymbolKind>(-1),
+                                ArrayRef<uint8_t>());
+      return Tombstone;
+    }
+    static unsigned getHashValue(const CVSymbol &Val) {
+      return xxHash64(Val.RecordData);
+    }
+    static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS) {
+      return LHS.RecordData == RHS.RecordData;
+    }
+  };
+
+  std::vector<CVSymbol> Records;
+  uint32_t StreamIndex;
+  llvm::DenseSet<CVSymbol, UdtDenseMapInfo> UdtHashes;
+  std::vector<PSHashRecord> HashRecords;
+  std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap;
+  std::vector<support::ulittle32_t> HashBuckets;
+
+  uint32_t calculateSerializedLength() const;
+  uint32_t calculateRecordByteSize() const;
+  Error commit(BinaryStreamWriter &Writer);
+  void finalizeBuckets(uint32_t RecordZeroOffset);
+
+  template <typename T> void addSymbol(const T &Symbol, MSFBuilder &Msf) {
+    T Copy(Symbol);
+    addSymbol(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(),
+                                               CodeViewContainer::Pdb));
+  }
+  void addSymbol(const CVSymbol &Symbol) {
+    if (Symbol.kind() == S_UDT) {
+      auto Iter = UdtHashes.insert(Symbol);
+      if (!Iter.second)
+        return;
+    }
+
+    Records.push_back(Symbol);
+  }
+};
+
+uint32_t GSIHashStreamBuilder::calculateSerializedLength() const {
+  uint32_t Size = sizeof(GSIHashHeader);
+  Size += HashRecords.size() * sizeof(PSHashRecord);
+  Size += HashBitmap.size() * sizeof(uint32_t);
+  Size += HashBuckets.size() * sizeof(uint32_t);
+  return Size;
+}
+
+uint32_t GSIHashStreamBuilder::calculateRecordByteSize() const {
+  uint32_t Size = 0;
+  for (const auto &Sym : Records)
+    Size += Sym.length();
+  return Size;
+}
+
+Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
+  GSIHashHeader Header;
+  Header.VerSignature = GSIHashHeader::HdrSignature;
+  Header.VerHdr = GSIHashHeader::HdrVersion;
+  Header.HrSize = HashRecords.size() * sizeof(PSHashRecord);
+  Header.NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4;
+
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+
+  if (auto EC = Writer.writeArray(makeArrayRef(HashRecords)))
+    return EC;
+  if (auto EC = Writer.writeArray(makeArrayRef(HashBitmap)))
+    return EC;
+  if (auto EC = Writer.writeArray(makeArrayRef(HashBuckets)))
+    return EC;
+  return Error::success();
+}
+
+static bool isAsciiString(StringRef S) {
+  return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
+}
+
+// See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
+static bool gsiRecordLess(StringRef S1, StringRef S2) {
+  size_t LS = S1.size();
+  size_t RS = S2.size();
+  // Shorter strings always compare less than longer strings.
+  if (LS != RS)
+    return LS < RS;
+
+  // If either string contains non ascii characters, memcmp them.
+  if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
+    return memcmp(S1.data(), S2.data(), LS) < 0;
+
+  // Both strings are ascii, perform a case-insenstive comparison.
+  return S1.compare_lower(S2.data()) < 0;
+}
+
+void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
+  std::array<std::vector<std::pair<StringRef, PSHashRecord>>, IPHR_HASH + 1>
+      TmpBuckets;
+  uint32_t SymOffset = RecordZeroOffset;
+  for (const CVSymbol &Sym : Records) {
+    PSHashRecord HR;
+    // Add one when writing symbol offsets to disk. See GSI1::fixSymRecs.
+    HR.Off = SymOffset + 1;
+    HR.CRef = 1; // Always use a refcount of 1.
+
+    // Hash the name to figure out which bucket this goes into.
+    StringRef Name = getSymbolName(Sym);
+    size_t BucketIdx = hashStringV1(Name) % IPHR_HASH;
+    TmpBuckets[BucketIdx].push_back(std::make_pair(Name, HR));
+    SymOffset += Sym.length();
+  }
+
+  // Compute the three tables: the hash records in bucket and chain order, the
+  // bucket presence bitmap, and the bucket chain start offsets.
+  HashRecords.reserve(Records.size());
+  for (ulittle32_t &Word : HashBitmap)
+    Word = 0;
+  for (size_t BucketIdx = 0; BucketIdx < IPHR_HASH + 1; ++BucketIdx) {
+    auto &Bucket = TmpBuckets[BucketIdx];
+    if (Bucket.empty())
+      continue;
+    HashBitmap[BucketIdx / 32] |= 1U << (BucketIdx % 32);
+
+    // Calculate what the offset of the first hash record in the chain would
+    // be if it were inflated to contain 32-bit pointers. On a 32-bit system,
+    // each record would be 12 bytes. See HROffsetCalc in gsi.h.
+    const int SizeOfHROffsetCalc = 12;
+    ulittle32_t ChainStartOff =
+        ulittle32_t(HashRecords.size() * SizeOfHROffsetCalc);
+    HashBuckets.push_back(ChainStartOff);
+
+    // Sort each bucket by memcmp of the symbol's name.  It's important that
+    // we use the same sorting algorithm as is used by the reference
+    // implementation to ensure that the search for a record within a bucket
+    // can properly early-out when it detects the record won't be found.  The
+    // algorithm used here corredsponds to the function
+    // caseInsensitiveComparePchPchCchCch in the reference implementation.
+    llvm::sort(Bucket, [](const std::pair<StringRef, PSHashRecord> &Left,
+                          const std::pair<StringRef, PSHashRecord> &Right) {
+      return gsiRecordLess(Left.first, Right.first);
+    });
+
+    for (const auto &Entry : Bucket)
+      HashRecords.push_back(Entry.second);
+  }
+}
+
+GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf)
+    : Msf(Msf), PSH(llvm::make_unique<GSIHashStreamBuilder>()),
+      GSH(llvm::make_unique<GSIHashStreamBuilder>()) {}
+
+GSIStreamBuilder::~GSIStreamBuilder() {}
+
+uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const {
+  uint32_t Size = 0;
+  Size += sizeof(PublicsStreamHeader);
+  Size += PSH->calculateSerializedLength();
+  Size += PSH->Records.size() * sizeof(uint32_t); // AddrMap
+  // FIXME: Add thunk map and section offsets for incremental linking.
+
+  return Size;
+}
+
+uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const {
+  return GSH->calculateSerializedLength();
+}
+
+Error GSIStreamBuilder::finalizeMsfLayout() {
+  // First we write public symbol records, then we write global symbol records.
+  uint32_t PSHZero = 0;
+  uint32_t GSHZero = PSH->calculateRecordByteSize();
+
+  PSH->finalizeBuckets(PSHZero);
+  GSH->finalizeBuckets(GSHZero);
+
+  Expected<uint32_t> Idx = Msf.addStream(calculateGlobalsHashStreamSize());
+  if (!Idx)
+    return Idx.takeError();
+  GSH->StreamIndex = *Idx;
+  Idx = Msf.addStream(calculatePublicsHashStreamSize());
+  if (!Idx)
+    return Idx.takeError();
+  PSH->StreamIndex = *Idx;
+
+  uint32_t RecordBytes =
+      GSH->calculateRecordByteSize() + PSH->calculateRecordByteSize();
+
+  Idx = Msf.addStream(RecordBytes);
+  if (!Idx)
+    return Idx.takeError();
+  RecordStreamIdx = *Idx;
+  return Error::success();
+}
+
+static bool comparePubSymByAddrAndName(
+    const std::pair<const CVSymbol *, const PublicSym32 *> &LS,
+    const std::pair<const CVSymbol *, const PublicSym32 *> &RS) {
+  if (LS.second->Segment != RS.second->Segment)
+    return LS.second->Segment < RS.second->Segment;
+  if (LS.second->Offset != RS.second->Offset)
+    return LS.second->Offset < RS.second->Offset;
+
+  return LS.second->Name < RS.second->Name;
+}
+
+/// Compute the address map. The address map is an array of symbol offsets
+/// sorted so that it can be binary searched by address.
+static std::vector<ulittle32_t> computeAddrMap(ArrayRef<CVSymbol> Records) {
+  // Make a vector of pointers to the symbols so we can sort it by address.
+  // Also gather the symbol offsets while we're at it.
+
+  std::vector<PublicSym32> DeserializedPublics;
+  std::vector<std::pair<const CVSymbol *, const PublicSym32 *>> PublicsByAddr;
+  std::vector<uint32_t> SymOffsets;
+  DeserializedPublics.reserve(Records.size());
+  PublicsByAddr.reserve(Records.size());
+  SymOffsets.reserve(Records.size());
+
+  uint32_t SymOffset = 0;
+  for (const CVSymbol &Sym : Records) {
+    assert(Sym.kind() == SymbolKind::S_PUB32);
+    DeserializedPublics.push_back(
+        cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym)));
+    PublicsByAddr.emplace_back(&Sym, &DeserializedPublics.back());
+    SymOffsets.push_back(SymOffset);
+    SymOffset += Sym.length();
+  }
+  std::stable_sort(PublicsByAddr.begin(), PublicsByAddr.end(),
+                   comparePubSymByAddrAndName);
+
+  // Fill in the symbol offsets in the appropriate order.
+  std::vector<ulittle32_t> AddrMap;
+  AddrMap.reserve(Records.size());
+  for (auto &Sym : PublicsByAddr) {
+    ptrdiff_t Idx = std::distance(Records.data(), Sym.first);
+    assert(Idx >= 0 && size_t(Idx) < Records.size());
+    AddrMap.push_back(ulittle32_t(SymOffsets[Idx]));
+  }
+  return AddrMap;
+}
+
+uint32_t GSIStreamBuilder::getPublicsStreamIndex() const {
+  return PSH->StreamIndex;
+}
+
+uint32_t GSIStreamBuilder::getGlobalsStreamIndex() const {
+  return GSH->StreamIndex;
+}
+
+void GSIStreamBuilder::addPublicSymbol(const PublicSym32 &Pub) {
+  PSH->addSymbol(Pub, Msf);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const ProcRefSym &Sym) {
+  GSH->addSymbol(Sym, Msf);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const DataSym &Sym) {
+  GSH->addSymbol(Sym, Msf);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) {
+  GSH->addSymbol(Sym, Msf);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Sym) {
+  GSH->addSymbol(Sym);
+}
+
+static Error writeRecords(BinaryStreamWriter &Writer,
+                          ArrayRef<CVSymbol> Records) {
+  BinaryItemStream<CVSymbol> ItemStream(support::endianness::little);
+  ItemStream.setItems(Records);
+  BinaryStreamRef RecordsRef(ItemStream);
+  return Writer.writeStreamRef(RecordsRef);
+}
+
+Error GSIStreamBuilder::commitSymbolRecordStream(
+    WritableBinaryStreamRef Stream) {
+  BinaryStreamWriter Writer(Stream);
+
+  // Write public symbol records first, followed by global symbol records.  This
+  // must match the order that we assume in finalizeMsfLayout when computing
+  // PSHZero and GSHZero.
+  if (auto EC = writeRecords(Writer, PSH->Records))
+    return EC;
+  if (auto EC = writeRecords(Writer, GSH->Records))
+    return EC;
+
+  return Error::success();
+}
+
+Error GSIStreamBuilder::commitPublicsHashStream(
+    WritableBinaryStreamRef Stream) {
+  BinaryStreamWriter Writer(Stream);
+  PublicsStreamHeader Header;
+
+  // FIXME: Fill these in. They are for incremental linking.
+  Header.SymHash = PSH->calculateSerializedLength();
+  Header.AddrMap = PSH->Records.size() * 4;
+  Header.NumThunks = 0;
+  Header.SizeOfThunk = 0;
+  Header.ISectThunkTable = 0;
+  memset(Header.Padding, 0, sizeof(Header.Padding));
+  Header.OffThunkTable = 0;
+  Header.NumSections = 0;
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+
+  if (auto EC = PSH->commit(Writer))
+    return EC;
+
+  std::vector<ulittle32_t> AddrMap = computeAddrMap(PSH->Records);
+  if (auto EC = Writer.writeArray(makeArrayRef(AddrMap)))
+    return EC;
+
+  return Error::success();
+}
+
+Error GSIStreamBuilder::commitGlobalsHashStream(
+    WritableBinaryStreamRef Stream) {
+  BinaryStreamWriter Writer(Stream);
+  return GSH->commit(Writer);
+}
+
+Error GSIStreamBuilder::commit(const msf::MSFLayout &Layout,
+                               WritableBinaryStreamRef Buffer) {
+  auto GS = WritableMappedBlockStream::createIndexedStream(
+      Layout, Buffer, getGlobalsStreamIndex(), Msf.getAllocator());
+  auto PS = WritableMappedBlockStream::createIndexedStream(
+      Layout, Buffer, getPublicsStreamIndex(), Msf.getAllocator());
+  auto PRS = WritableMappedBlockStream::createIndexedStream(
+      Layout, Buffer, getRecordStreamIdx(), Msf.getAllocator());
+
+  if (auto EC = commitSymbolRecordStream(*PRS))
+    return EC;
+  if (auto EC = commitGlobalsHashStream(*GS))
+    return EC;
+  if (auto EC = commitPublicsHashStream(*PS))
+    return EC;
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
new file mode 100644
index 0000000..e363195
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
@@ -0,0 +1,182 @@
+//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The on-disk structores used in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+//  - ppdb1->m_fMinimalDbgInfo seems to be always true.
+//  - SMALLBUCKETS macro is defined.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
+    : Stream(std::move(Stream)) {}
+
+GlobalsStream::~GlobalsStream() = default;
+
+Error GlobalsStream::reload() {
+  BinaryStreamReader Reader(*Stream);
+  if (auto E = GlobalsTable.read(Reader))
+    return E;
+  return Error::success();
+}
+
+std::vector<std::pair<uint32_t, codeview::CVSymbol>>
+GlobalsStream::findRecordsByName(StringRef Name,
+                                 const SymbolStream &Symbols) const {
+  std::vector<std::pair<uint32_t, codeview::CVSymbol>> Result;
+
+  // Hash the name to figure out which bucket this goes into.
+  size_t ExpandedBucketIndex = hashStringV1(Name) % IPHR_HASH;
+  int32_t CompressedBucketIndex = GlobalsTable.BucketMap[ExpandedBucketIndex];
+  if (CompressedBucketIndex == -1)
+    return Result;
+
+  uint32_t LastBucketIndex = GlobalsTable.HashBuckets.size() - 1;
+  uint32_t StartRecordIndex =
+      GlobalsTable.HashBuckets[CompressedBucketIndex] / 12;
+  uint32_t EndRecordIndex = 0;
+  if (LLVM_LIKELY(uint32_t(CompressedBucketIndex) < LastBucketIndex)) {
+    EndRecordIndex = GlobalsTable.HashBuckets[CompressedBucketIndex + 1];
+  } else {
+    // If this is the last bucket, it consists of all hash records until the end
+    // of the HashRecords array.
+    EndRecordIndex = GlobalsTable.HashRecords.size() * 12;
+  }
+
+  EndRecordIndex /= 12;
+
+  assert(EndRecordIndex <= GlobalsTable.HashRecords.size());
+  while (StartRecordIndex < EndRecordIndex) {
+    PSHashRecord PSH = GlobalsTable.HashRecords[StartRecordIndex];
+    uint32_t Off = PSH.Off - 1;
+    codeview::CVSymbol Record = Symbols.readRecord(Off);
+    if (codeview::getSymbolName(Record) == Name)
+      Result.push_back(std::make_pair(Off, std::move(Record)));
+    ++StartRecordIndex;
+  }
+  return Result;
+}
+
+static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
+  if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
+    return make_error<RawError>(
+        raw_error_code::feature_unsupported,
+        "Encountered unsupported globals stream version.");
+
+  return Error::success();
+}
+
+static Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
+                               BinaryStreamReader &Reader) {
+  if (Reader.readObject(HashHdr))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Stream does not contain a GSIHashHeader.");
+
+  if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
+    return make_error<RawError>(
+        raw_error_code::feature_unsupported,
+        "GSIHashHeader signature (0xffffffff) not found.");
+
+  return Error::success();
+}
+
+static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
+                                const GSIHashHeader *HashHdr,
+                                BinaryStreamReader &Reader) {
+  if (auto EC = checkHashHdrVersion(HashHdr))
+    return EC;
+
+  // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
+  // Verify that we can read them all.
+  if (HashHdr->HrSize % sizeof(PSHashRecord))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Invalid HR array size.");
+  uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
+  if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Error reading hash records."));
+
+  return Error::success();
+}
+
+static Error
+readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
+                   FixedStreamArray<support::ulittle32_t> &HashBitmap,
+                   const GSIHashHeader *HashHdr,
+                   MutableArrayRef<int32_t> BucketMap,
+                   BinaryStreamReader &Reader) {
+  if (auto EC = checkHashHdrVersion(HashHdr))
+    return EC;
+
+  // Before the actual hash buckets, there is a bitmap of length determined by
+  // IPHR_HASH.
+  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
+  uint32_t NumBitmapEntries = BitmapSizeInBits / 32;
+  if (auto EC = Reader.readArray(HashBitmap, NumBitmapEntries))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Could not read a bitmap."));
+  uint32_t NumBuckets1 = 0;
+  uint32_t CompressedBucketIdx = 0;
+  for (uint32_t I = 0; I <= IPHR_HASH; ++I) {
+    uint8_t WordIdx = I / 32;
+    uint8_t BitIdx = I % 32;
+    bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx);
+    if (IsSet) {
+      ++NumBuckets1;
+      BucketMap[I] = CompressedBucketIdx++;
+    } else {
+      BucketMap[I] = -1;
+    }
+  }
+
+  uint32_t NumBuckets = 0;
+  for (uint32_t B : HashBitmap)
+    NumBuckets += countPopulation(B);
+
+  // Hash buckets follow.
+  if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Hash buckets corrupted."));
+
+  return Error::success();
+}
+
+Error GSIHashTable::read(BinaryStreamReader &Reader) {
+  if (auto EC = readGSIHashHeader(HashHdr, Reader))
+    return EC;
+  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+    return EC;
+  if (HashHdr->HrSize > 0)
+    if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr,
+                                     BucketMap, Reader))
+      return EC;
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/Hash.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/Hash.cpp
new file mode 100644
index 0000000..61188ec
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/Hash.cpp
@@ -0,0 +1,86 @@
+//===- Hash.cpp - PDB Hash Functions --------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/JamCRC.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::support;
+
+// Corresponds to `Hasher::lhashPbCb` in PDB/include/misc.h.
+// Used for name hash table and TPI/IPI hashes.
+uint32_t pdb::hashStringV1(StringRef Str) {
+  uint32_t Result = 0;
+  uint32_t Size = Str.size();
+
+  ArrayRef<ulittle32_t> Longs(reinterpret_cast<const ulittle32_t *>(Str.data()),
+                              Size / 4);
+
+  for (auto Value : Longs)
+    Result ^= Value;
+
+  const uint8_t *Remainder = reinterpret_cast<const uint8_t *>(Longs.end());
+  uint32_t RemainderSize = Size % 4;
+
+  // Maximum of 3 bytes left.  Hash a 2 byte word if possible, then hash the
+  // possibly remaining 1 byte.
+  if (RemainderSize >= 2) {
+    uint16_t Value = *reinterpret_cast<const ulittle16_t *>(Remainder);
+    Result ^= static_cast<uint32_t>(Value);
+    Remainder += 2;
+    RemainderSize -= 2;
+  }
+
+  // hash possible odd byte
+  if (RemainderSize == 1) {
+    Result ^= *(Remainder++);
+  }
+
+  const uint32_t toLowerMask = 0x20202020;
+  Result |= toLowerMask;
+  Result ^= (Result >> 11);
+
+  return Result ^ (Result >> 16);
+}
+
+// Corresponds to `HasherV2::HashULONG` in PDB/include/misc.h.
+// Used for name hash table.
+uint32_t pdb::hashStringV2(StringRef Str) {
+  uint32_t Hash = 0xb170a1bf;
+
+  ArrayRef<char> Buffer(Str.begin(), Str.end());
+
+  ArrayRef<ulittle32_t> Items(
+      reinterpret_cast<const ulittle32_t *>(Buffer.data()),
+      Buffer.size() / sizeof(ulittle32_t));
+  for (ulittle32_t Item : Items) {
+    Hash += Item;
+    Hash += (Hash << 10);
+    Hash ^= (Hash >> 6);
+  }
+  Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t));
+  for (uint8_t Item : Buffer) {
+    Hash += Item;
+    Hash += (Hash << 10);
+    Hash ^= (Hash >> 6);
+  }
+
+  return Hash * 1664525U + 1013904223U;
+}
+
+// Corresponds to `SigForPbCb` in langapi/shared/crc32.h.
+uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) {
+  JamCRC JC(/*Init=*/0U);
+  JC.update(makeArrayRef<char>(reinterpret_cast<const char *>(Buf.data()),
+                               Buf.size()));
+  return JC.getCRC();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp
new file mode 100644
index 0000000..cfabc9c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp
@@ -0,0 +1,72 @@
+//===- HashTable.cpp - PDB Hash Table -------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+Error llvm::pdb::readSparseBitVector(BinaryStreamReader &Stream,
+                                     SparseBitVector<> &V) {
+  uint32_t NumWords;
+  if (auto EC = Stream.readInteger(NumWords))
+    return joinErrors(
+        std::move(EC),
+        make_error<RawError>(raw_error_code::corrupt_file,
+                             "Expected hash table number of words"));
+
+  for (uint32_t I = 0; I != NumWords; ++I) {
+    uint32_t Word;
+    if (auto EC = Stream.readInteger(Word))
+      return joinErrors(std::move(EC),
+                        make_error<RawError>(raw_error_code::corrupt_file,
+                                             "Expected hash table word"));
+    for (unsigned Idx = 0; Idx < 32; ++Idx)
+      if (Word & (1U << Idx))
+        V.set((I * 32) + Idx);
+  }
+  return Error::success();
+}
+
+Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer,
+                                      SparseBitVector<> &Vec) {
+  constexpr int BitsPerWord = 8 * sizeof(uint32_t);
+
+  int ReqBits = Vec.find_last() + 1;
+  uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord;
+  if (auto EC = Writer.writeInteger(ReqWords))
+    return joinErrors(
+        std::move(EC),
+        make_error<RawError>(raw_error_code::corrupt_file,
+                             "Could not write linear map number of words"));
+
+  uint32_t Idx = 0;
+  for (uint32_t I = 0; I != ReqWords; ++I) {
+    uint32_t Word = 0;
+    for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) {
+      if (Vec.test(Idx))
+        Word |= (1 << WordIdx);
+    }
+    if (auto EC = Writer.writeInteger(Word))
+      return joinErrors(std::move(EC), make_error<RawError>(
+                                           raw_error_code::corrupt_file,
+                                           "Could not write linear map word"));
+  }
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp
new file mode 100644
index 0000000..973a520
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -0,0 +1,132 @@
+//===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
+    : Stream(std::move(Stream)), Header(nullptr) {}
+
+Error InfoStream::reload() {
+  BinaryStreamReader Reader(*Stream);
+
+  if (auto EC = Reader.readObject(Header))
+    return joinErrors(
+        std::move(EC),
+        make_error<RawError>(raw_error_code::corrupt_file,
+                             "PDB Stream does not contain a header."));
+
+  switch (Header->Version) {
+  case PdbImplVC70:
+  case PdbImplVC80:
+  case PdbImplVC110:
+  case PdbImplVC140:
+    break;
+  default:
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Unsupported PDB stream version.");
+  }
+
+  uint32_t Offset = Reader.getOffset();
+  if (auto EC = NamedStreams.load(Reader))
+    return EC;
+  uint32_t NewOffset = Reader.getOffset();
+  NamedStreamMapByteSize = NewOffset - Offset;
+
+  Reader.setOffset(Offset);
+  if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize))
+    return EC;
+
+  bool Stop = false;
+  while (!Stop && !Reader.empty()) {
+    PdbRaw_FeatureSig Sig;
+    if (auto EC = Reader.readEnum(Sig))
+      return EC;
+    // Since this value comes from a file, it's possible we have some strange
+    // value which doesn't correspond to any value.  We don't want to warn on
+    // -Wcovered-switch-default in this case, so switch on the integral value
+    // instead of the enumeration value.
+    switch (uint32_t(Sig)) {
+    case uint32_t(PdbRaw_FeatureSig::VC110):
+      // No other flags for VC110 PDB.
+      Stop = true;
+      LLVM_FALLTHROUGH;
+    case uint32_t(PdbRaw_FeatureSig::VC140):
+      Features |= PdbFeatureContainsIdStream;
+      break;
+    case uint32_t(PdbRaw_FeatureSig::NoTypeMerge):
+      Features |= PdbFeatureNoTypeMerging;
+      break;
+    case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
+      Features |= PdbFeatureMinimalDebugInfo;
+      break;
+    default:
+      continue;
+    }
+    FeatureSignatures.push_back(Sig);
+  }
+  return Error::success();
+}
+
+uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
+
+Expected<uint32_t> InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
+  uint32_t Result;
+  if (!NamedStreams.get(Name, Result))
+    return make_error<RawError>(raw_error_code::no_stream);
+  return Result;
+}
+
+StringMap<uint32_t> InfoStream::named_streams() const {
+  return NamedStreams.entries();
+}
+
+bool InfoStream::containsIdStream() const {
+  return !!(Features & PdbFeatureContainsIdStream);
+}
+
+PdbRaw_ImplVer InfoStream::getVersion() const {
+  return static_cast<PdbRaw_ImplVer>(uint32_t(Header->Version));
+}
+
+uint32_t InfoStream::getSignature() const {
+  return uint32_t(Header->Signature);
+}
+
+uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
+
+GUID InfoStream::getGuid() const { return Header->Guid; }
+
+uint32_t InfoStream::getNamedStreamMapByteSize() const {
+  return NamedStreamMapByteSize;
+}
+
+PdbRaw_Features InfoStream::getFeatures() const { return Features; }
+
+ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {
+  return FeatureSignatures;
+}
+
+const NamedStreamMap &InfoStream::getNamedStreams() const {
+  return NamedStreams;
+}
+
+BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const {
+  return SubNamedStreams;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
new file mode 100644
index 0000000..3b5a2ac
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
@@ -0,0 +1,83 @@
+//===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
+                                     NamedStreamMap &NamedStreams)
+    : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Age(0),
+      NamedStreams(NamedStreams) {
+  ::memset(&Guid, 0, sizeof(Guid));
+}
+
+void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
+
+void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
+  Features.push_back(Sig);
+}
+
+void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) {
+  HashPDBContentsToGUID = B;
+}
+
+void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
+
+void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
+
+void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
+
+
+Error InfoStreamBuilder::finalizeMsfLayout() {
+  uint32_t Length = sizeof(InfoStreamHeader) +
+                    NamedStreams.calculateSerializedLength() +
+                    (Features.size() + 1) * sizeof(uint32_t);
+  if (auto EC = Msf.setStreamSize(StreamPDB, Length))
+    return EC;
+  return Error::success();
+}
+
+Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
+                                WritableBinaryStreamRef Buffer) const {
+  auto InfoS = WritableMappedBlockStream::createIndexedStream(
+      Layout, Buffer, StreamPDB, Msf.getAllocator());
+  BinaryStreamWriter Writer(*InfoS);
+
+  InfoStreamHeader H;
+  // Leave the build id fields 0 so they can be set as the last step before
+  // committing the file to disk.
+  ::memset(&H, 0, sizeof(H));
+  H.Version = Ver;
+  if (auto EC = Writer.writeObject(H))
+    return EC;
+
+  if (auto EC = NamedStreams.commit(Writer))
+    return EC;
+  if (auto EC = Writer.writeInteger(0))
+    return EC;
+  for (auto E : Features) {
+    if (auto EC = Writer.writeEnum(E))
+      return EC;
+  }
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
new file mode 100644
index 0000000..8c97f4a
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
@@ -0,0 +1,137 @@
+//===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+ModuleDebugStreamRef::ModuleDebugStreamRef(
+    const DbiModuleDescriptor &Module,
+    std::unique_ptr<MappedBlockStream> Stream)
+    : Mod(Module), Stream(std::move(Stream)) {}
+
+ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
+
+Error ModuleDebugStreamRef::reload() {
+  BinaryStreamReader Reader(*Stream);
+
+  uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
+  uint32_t C11Size = Mod.getC11LineInfoByteSize();
+  uint32_t C13Size = Mod.getC13LineInfoByteSize();
+
+  if (C11Size > 0 && C13Size > 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Module has both C11 and C13 line info");
+
+  BinaryStreamRef S;
+
+  if (auto EC = Reader.readInteger(Signature))
+    return EC;
+  Reader.setOffset(0);
+  if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
+    return EC;
+  if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
+    return EC;
+  if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size))
+    return EC;
+
+  BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
+  if (auto EC = SymbolReader.readArray(
+          SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
+    return EC;
+
+  BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
+  if (auto EC = SubsectionsReader.readArray(Subsections,
+                                            SubsectionsReader.bytesRemaining()))
+    return EC;
+
+  uint32_t GlobalRefsSize;
+  if (auto EC = Reader.readInteger(GlobalRefsSize))
+    return EC;
+  if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize))
+    return EC;
+  if (Reader.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Unexpected bytes in module stream.");
+
+  return Error::success();
+}
+
+const codeview::CVSymbolArray
+ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const {
+  return limitSymbolArrayToScope(SymbolArray, ScopeBegin);
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const {
+  return SymbolsSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const {
+  return C11LinesSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const {
+  return C13LinesSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const {
+  return GlobalRefsSubstream;
+}
+
+iterator_range<codeview::CVSymbolArray::Iterator>
+ModuleDebugStreamRef::symbols(bool *HadError) const {
+  return make_range(SymbolArray.begin(HadError), SymbolArray.end());
+}
+
+CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
+  auto Iter = SymbolArray.at(Offset);
+  assert(Iter != SymbolArray.end());
+  return *Iter;
+}
+
+iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
+ModuleDebugStreamRef::subsections() const {
+  return make_range(Subsections.begin(), Subsections.end());
+}
+
+bool ModuleDebugStreamRef::hasDebugSubsections() const {
+  return !C13LinesSubstream.empty();
+}
+
+Error ModuleDebugStreamRef::commit() { return Error::success(); }
+
+Expected<codeview::DebugChecksumsSubsectionRef>
+ModuleDebugStreamRef::findChecksumsSubsection() const {
+  codeview::DebugChecksumsSubsectionRef Result;
+  for (const auto &SS : subsections()) {
+    if (SS.kind() != DebugSubsectionKind::FileChecksums)
+      continue;
+
+    if (auto EC = Result.initialize(SS.getRecordData()))
+      return std::move(EC);
+    return Result;
+  }
+  return Result;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
new file mode 100644
index 0000000..a4eaed9
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
@@ -0,0 +1,127 @@
+//===- NamedStreamMap.cpp - PDB Named Stream Map --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NamedStreamMapTraits::NamedStreamMapTraits(NamedStreamMap &NS) : NS(&NS) {}
+
+uint16_t NamedStreamMapTraits::hashLookupKey(StringRef S) const {
+  // In the reference implementation, this uses
+  // HASH Hasher<ULONG*, USHORT*>::hashPbCb(PB pb, size_t cb, ULONG ulMod).
+  // Here, the type HASH is a typedef of unsigned short.
+  // ** It is not a bug that we truncate the result of hashStringV1, in fact
+  //    it is a bug if we do not! **
+  return static_cast<uint16_t>(hashStringV1(S));
+}
+
+StringRef NamedStreamMapTraits::storageKeyToLookupKey(uint32_t Offset) const {
+  return NS->getString(Offset);
+}
+
+uint32_t NamedStreamMapTraits::lookupKeyToStorageKey(StringRef S) {
+  return NS->appendStringData(S);
+}
+
+NamedStreamMap::NamedStreamMap()
+    : HashTraits(*this), OffsetIndexMap(1, HashTraits) {}
+
+Error NamedStreamMap::load(BinaryStreamReader &Stream) {
+  uint32_t StringBufferSize;
+  if (auto EC = Stream.readInteger(StringBufferSize))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Expected string buffer size"));
+
+  StringRef Buffer;
+  if (auto EC = Stream.readFixedString(Buffer, StringBufferSize))
+    return EC;
+  NamesBuffer.assign(Buffer.begin(), Buffer.end());
+
+  return OffsetIndexMap.load(Stream);
+}
+
+Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
+  // The first field is the number of bytes of string data.
+  if (auto EC = Writer.writeInteger<uint32_t>(NamesBuffer.size()))
+    return EC;
+
+  // Then the actual string data.
+  StringRef Data(NamesBuffer.data(), NamesBuffer.size());
+  if (auto EC = Writer.writeFixedString(Data))
+    return EC;
+
+  // And finally the Offset Index map.
+  if (auto EC = OffsetIndexMap.commit(Writer))
+    return EC;
+
+  return Error::success();
+}
+
+uint32_t NamedStreamMap::calculateSerializedLength() const {
+  return sizeof(uint32_t)                              // String data size
+         + NamesBuffer.size()                          // String data
+         + OffsetIndexMap.calculateSerializedLength(); // Offset Index Map
+}
+
+uint32_t NamedStreamMap::size() const { return OffsetIndexMap.size(); }
+
+StringRef NamedStreamMap::getString(uint32_t Offset) const {
+  assert(NamesBuffer.size() > Offset);
+  return StringRef(NamesBuffer.data() + Offset);
+}
+
+uint32_t NamedStreamMap::hashString(uint32_t Offset) const {
+  return hashStringV1(getString(Offset));
+}
+
+bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
+  auto Iter = OffsetIndexMap.find_as(Stream);
+  if (Iter == OffsetIndexMap.end())
+    return false;
+  StreamNo = (*Iter).second;
+  return true;
+}
+
+StringMap<uint32_t> NamedStreamMap::entries() const {
+  StringMap<uint32_t> Result;
+  for (const auto &Entry : OffsetIndexMap) {
+    StringRef Stream(NamesBuffer.data() + Entry.first);
+    Result.try_emplace(Stream, Entry.second);
+  }
+  return Result;
+}
+
+uint32_t NamedStreamMap::appendStringData(StringRef S) {
+  uint32_t Offset = NamesBuffer.size();
+  NamesBuffer.insert(NamesBuffer.end(), S.begin(), S.end());
+  NamesBuffer.push_back('\0');
+  return Offset;
+}
+
+void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
+  OffsetIndexMap.set_as(Stream, support::ulittle32_t(StreamNo));
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
new file mode 100644
index 0000000..efa70b0
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
@@ -0,0 +1,61 @@
+//===- NativeCompilandSymbol.cpp - Native impl for compilands ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+namespace llvm {
+namespace pdb {
+
+NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session,
+                                             SymIndexId SymbolId,
+                                             DbiModuleDescriptor MI)
+    : NativeRawSymbol(Session, PDB_SymType::Compiland, SymbolId), Module(MI) {}
+
+PDB_SymType NativeCompilandSymbol::getSymTag() const {
+  return PDB_SymType::Compiland;
+}
+
+void NativeCompilandSymbol::dump(raw_ostream &OS, int Indent,
+                                 PdbSymbolIdField ShowIdFields,
+                                 PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "libraryName", getLibraryName(), Indent);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolField(OS, "editAndContinueEnabled", isEditAndContinueEnabled(),
+                  Indent);
+}
+
+bool NativeCompilandSymbol::isEditAndContinueEnabled() const {
+  return Module.hasECInfo();
+}
+
+SymIndexId NativeCompilandSymbol::getLexicalParentId() const { return 0; }
+
+// The usage of getObjFileName for getLibraryName and getModuleName for getName
+// may seem backwards, but it is consistent with DIA, which is what this API
+// was modeled after.  We may rename these methods later to try to eliminate
+// this potential confusion.
+
+std::string NativeCompilandSymbol::getLibraryName() const {
+  return Module.getObjFileName();
+}
+
+std::string NativeCompilandSymbol::getName() const {
+  return Module.getModuleName();
+}
+
+} // namespace pdb
+} // namespace llvm
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
new file mode 100644
index 0000000..6eece3d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
@@ -0,0 +1,55 @@
+//==- NativeEnumGlobals.cpp - Native Global Enumerator impl ------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumGlobals::NativeEnumGlobals(NativeSession &PDBSession,
+                                     std::vector<codeview::SymbolKind> Kinds)
+    : Index(0), Session(PDBSession) {
+  GlobalsStream &GS = cantFail(Session.getPDBFile().getPDBGlobalsStream());
+  SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+  for (uint32_t Off : GS.getGlobalsTable()) {
+    CVSymbol S = SS.readRecord(Off);
+    if (!llvm::is_contained(Kinds, S.kind()))
+      continue;
+    MatchOffsets.push_back(Off);
+  }
+}
+
+uint32_t NativeEnumGlobals::getChildCount() const {
+  return static_cast<uint32_t>(MatchOffsets.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumGlobals::getChildAtIndex(uint32_t N) const {
+  if (N >= MatchOffsets.size())
+    return nullptr;
+
+  SymIndexId Id =
+      Session.getSymbolCache().getOrCreateGlobalSymbolByOffset(MatchOffsets[N]);
+  return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumGlobals::getNext() {
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumGlobals::reset() { Index = 0; }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
new file mode 100644
index 0000000..6e4d564
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
@@ -0,0 +1,44 @@
+//==- NativeEnumModules.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+
+namespace llvm {
+namespace pdb {
+
+NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, uint32_t Index)
+    : Session(PDBSession), Index(Index) {}
+
+uint32_t NativeEnumModules::getChildCount() const {
+  return Session.getSymbolCache().getNumCompilands();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumModules::getChildAtIndex(uint32_t N) const {
+  return Session.getSymbolCache().getOrCreateCompiland(N);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
+  if (Index >= getChildCount())
+    return nullptr;
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumModules::reset() { Index = 0; }
+
+}
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
new file mode 100644
index 0000000..288a912
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
@@ -0,0 +1,71 @@
+//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
+                                 LazyRandomTypeCollection &Types,
+                                 std::vector<codeview::TypeLeafKind> Kinds)
+    : Matches(), Index(0), Session(PDBSession) {
+  Optional<TypeIndex> TI = Types.getFirst();
+  while (TI) {
+    CVType CVT = Types.getType(*TI);
+    TypeLeafKind K = CVT.kind();
+    if (llvm::is_contained(Kinds, K)) {
+      // Don't add forward refs, we'll find those later while enumerating.
+      if (!isUdtForwardRef(CVT))
+        Matches.push_back(*TI);
+    } else if (K == TypeLeafKind::LF_MODIFIER) {
+      TypeIndex ModifiedTI = getModifiedType(CVT);
+      if (!ModifiedTI.isSimple()) {
+        CVType UnmodifiedCVT = Types.getType(ModifiedTI);
+        // LF_MODIFIERs point to forward refs, but don't worry about that
+        // here.  We're pushing the TypeIndex of the LF_MODIFIER itself,
+        // so we'll worry about resolving forward refs later.
+        if (llvm::is_contained(Kinds, UnmodifiedCVT.kind()))
+          Matches.push_back(*TI);
+      }
+    }
+    TI = Types.getNext(*TI);
+  }
+}
+
+NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
+                                 std::vector<codeview::TypeIndex> Indices)
+    : Matches(std::move(Indices)), Index(0), Session(PDBSession) {}
+
+uint32_t NativeEnumTypes::getChildCount() const {
+  return static_cast<uint32_t>(Matches.size());
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getChildAtIndex(uint32_t N) const {
+  if (N < Matches.size()) {
+    SymIndexId Id = Session.getSymbolCache().findSymbolByTypeIndex(Matches[N]);
+    return Session.getSymbolCache().getSymbolById(Id);
+  }
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumTypes::reset() { Index = 0; }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
new file mode 100644
index 0000000..6dde5d0
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -0,0 +1,102 @@
+//===- NativeExeSymbol.cpp - native impl for PDBSymbolExe -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#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),
+      Dbi(getDbiStreamPtr(Session)) {}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeExeSymbol::findChildren(PDB_SymType Type) const {
+  switch (Type) {
+  case PDB_SymType::Compiland: {
+    return std::unique_ptr<IPDBEnumSymbols>(new NativeEnumModules(Session));
+    break;
+  }
+  case PDB_SymType::ArrayType:
+    return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ARRAY);
+  case PDB_SymType::Enum:
+    return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM);
+  case PDB_SymType::PointerType:
+    return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER);
+  case PDB_SymType::UDT:
+    return Session.getSymbolCache().createTypeEnumerator(
+        {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION,
+         codeview::LF_INTERFACE});
+  case PDB_SymType::VTableShape:
+    return Session.getSymbolCache().createTypeEnumerator(codeview::LF_VTSHAPE);
+  case PDB_SymType::FunctionSig:
+    return Session.getSymbolCache().createTypeEnumerator(
+        {codeview::LF_PROCEDURE, codeview::LF_MFUNCTION});
+  case PDB_SymType::Typedef:
+    return Session.getSymbolCache().createGlobalsEnumerator(codeview::S_UDT);
+
+  default:
+    break;
+  }
+  return nullptr;
+}
+
+uint32_t NativeExeSymbol::getAge() const {
+  auto IS = Session.getPDBFile().getPDBInfoStream();
+  if (IS)
+    return IS->getAge();
+  consumeError(IS.takeError());
+  return 0;
+}
+
+std::string NativeExeSymbol::getSymbolsFileName() const {
+  return Session.getPDBFile().getFilePath();
+}
+
+codeview::GUID NativeExeSymbol::getGuid() const {
+  auto IS = Session.getPDBFile().getPDBInfoStream();
+  if (IS)
+    return IS->getGuid();
+  consumeError(IS.takeError());
+  return codeview::GUID{{0}};
+}
+
+bool NativeExeSymbol::hasCTypes() const {
+  auto Dbi = Session.getPDBFile().getPDBDbiStream();
+  if (Dbi)
+    return Dbi->hasCTypes();
+  consumeError(Dbi.takeError());
+  return false;
+}
+
+bool NativeExeSymbol::hasPrivateSymbols() const {
+  auto Dbi = Session.getPDBFile().getPDBDbiStream();
+  if (Dbi)
+    return !Dbi->isStripped();
+  consumeError(Dbi.takeError());
+  return false;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
new file mode 100644
index 0000000..62950cb
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -0,0 +1,735 @@
+//===- NativeRawSymbol.cpp - Native implementation of IPDBRawSymbol -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag,
+                                 SymIndexId SymbolId)
+    : Session(PDBSession), Tag(Tag), SymbolId(SymbolId) {}
+
+void NativeRawSymbol::dump(raw_ostream &OS, int Indent,
+                           PdbSymbolIdField ShowIdFields,
+                           PdbSymbolIdField RecurseIdFields) const {
+  dumpSymbolIdField(OS, "symIndexId", SymbolId, Indent, Session,
+                    PdbSymbolIdField::SymIndexId, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "symTag", Tag, Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildren(PDB_SymType Type) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name,
+    PDB_NameSearchFlags Flags) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
+    PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
+   PDB_NameSearchFlags Flags, uint64_t VA) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+    PDB_NameSearchFlags Flags, uint32_t RVA) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByAddr(uint32_t Section,
+                                        uint32_t Offset) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const {
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLines() const {
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+                                        uint32_t Length) const {
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const {
+  bytes.clear();
+}
+
+PDB_MemberAccess NativeRawSymbol::getAccess() const {
+  return PDB_MemberAccess::Private;
+}
+
+uint32_t NativeRawSymbol::getAddressOffset() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getAddressSection() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getAge() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getArrayIndexTypeId() const { return 0; }
+
+void NativeRawSymbol::getBackEndVersion(VersionInfo &Version) const {
+  Version.Major = 0;
+  Version.Minor = 0;
+  Version.Build = 0;
+  Version.QFE = 0;
+}
+
+uint32_t NativeRawSymbol::getBaseDataOffset() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getBaseDataSlot() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getBaseSymbolId() const { return 0; }
+
+PDB_BuiltinType NativeRawSymbol::getBuiltinType() const {
+  return PDB_BuiltinType::None;
+}
+
+uint32_t NativeRawSymbol::getBitPosition() const {
+  return 0;
+}
+
+PDB_CallingConv NativeRawSymbol::getCallingConvention() const {
+  return PDB_CallingConv::FarStdCall;
+}
+
+SymIndexId NativeRawSymbol::getClassParentId() const { return 0; }
+
+std::string NativeRawSymbol::getCompilerName() const {
+  return {};
+}
+
+uint32_t NativeRawSymbol::getCount() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getCountLiveRanges() const {
+  return 0;
+}
+
+void NativeRawSymbol::getFrontEndVersion(VersionInfo &Version) const {
+  Version.Major = 0;
+  Version.Minor = 0;
+  Version.Build = 0;
+  Version.QFE = 0;
+}
+
+PDB_Lang NativeRawSymbol::getLanguage() const {
+  return PDB_Lang::Cobol;
+}
+
+SymIndexId NativeRawSymbol::getLexicalParentId() const { return 0; }
+
+std::string NativeRawSymbol::getLibraryName() const {
+  return {};
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartAddressOffset() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartAddressSection() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
+  return 0;
+}
+
+codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const {
+  return codeview::RegisterId::EAX;
+}
+
+SymIndexId NativeRawSymbol::getLowerBoundId() const { return 0; }
+
+uint32_t NativeRawSymbol::getMemorySpaceKind() const {
+  return 0;
+}
+
+std::string NativeRawSymbol::getName() const {
+  return {};
+}
+
+uint32_t NativeRawSymbol::getNumberOfAcceleratorPointerTags() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfColumns() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfModifiers() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfRegisterIndices() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfRows() const {
+  return 0;
+}
+
+std::string NativeRawSymbol::getObjectFileName() const {
+  return {};
+}
+
+uint32_t NativeRawSymbol::getOemId() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getOemSymbolId() const { return 0; }
+
+uint32_t NativeRawSymbol::getOffsetInUdt() const {
+  return 0;
+}
+
+PDB_Cpu NativeRawSymbol::getPlatform() const {
+  return PDB_Cpu::Intel8080;
+}
+
+uint32_t NativeRawSymbol::getRank() const {
+  return 0;
+}
+
+codeview::RegisterId NativeRawSymbol::getRegisterId() const {
+  return codeview::RegisterId::EAX;
+}
+
+uint32_t NativeRawSymbol::getRegisterType() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getRelativeVirtualAddress() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getSamplerSlot() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getSignature() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getSizeInUdt() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getSlot() const {
+  return 0;
+}
+
+std::string NativeRawSymbol::getSourceFileName() const {
+  return {};
+}
+
+std::unique_ptr<IPDBLineNumber>
+NativeRawSymbol::getSrcLineOnTypeDefn() const {
+  return nullptr;
+}
+
+uint32_t NativeRawSymbol::getStride() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getSubTypeId() const { return 0; }
+
+std::string NativeRawSymbol::getSymbolsFileName() const { return {}; }
+
+SymIndexId NativeRawSymbol::getSymIndexId() const { return SymbolId; }
+
+uint32_t NativeRawSymbol::getTargetOffset() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getTargetRelativeVirtualAddress() const {
+  return 0;
+}
+
+uint64_t NativeRawSymbol::getTargetVirtualAddress() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getTargetSection() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getTextureSlot() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getTimeStamp() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getToken() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getTypeId() const { return 0; }
+
+uint32_t NativeRawSymbol::getUavSlot() const {
+  return 0;
+}
+
+std::string NativeRawSymbol::getUndecoratedName() const {
+  return {};
+}
+
+std::string NativeRawSymbol::getUndecoratedNameEx(
+    PDB_UndnameFlags Flags) const {
+  return {};
+}
+
+SymIndexId NativeRawSymbol::getUnmodifiedTypeId() const { return 0; }
+
+SymIndexId NativeRawSymbol::getUpperBoundId() const { return 0; }
+
+Variant NativeRawSymbol::getValue() const {
+  return Variant();
+}
+
+uint32_t NativeRawSymbol::getVirtualBaseDispIndex() const {
+  return 0;
+}
+
+uint32_t NativeRawSymbol::getVirtualBaseOffset() const {
+  return 0;
+}
+
+SymIndexId NativeRawSymbol::getVirtualTableShapeId() const { return 0; }
+
+std::unique_ptr<PDBSymbolTypeBuiltin>
+NativeRawSymbol::getVirtualBaseTableType() const {
+  return nullptr;
+}
+
+PDB_DataKind NativeRawSymbol::getDataKind() const {
+  return PDB_DataKind::Unknown;
+}
+
+PDB_SymType NativeRawSymbol::getSymTag() const { return Tag; }
+
+codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; }
+
+int32_t NativeRawSymbol::getOffset() const {
+  return 0;
+}
+
+int32_t NativeRawSymbol::getThisAdjust() const {
+  return 0;
+}
+
+int32_t NativeRawSymbol::getVirtualBasePointerOffset() const {
+  return 0;
+}
+
+PDB_LocType NativeRawSymbol::getLocationType() const {
+  return PDB_LocType::Null;
+}
+
+PDB_Machine NativeRawSymbol::getMachineType() const {
+  return PDB_Machine::Invalid;
+}
+
+codeview::ThunkOrdinal NativeRawSymbol::getThunkOrdinal() const {
+  return codeview::ThunkOrdinal::Standard;
+}
+
+uint64_t NativeRawSymbol::getLength() const {
+  return 0;
+}
+
+uint64_t NativeRawSymbol::getLiveRangeLength() const {
+  return 0;
+}
+
+uint64_t NativeRawSymbol::getVirtualAddress() const {
+  return 0;
+}
+
+PDB_UdtType NativeRawSymbol::getUdtKind() const {
+  return PDB_UdtType::Struct;
+}
+
+bool NativeRawSymbol::hasConstructor() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasCustomCallingConvention() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasFarReturn() const {
+  return false;
+}
+
+bool NativeRawSymbol::isCode() const {
+  return false;
+}
+
+bool NativeRawSymbol::isCompilerGenerated() const {
+  return false;
+}
+
+bool NativeRawSymbol::isConstType() const {
+  return false;
+}
+
+bool NativeRawSymbol::isEditAndContinueEnabled() const {
+  return false;
+}
+
+bool NativeRawSymbol::isFunction() const {
+  return false;
+}
+
+bool NativeRawSymbol::getAddressTaken() const {
+  return false;
+}
+
+bool NativeRawSymbol::getNoStackOrdering() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasAlloca() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasAssignmentOperator() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasCTypes() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasCastOperator() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasDebugInfo() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasEH() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasEHa() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasInlAsm() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasInlineAttribute() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasInterruptReturn() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasFramePointer() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasLongJump() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasManagedCode() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasNestedTypes() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasNoInlineAttribute() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasNoReturnAttribute() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasOptimizedCodeDebugInfo() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasOverloadedOperator() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasSEH() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasSecurityChecks() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasSetJump() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasStrictGSCheck() const {
+  return false;
+}
+
+bool NativeRawSymbol::isAcceleratorGroupSharedLocal() const {
+  return false;
+}
+
+bool NativeRawSymbol::isAcceleratorPointerTagLiveRange() const {
+  return false;
+}
+
+bool NativeRawSymbol::isAcceleratorStubFunction() const {
+  return false;
+}
+
+bool NativeRawSymbol::isAggregated() const {
+  return false;
+}
+
+bool NativeRawSymbol::isIntroVirtualFunction() const {
+  return false;
+}
+
+bool NativeRawSymbol::isCVTCIL() const {
+  return false;
+}
+
+bool NativeRawSymbol::isConstructorVirtualBase() const {
+  return false;
+}
+
+bool NativeRawSymbol::isCxxReturnUdt() const {
+  return false;
+}
+
+bool NativeRawSymbol::isDataAligned() const {
+  return false;
+}
+
+bool NativeRawSymbol::isHLSLData() const {
+  return false;
+}
+
+bool NativeRawSymbol::isHotpatchable() const {
+  return false;
+}
+
+bool NativeRawSymbol::isIndirectVirtualBaseClass() const {
+  return false;
+}
+
+bool NativeRawSymbol::isInterfaceUdt() const {
+  return false;
+}
+
+bool NativeRawSymbol::isIntrinsic() const {
+  return false;
+}
+
+bool NativeRawSymbol::isLTCG() const {
+  return false;
+}
+
+bool NativeRawSymbol::isLocationControlFlowDependent() const {
+  return false;
+}
+
+bool NativeRawSymbol::isMSILNetmodule() const {
+  return false;
+}
+
+bool NativeRawSymbol::isMatrixRowMajor() const {
+  return false;
+}
+
+bool NativeRawSymbol::isManagedCode() const {
+  return false;
+}
+
+bool NativeRawSymbol::isMSILCode() const {
+  return false;
+}
+
+bool NativeRawSymbol::isMultipleInheritance() const {
+  return false;
+}
+
+bool NativeRawSymbol::isNaked() const {
+  return false;
+}
+
+bool NativeRawSymbol::isNested() const {
+  return false;
+}
+
+bool NativeRawSymbol::isOptimizedAway() const {
+  return false;
+}
+
+bool NativeRawSymbol::isPacked() const {
+  return false;
+}
+
+bool NativeRawSymbol::isPointerBasedOnSymbolValue() const {
+  return false;
+}
+
+bool NativeRawSymbol::isPointerToDataMember() const {
+  return false;
+}
+
+bool NativeRawSymbol::isPointerToMemberFunction() const {
+  return false;
+}
+
+bool NativeRawSymbol::isPureVirtual() const {
+  return false;
+}
+
+bool NativeRawSymbol::isRValueReference() const {
+  return false;
+}
+
+bool NativeRawSymbol::isRefUdt() const {
+  return false;
+}
+
+bool NativeRawSymbol::isReference() const {
+  return false;
+}
+
+bool NativeRawSymbol::isRestrictedType() const {
+  return false;
+}
+
+bool NativeRawSymbol::isReturnValue() const {
+  return false;
+}
+
+bool NativeRawSymbol::isSafeBuffers() const {
+  return false;
+}
+
+bool NativeRawSymbol::isScoped() const {
+  return false;
+}
+
+bool NativeRawSymbol::isSdl() const {
+  return false;
+}
+
+bool NativeRawSymbol::isSingleInheritance() const {
+  return false;
+}
+
+bool NativeRawSymbol::isSplitted() const {
+  return false;
+}
+
+bool NativeRawSymbol::isStatic() const {
+  return false;
+}
+
+bool NativeRawSymbol::hasPrivateSymbols() const {
+  return false;
+}
+
+bool NativeRawSymbol::isUnalignedType() const {
+  return false;
+}
+
+bool NativeRawSymbol::isUnreached() const {
+  return false;
+}
+
+bool NativeRawSymbol::isValueUdt() const {
+  return false;
+}
+
+bool NativeRawSymbol::isVirtual() const {
+  return false;
+}
+
+bool NativeRawSymbol::isVirtualBaseClass() const {
+  return false;
+}
+
+bool NativeRawSymbol::isVirtualInheritance() const {
+  return false;
+}
+
+bool NativeRawSymbol::isVolatileType() const {
+  return false;
+}
+
+bool NativeRawSymbol::wasInlined() const {
+  return false;
+}
+
+std::string NativeRawSymbol::getUnused() const {
+  return {};
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
new file mode 100644
index 0000000..7807e31
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -0,0 +1,217 @@
+//===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.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"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+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)),
+      Cache(*this, getDbiStreamPtr(*Pdb)) {}
+
+NativeSession::~NativeSession() = default;
+
+Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
+                                   std::unique_ptr<IPDBSession> &Session) {
+  StringRef Path = Buffer->getBufferIdentifier();
+  auto Stream = llvm::make_unique<MemoryBufferByteStream>(
+      std::move(Buffer), llvm::support::little);
+
+  auto Allocator = llvm::make_unique<BumpPtrAllocator>();
+  auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
+  if (auto EC = File->parseFileHeaders())
+    return EC;
+  if (auto EC = File->parseStreamData())
+    return EC;
+
+  Session =
+      llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator));
+
+  return Error::success();
+}
+
+Error NativeSession::createFromExe(StringRef Path,
+                                   std::unique_ptr<IPDBSession> &Session) {
+  return make_error<RawError>(raw_error_code::feature_unsupported);
+}
+
+uint64_t NativeSession::getLoadAddress() const { return 0; }
+
+bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
+
+std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
+  return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::getSymbolById(SymIndexId SymbolId) const {
+  return Cache.getSymbolById(SymbolId);
+}
+
+bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
+                                 uint32_t &Offset) const {
+  return false;
+}
+
+bool NativeSession::addressForRVA(uint32_t VA, uint32_t &Section,
+                                  uint32_t &Offset) const {
+  return false;
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const {
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+                                      PDB_SymType Type) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
+                               const IPDBSourceFile &File) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersByAddress(uint64_t Address,
+                                        uint32_t Length) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+                                           uint32_t Length) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSourceFiles>
+NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
+                               StringRef Pattern,
+                               PDB_NameSearchFlags Flags) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBSourceFile>
+NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
+                                 StringRef Pattern,
+                                 PDB_NameSearchFlags Flags) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+NativeSession::findCompilandsForSourceFile(StringRef Pattern,
+                                           PDB_NameSearchFlags Flags) const {
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
+                                             PDB_NameSearchFlags Flags) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
+    const PDBSymbolCompiland &Compiland) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBSourceFile>
+NativeSession::getSourceFileById(uint32_t FileId) const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumInjectedSources>
+NativeSession::getInjectedSources() const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSectionContribs>
+NativeSession::getSectionContribs() const {
+  return nullptr;
+}
+
+std::unique_ptr<IPDBEnumFrameData>
+NativeSession::getFrameData() const {
+  return nullptr;
+}
+
+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/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
new file mode 100644
index 0000000..6ebb8ca
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
@@ -0,0 +1,123 @@
+//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeSymbolEnumerator::NativeSymbolEnumerator(
+    NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
+    codeview::EnumeratorRecord Record)
+    : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
+      Record(std::move(Record)) {}
+
+NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
+
+void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent,
+                                  PdbSymbolIdField ShowIdFields,
+                                  PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+  dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+                    PdbSymbolIdField::ClassParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolIdField(OS, "lexicalParentId", getLexicalParentId(), Indent,
+                    Session, PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
+  dumpSymbolField(OS, "locationType", getLocationType(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+  dumpSymbolField(OS, "value", getValue(), Indent);
+}
+
+SymIndexId NativeSymbolEnumerator::getClassParentId() const {
+  return Parent.getSymIndexId();
+}
+
+SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
+
+std::string NativeSymbolEnumerator::getName() const { return Record.Name; }
+
+SymIndexId NativeSymbolEnumerator::getTypeId() const {
+  return Parent.getTypeId();
+}
+
+PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
+  return PDB_DataKind::Constant;
+}
+
+PDB_LocType NativeSymbolEnumerator::getLocationType() const {
+  return PDB_LocType::Constant;
+}
+
+bool NativeSymbolEnumerator::isConstType() const { return false; }
+
+bool NativeSymbolEnumerator::isVolatileType() const { return false; }
+
+bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
+
+Variant NativeSymbolEnumerator::getValue() const {
+  const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
+
+  switch (BT.getBuiltinType()) {
+  case PDB_BuiltinType::Int:
+  case PDB_BuiltinType::Long:
+  case PDB_BuiltinType::Char: {
+    assert(Record.Value.isSignedIntN(BT.getLength() * 8));
+    int64_t N = Record.Value.getSExtValue();
+    switch (BT.getLength()) {
+    case 1:
+      return Variant{static_cast<int8_t>(N)};
+    case 2:
+      return Variant{static_cast<int16_t>(N)};
+    case 4:
+      return Variant{static_cast<int32_t>(N)};
+    case 8:
+      return Variant{static_cast<int64_t>(N)};
+    }
+    break;
+  }
+  case PDB_BuiltinType::UInt:
+  case PDB_BuiltinType::ULong: {
+    assert(Record.Value.isIntN(BT.getLength() * 8));
+    uint64_t U = Record.Value.getZExtValue();
+    switch (BT.getLength()) {
+    case 1:
+      return Variant{static_cast<uint8_t>(U)};
+    case 2:
+      return Variant{static_cast<uint16_t>(U)};
+    case 4:
+      return Variant{static_cast<uint32_t>(U)};
+    case 8:
+      return Variant{static_cast<uint64_t>(U)};
+    }
+    break;
+  }
+  case PDB_BuiltinType::Bool: {
+    assert(Record.Value.isIntN(BT.getLength() * 8));
+    uint64_t U = Record.Value.getZExtValue();
+    return Variant{static_cast<bool>(U)};
+  }
+  default:
+    assert(false && "Invalid enumeration type");
+    break;
+  }
+
+  return Variant{Record.Value.getSExtValue()};
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
new file mode 100644
index 0000000..a5256172
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
@@ -0,0 +1,67 @@
+//===- NativeTypeArray.cpp - info about arrays ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeArray::NativeTypeArray(NativeSession &Session, SymIndexId Id,
+                                 codeview::TypeIndex TI,
+                                 codeview::ArrayRecord Record)
+    : NativeRawSymbol(Session, PDB_SymType::ArrayType, Id), Record(Record),
+      Index(TI) {}
+NativeTypeArray::~NativeTypeArray() {}
+
+void NativeTypeArray::dump(raw_ostream &OS, int Indent,
+                           PdbSymbolIdField ShowIdFields,
+                           PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolField(OS, "arrayIndexTypeId", getArrayIndexTypeId(), Indent);
+  dumpSymbolIdField(OS, "elementTypeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "count", getCount(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypeArray::getArrayIndexTypeId() const {
+  return Session.getSymbolCache().findSymbolByTypeIndex(Record.getIndexType());
+}
+
+bool NativeTypeArray::isConstType() const { return false; }
+
+bool NativeTypeArray::isUnalignedType() const { return false; }
+
+bool NativeTypeArray::isVolatileType() const { return false; }
+
+uint32_t NativeTypeArray::getCount() const {
+  NativeRawSymbol &Element =
+      Session.getSymbolCache().getNativeSymbolById(getTypeId());
+  return getLength() / Element.getLength();
+}
+
+SymIndexId NativeTypeArray::getTypeId() const {
+  return Session.getSymbolCache().findSymbolByTypeIndex(
+      Record.getElementType());
+}
+
+uint64_t NativeTypeArray::getLength() const { return Record.Size; }
\ No newline at end of file
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
new file mode 100644
index 0000000..7b0f13f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
@@ -0,0 +1,47 @@
+//===- NativeTypeBuiltin.cpp -------------------------------------- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id,
+                                     ModifierOptions Mods, PDB_BuiltinType T,
+                                     uint64_t L)
+    : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id),
+      Session(PDBSession), Mods(Mods), Type(T), Length(L) {}
+
+NativeTypeBuiltin::~NativeTypeBuiltin() {}
+
+void NativeTypeBuiltin::dump(raw_ostream &OS, int Indent,
+                             PdbSymbolIdField ShowIdFields,
+                             PdbSymbolIdField RecurseIdFields) const {}
+
+PDB_SymType NativeTypeBuiltin::getSymTag() const {
+  return PDB_SymType::BuiltinType;
+}
+
+PDB_BuiltinType NativeTypeBuiltin::getBuiltinType() const { return Type; }
+
+bool NativeTypeBuiltin::isConstType() const {
+  return (Mods & ModifierOptions::Const) != ModifierOptions::None;
+}
+
+uint64_t NativeTypeBuiltin::getLength() const { return Length; }
+
+bool NativeTypeBuiltin::isUnalignedType() const {
+  return (Mods & ModifierOptions::Unaligned) != ModifierOptions::None;
+}
+
+bool NativeTypeBuiltin::isVolatileType() const {
+  return (Mods & ModifierOptions::Volatile) != ModifierOptions::None;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
new file mode 100644
index 0000000..37176fe
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
@@ -0,0 +1,382 @@
+//===- NativeTypeEnum.cpp - info about enum type ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include "llvm/Support/FormatVariadic.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// Yea, this is a pretty terrible class name.  But if we have an enum:
+//
+// enum Foo {
+//  A,
+//  B
+// };
+//
+// then A and B are the "enumerators" of the "enum" Foo.  And we need
+// to enumerate them.
+class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
+public:
+  NativeEnumEnumEnumerators(NativeSession &Session,
+                            const NativeTypeEnum &ClassParent);
+
+  uint32_t getChildCount() const override;
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+  std::unique_ptr<PDBSymbol> getNext() override;
+  void reset() override;
+
+private:
+  Error visitKnownMember(CVMemberRecord &CVM,
+                         EnumeratorRecord &Record) override;
+  Error visitKnownMember(CVMemberRecord &CVM,
+                         ListContinuationRecord &Record) override;
+
+  NativeSession &Session;
+  const NativeTypeEnum &ClassParent;
+  std::vector<EnumeratorRecord> Enumerators;
+  Optional<TypeIndex> ContinuationIndex;
+  uint32_t Index = 0;
+};
+} // namespace
+
+NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
+    NativeSession &Session, const NativeTypeEnum &ClassParent)
+    : Session(Session), ClassParent(ClassParent) {
+  TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+  LazyRandomTypeCollection &Types = Tpi.typeCollection();
+
+  ContinuationIndex = ClassParent.getEnumRecord().FieldList;
+  while (ContinuationIndex) {
+    CVType FieldList = Types.getType(*ContinuationIndex);
+    assert(FieldList.kind() == LF_FIELDLIST);
+    ContinuationIndex.reset();
+    cantFail(visitMemberRecordStream(FieldList.data(), *this));
+  }
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
+                                                  EnumeratorRecord &Record) {
+  Enumerators.push_back(Record);
+  return Error::success();
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(
+    CVMemberRecord &CVM, ListContinuationRecord &Record) {
+  ContinuationIndex = Record.ContinuationIndex;
+  return Error::success();
+}
+
+uint32_t NativeEnumEnumEnumerators::getChildCount() const {
+  return Enumerators.size();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
+  if (Index >= getChildCount())
+    return nullptr;
+
+  SymIndexId Id = Session.getSymbolCache()
+                      .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+                          ClassParent.getEnumRecord().FieldList, Index,
+                          ClassParent, Enumerators[Index]);
+  return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
+  if (Index >= getChildCount())
+    return nullptr;
+
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumEnumEnumerators::reset() { Index = 0; }
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+                               TypeIndex Index, EnumRecord Record)
+    : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
+      Record(std::move(Record)) {}
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+                               NativeTypeEnum &UnmodifiedType,
+                               codeview::ModifierRecord Modifier)
+    : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
+      UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeEnum::~NativeTypeEnum() {}
+
+void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
+                          PdbSymbolIdField ShowIdFields,
+                          PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
+                  Indent);
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+  if (Modifiers.hasValue())
+    dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+                      Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+                      RecurseIdFields);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+  dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+  dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+  dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+  dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+  dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+  dumpSymbolField(OS, "nested", isNested(), Indent);
+  dumpSymbolField(OS, "packed", isPacked(), Indent);
+  dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+  dumpSymbolField(OS, "scoped", isScoped(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeTypeEnum::findChildren(PDB_SymType Type) const {
+  if (Type != PDB_SymType::Data)
+    return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+  const NativeTypeEnum *ClassParent = nullptr;
+  if (!Modifiers)
+    ClassParent = this;
+  else
+    ClassParent = UnmodifiedType;
+  return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
+}
+
+PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
+
+PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getBuiltinType();
+
+  Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
+
+  codeview::TypeIndex Underlying = Record->getUnderlyingType();
+
+  // This indicates a corrupt record.
+  if (!Underlying.isSimple() ||
+      Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
+    return PDB_BuiltinType::None;
+  }
+
+  switch (Underlying.getSimpleKind()) {
+  case SimpleTypeKind::Boolean128:
+  case SimpleTypeKind::Boolean64:
+  case SimpleTypeKind::Boolean32:
+  case SimpleTypeKind::Boolean16:
+  case SimpleTypeKind::Boolean8:
+    return PDB_BuiltinType::Bool;
+  case SimpleTypeKind::NarrowCharacter:
+  case SimpleTypeKind::UnsignedCharacter:
+  case SimpleTypeKind::SignedCharacter:
+    return PDB_BuiltinType::Char;
+  case SimpleTypeKind::WideCharacter:
+    return PDB_BuiltinType::WCharT;
+  case SimpleTypeKind::Character16:
+    return PDB_BuiltinType::Char16;
+  case SimpleTypeKind::Character32:
+    return PDB_BuiltinType::Char32;
+  case SimpleTypeKind::Int128:
+  case SimpleTypeKind::Int128Oct:
+  case SimpleTypeKind::Int16:
+  case SimpleTypeKind::Int16Short:
+  case SimpleTypeKind::Int32:
+  case SimpleTypeKind::Int32Long:
+  case SimpleTypeKind::Int64:
+  case SimpleTypeKind::Int64Quad:
+    return PDB_BuiltinType::Int;
+  case SimpleTypeKind::UInt128:
+  case SimpleTypeKind::UInt128Oct:
+  case SimpleTypeKind::UInt16:
+  case SimpleTypeKind::UInt16Short:
+  case SimpleTypeKind::UInt32:
+  case SimpleTypeKind::UInt32Long:
+  case SimpleTypeKind::UInt64:
+  case SimpleTypeKind::UInt64Quad:
+    return PDB_BuiltinType::UInt;
+  case SimpleTypeKind::HResult:
+    return PDB_BuiltinType::HResult;
+  case SimpleTypeKind::Complex16:
+  case SimpleTypeKind::Complex32:
+  case SimpleTypeKind::Complex32PartialPrecision:
+  case SimpleTypeKind::Complex64:
+  case SimpleTypeKind::Complex80:
+  case SimpleTypeKind::Complex128:
+    return PDB_BuiltinType::Complex;
+  case SimpleTypeKind::Float16:
+  case SimpleTypeKind::Float32:
+  case SimpleTypeKind::Float32PartialPrecision:
+  case SimpleTypeKind::Float48:
+  case SimpleTypeKind::Float64:
+  case SimpleTypeKind::Float80:
+  case SimpleTypeKind::Float128:
+    return PDB_BuiltinType::Float;
+  default:
+    return PDB_BuiltinType::None;
+  }
+  llvm_unreachable("Unreachable");
+}
+
+SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
+  return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
+}
+
+bool NativeTypeEnum::hasConstructor() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasConstructor();
+
+  return bool(Record->getOptions() &
+              codeview::ClassOptions::HasConstructorOrDestructor);
+}
+
+bool NativeTypeEnum::hasAssignmentOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasAssignmentOperator();
+
+  return bool(Record->getOptions() &
+              codeview::ClassOptions::HasOverloadedAssignmentOperator);
+}
+
+bool NativeTypeEnum::hasNestedTypes() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasNestedTypes();
+
+  return bool(Record->getOptions() &
+              codeview::ClassOptions::ContainsNestedClass);
+}
+
+bool NativeTypeEnum::isIntrinsic() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isIntrinsic();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
+}
+
+bool NativeTypeEnum::hasCastOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasCastOperator();
+
+  return bool(Record->getOptions() &
+              codeview::ClassOptions::HasConversionOperator);
+}
+
+uint64_t NativeTypeEnum::getLength() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getLength();
+
+  const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
+      Record->getUnderlyingType());
+  const auto UnderlyingType =
+      Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
+  return UnderlyingType ? UnderlyingType->getLength() : 0;
+}
+
+std::string NativeTypeEnum::getName() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getName();
+
+  return Record->getName();
+}
+
+bool NativeTypeEnum::isNested() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isNested();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Nested);
+}
+
+bool NativeTypeEnum::hasOverloadedOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasOverloadedOperator();
+
+  return bool(Record->getOptions() &
+              codeview::ClassOptions::HasOverloadedOperator);
+}
+
+bool NativeTypeEnum::isPacked() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isPacked();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Packed);
+}
+
+bool NativeTypeEnum::isScoped() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isScoped();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
+}
+
+SymIndexId NativeTypeEnum::getTypeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getTypeId();
+
+  return Session.getSymbolCache().findSymbolByTypeIndex(
+      Record->getUnderlyingType());
+}
+
+bool NativeTypeEnum::isRefUdt() const { return false; }
+
+bool NativeTypeEnum::isValueUdt() const { return false; }
+
+bool NativeTypeEnum::isInterfaceUdt() const { return false; }
+
+bool NativeTypeEnum::isConstType() const {
+  if (!Modifiers)
+    return false;
+  return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
+          ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isVolatileType() const {
+  if (!Modifiers)
+    return false;
+  return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
+          ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isUnalignedType() const {
+  if (!Modifiers)
+    return false;
+  return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
+          ModifierOptions::None);
+}
+
+const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getUnderlyingBuiltinType();
+
+  return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
+      getTypeId());
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
new file mode 100644
index 0000000..a9590ff
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
@@ -0,0 +1,200 @@
+//===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// This is kind of a silly class, hence why we keep it private to the file.
+// It's only purpose is to wrap the real type record.  I guess this is so that
+// we can have the lexical parent point to the function instead of the global
+// scope.
+class NativeTypeFunctionArg : public NativeRawSymbol {
+public:
+  NativeTypeFunctionArg(NativeSession &Session,
+                        std::unique_ptr<PDBSymbol> RealType)
+      : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0),
+        RealType(std::move(RealType)) {}
+
+  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+            PdbSymbolIdField RecurseIdFields) const override {
+    NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+    dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                      PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+  }
+
+  SymIndexId getTypeId() const override { return RealType->getSymIndexId(); }
+
+  std::unique_ptr<PDBSymbol> RealType;
+};
+
+class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> {
+public:
+  NativeEnumFunctionArgs(NativeSession &Session,
+                         std::unique_ptr<NativeEnumTypes> TypeEnumerator)
+      : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {}
+
+  uint32_t getChildCount() const override {
+    return TypeEnumerator->getChildCount();
+  }
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
+    return wrap(TypeEnumerator->getChildAtIndex(Index));
+  }
+  std::unique_ptr<PDBSymbol> getNext() override {
+    return wrap(TypeEnumerator->getNext());
+  }
+
+  void reset() override { TypeEnumerator->reset(); }
+
+private:
+  std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const {
+    if (!S)
+      return nullptr;
+    auto NTFA = llvm::make_unique<NativeTypeFunctionArg>(Session, std::move(S));
+    return PDBSymbol::create(Session, std::move(NTFA));
+  }
+  NativeSession &Session;
+  std::unique_ptr<NativeEnumTypes> TypeEnumerator;
+};
+} // namespace
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session,
+                                             SymIndexId Id,
+                                             codeview::TypeIndex Index,
+                                             codeview::ProcedureRecord Proc)
+    : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+      Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {}
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(
+    NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index,
+    codeview::MemberFunctionRecord MemberFunc)
+    : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+      MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {}
+
+void NativeTypeFunctionSig::initialize() {
+  if (IsMemberFunction) {
+    ClassParentId =
+        Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType);
+    initializeArgList(MemberFunc.ArgumentList);
+  } else {
+    initializeArgList(Proc.ArgumentList);
+  }
+}
+
+NativeTypeFunctionSig::~NativeTypeFunctionSig() {}
+
+void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) {
+  TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+  CVType CVT = Tpi.typeCollection().getType(ArgListTI);
+
+  cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList));
+}
+
+void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent,
+                                 PdbSymbolIdField ShowIdFields,
+                                 PdbSymbolIdField RecurseIdFields) const {
+
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+
+  dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent);
+  dumpSymbolField(OS, "count", getCount(), Indent);
+  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+  if (IsMemberFunction)
+    dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent);
+  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(),
+                  Indent);
+  dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeTypeFunctionSig::findChildren(PDB_SymType Type) const {
+  if (Type != PDB_SymType::FunctionArg)
+    return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+  auto NET = llvm::make_unique<NativeEnumTypes>(Session,
+                                                /* copy */ ArgList.ArgIndices);
+  return std::unique_ptr<IPDBEnumSymbols>(
+      new NativeEnumFunctionArgs(Session, std::move(NET)));
+}
+
+SymIndexId NativeTypeFunctionSig::getClassParentId() const {
+  if (!IsMemberFunction)
+    return 0;
+
+  return ClassParentId;
+}
+
+PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const {
+  return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv;
+}
+
+uint32_t NativeTypeFunctionSig::getCount() const {
+  return IsMemberFunction ? (1 + MemberFunc.getParameterCount())
+                          : Proc.getParameterCount();
+}
+
+SymIndexId NativeTypeFunctionSig::getTypeId() const {
+  TypeIndex ReturnTI =
+      IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType();
+
+  SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI);
+  return Result;
+}
+
+int32_t NativeTypeFunctionSig::getThisAdjust() const {
+  return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0;
+}
+
+bool NativeTypeFunctionSig::hasConstructor() const {
+  if (!IsMemberFunction)
+    return false;
+
+  return (MemberFunc.getOptions() & FunctionOptions::Constructor) !=
+         FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isConstType() const { return false; }
+
+bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
+  if (!IsMemberFunction)
+    return false;
+
+  return (MemberFunc.getOptions() &
+          FunctionOptions::ConstructorWithVirtualBases) !=
+         FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isCxxReturnUdt() const {
+  FunctionOptions Options =
+      IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions();
+  return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
+
+bool NativeTypeFunctionSig::isVolatileType() const { return false; }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
new file mode 100644
index 0000000..bd8ecb6
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
@@ -0,0 +1,194 @@
+//===- NativeTypePointer.cpp - info about pointer type ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+                                     codeview::TypeIndex TI)
+    : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI) {
+  assert(TI.isSimple());
+  assert(TI.getSimpleMode() != SimpleTypeMode::Direct);
+}
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+                                     codeview::TypeIndex TI,
+                                     codeview::PointerRecord Record)
+    : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI),
+      Record(std::move(Record)) {}
+
+NativeTypePointer::~NativeTypePointer() {}
+
+void NativeTypePointer::dump(raw_ostream &OS, int Indent,
+                             PdbSymbolIdField ShowIdFields,
+                             PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  if (isMemberPointer()) {
+    dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+                      PdbSymbolIdField::ClassParent, ShowIdFields,
+                      RecurseIdFields);
+  }
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "isPointerToDataMember", isPointerToDataMember(), Indent);
+  dumpSymbolField(OS, "isPointerToMemberFunction", isPointerToMemberFunction(),
+                  Indent);
+  dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent);
+  dumpSymbolField(OS, "reference", isReference(), Indent);
+  dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent);
+  if (isMemberPointer()) {
+    if (isSingleInheritance())
+      dumpSymbolField(OS, "isSingleInheritance", 1, Indent);
+    else if (isMultipleInheritance())
+      dumpSymbolField(OS, "isMultipleInheritance", 1, Indent);
+    else if (isVirtualInheritance())
+      dumpSymbolField(OS, "isVirtualInheritance", 1, Indent);
+  }
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypePointer::getClassParentId() const {
+  if (!isMemberPointer())
+    return 0;
+
+  assert(Record);
+  const MemberPointerInfo &MPI = Record->getMemberInfo();
+  return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType);
+}
+
+uint64_t NativeTypePointer::getLength() const {
+  if (Record)
+    return Record->getSize();
+
+  switch (TI.getSimpleMode()) {
+  case SimpleTypeMode::NearPointer:
+  case SimpleTypeMode::FarPointer:
+  case SimpleTypeMode::HugePointer:
+    return 2;
+  case SimpleTypeMode::NearPointer32:
+  case SimpleTypeMode::FarPointer32:
+    return 4;
+  case SimpleTypeMode::NearPointer64:
+    return 8;
+  case SimpleTypeMode::NearPointer128:
+    return 16;
+  default:
+    assert(false && "invalid simple type mode!");
+  }
+  return 0;
+}
+
+SymIndexId NativeTypePointer::getTypeId() const {
+  // This is the pointee SymIndexId.
+  TypeIndex Referent = Record ? Record->ReferentType : TI.makeDirect();
+
+  return Session.getSymbolCache().findSymbolByTypeIndex(Referent);
+}
+
+bool NativeTypePointer::isReference() const {
+  if (!Record)
+    return false;
+  return Record->getMode() == PointerMode::LValueReference;
+}
+
+bool NativeTypePointer::isRValueReference() const {
+  if (!Record)
+    return false;
+  return Record->getMode() == PointerMode::RValueReference;
+}
+
+bool NativeTypePointer::isPointerToDataMember() const {
+  if (!Record)
+    return false;
+  return Record->getMode() == PointerMode::PointerToDataMember;
+}
+
+bool NativeTypePointer::isPointerToMemberFunction() const {
+  if (!Record)
+    return false;
+  return Record->getMode() == PointerMode::PointerToMemberFunction;
+}
+
+bool NativeTypePointer::isConstType() const {
+  if (!Record)
+    return false;
+  return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None;
+}
+
+bool NativeTypePointer::isRestrictedType() const {
+  if (!Record)
+    return false;
+  return (Record->getOptions() & PointerOptions::Restrict) !=
+         PointerOptions::None;
+}
+
+bool NativeTypePointer::isVolatileType() const {
+  if (!Record)
+    return false;
+  return (Record->getOptions() & PointerOptions::Volatile) !=
+         PointerOptions::None;
+}
+
+bool NativeTypePointer::isUnalignedType() const {
+  if (!Record)
+    return false;
+  return (Record->getOptions() & PointerOptions::Unaligned) !=
+         PointerOptions::None;
+}
+
+static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
+                                     PointerToMemberRepresentation P1,
+                                     PointerToMemberRepresentation P2) {
+  return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
+}
+
+bool NativeTypePointer::isSingleInheritance() const {
+  if (!isMemberPointer())
+    return false;
+  return isInheritanceKind(
+      Record->getMemberInfo(),
+      PointerToMemberRepresentation::SingleInheritanceData,
+      PointerToMemberRepresentation::SingleInheritanceFunction);
+}
+
+bool NativeTypePointer::isMultipleInheritance() const {
+  if (!isMemberPointer())
+    return false;
+  return isInheritanceKind(
+      Record->getMemberInfo(),
+      PointerToMemberRepresentation::MultipleInheritanceData,
+      PointerToMemberRepresentation::MultipleInheritanceFunction);
+}
+
+bool NativeTypePointer::isVirtualInheritance() const {
+  if (!isMemberPointer())
+    return false;
+  return isInheritanceKind(
+      Record->getMemberInfo(),
+      PointerToMemberRepresentation::VirtualInheritanceData,
+      PointerToMemberRepresentation::VirtualInheritanceFunction);
+}
+
+bool NativeTypePointer::isMemberPointer() const {
+  return isPointerToDataMember() || isPointerToMemberFunction();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
new file mode 100644
index 0000000..60b3732
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
@@ -0,0 +1,27 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id,
+                                     codeview::UDTSym Typedef)
+    : NativeRawSymbol(Session, PDB_SymType::Typedef, Id),
+      Record(std::move(Typedef)) {}
+
+NativeTypeTypedef::~NativeTypeTypedef() {}
+
+void NativeTypeTypedef::dump(raw_ostream &OS, int Indent,
+                             PdbSymbolIdField ShowIdFields,
+                             PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+                    PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+}
+
+std::string NativeTypeTypedef::getName() const { return Record.Name; }
+
+SymIndexId NativeTypeTypedef::getTypeId() const {
+  return Session.getSymbolCache().findSymbolByTypeIndex(Record.Type);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
new file mode 100644
index 0000000..3abf91d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
@@ -0,0 +1,221 @@
+//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             codeview::TypeIndex TI, codeview::ClassRecord CR)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+      Class(std::move(CR)), Tag(Class.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             codeview::TypeIndex TI, codeview::UnionRecord UR)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+      Union(std::move(UR)), Tag(Union.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             NativeTypeUDT &UnmodifiedType,
+                             codeview::ModifierRecord Modifier)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id),
+      UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeUDT::~NativeTypeUDT() {}
+
+void NativeTypeUDT::dump(raw_ostream &OS, int Indent,
+                         PdbSymbolIdField ShowIdFields,
+                         PdbSymbolIdField RecurseIdFields) const {
+
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  if (Modifiers.hasValue())
+    dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+                      Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+                      RecurseIdFields);
+  if (getUdtKind() != PDB_UdtType::Union)
+    dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(),
+                    Indent);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "udtKind", getUdtKind(), Indent);
+  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+  dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+  dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+  dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+  dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+  dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+  dumpSymbolField(OS, "nested", isNested(), Indent);
+  dumpSymbolField(OS, "packed", isPacked(), Indent);
+  dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+  dumpSymbolField(OS, "scoped", isScoped(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::string NativeTypeUDT::getName() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getName();
+
+  return Tag->getName();
+}
+
+SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
+
+SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getSymIndexId();
+
+  return 0;
+}
+
+SymIndexId NativeTypeUDT::getVirtualTableShapeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getVirtualTableShapeId();
+
+  if (Class)
+    return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape);
+
+  return 0;
+}
+
+uint64_t NativeTypeUDT::getLength() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getLength();
+
+  if (Class)
+    return Class->getSize();
+
+  return Union->getSize();
+}
+
+PDB_UdtType NativeTypeUDT::getUdtKind() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getUdtKind();
+
+  switch (Tag->Kind) {
+  case TypeRecordKind::Class:
+    return PDB_UdtType::Class;
+  case TypeRecordKind::Union:
+    return PDB_UdtType::Union;
+  case TypeRecordKind::Struct:
+    return PDB_UdtType::Struct;
+  case TypeRecordKind::Interface:
+    return PDB_UdtType::Interface;
+  default:
+    llvm_unreachable("Unexected udt kind");
+  }
+}
+
+bool NativeTypeUDT::hasConstructor() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasConstructor();
+
+  return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::isConstType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Const) !=
+         ModifierOptions::None;
+}
+
+bool NativeTypeUDT::hasAssignmentOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasAssignmentOperator();
+
+  return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasCastOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasCastOperator();
+
+  return (Tag->Options & ClassOptions::HasConversionOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasNestedTypes() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasNestedTypes();
+
+  return (Tag->Options & ClassOptions::ContainsNestedClass) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasOverloadedOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasOverloadedOperator();
+
+  return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::isInterfaceUdt() const { return false; }
+
+bool NativeTypeUDT::isIntrinsic() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isIntrinsic();
+
+  return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isNested() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isNested();
+
+  return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isPacked() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isPacked();
+
+  return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isRefUdt() const { return false; }
+
+bool NativeTypeUDT::isScoped() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isScoped();
+
+  return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isValueUdt() const { return false; }
+
+bool NativeTypeUDT::isUnalignedType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
+         ModifierOptions::None;
+}
+
+bool NativeTypeUDT::isVolatileType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
+         ModifierOptions::None;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
new file mode 100644
index 0000000..837fe19
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
@@ -0,0 +1,35 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// Create a pointer record for a non-simple type.
+NativeTypeVTShape::NativeTypeVTShape(NativeSession &Session, SymIndexId Id,
+                                     codeview::TypeIndex TI,
+                                     codeview::VFTableShapeRecord SR)
+    : NativeRawSymbol(Session, PDB_SymType::VTableShape, Id), TI(TI),
+      Record(std::move(SR)) {}
+
+NativeTypeVTShape::~NativeTypeVTShape() {}
+
+void NativeTypeVTShape::dump(raw_ostream &OS, int Indent,
+                             PdbSymbolIdField ShowIdFields,
+                             PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  dumpSymbolField(OS, "count", getCount(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+bool NativeTypeVTShape::isConstType() const { return false; }
+
+bool NativeTypeVTShape::isVolatileType() const { return false; }
+
+bool NativeTypeVTShape::isUnalignedType() const { return false; }
+
+uint32_t NativeTypeVTShape::getCount() const { return Record.Slots.size(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
new file mode 100644
index 0000000..a1f8786
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -0,0 +1,474 @@
+//===- PDBFile.cpp - Low level interface to a PDB file ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+namespace {
+typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
+} // end anonymous namespace
+
+PDBFile::PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer,
+                 BumpPtrAllocator &Allocator)
+    : FilePath(Path), Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
+
+PDBFile::~PDBFile() = default;
+
+StringRef PDBFile::getFilePath() const { return FilePath; }
+
+StringRef PDBFile::getFileDirectory() const {
+  return sys::path::parent_path(FilePath);
+}
+
+uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; }
+
+uint32_t PDBFile::getFreeBlockMapBlock() const {
+  return ContainerLayout.SB->FreeBlockMapBlock;
+}
+
+uint32_t PDBFile::getBlockCount() const {
+  return ContainerLayout.SB->NumBlocks;
+}
+
+uint32_t PDBFile::getNumDirectoryBytes() const {
+  return ContainerLayout.SB->NumDirectoryBytes;
+}
+
+uint32_t PDBFile::getBlockMapIndex() const {
+  return ContainerLayout.SB->BlockMapAddr;
+}
+
+uint32_t PDBFile::getUnknown1() const { return ContainerLayout.SB->Unknown1; }
+
+uint32_t PDBFile::getNumDirectoryBlocks() const {
+  return msf::bytesToBlocks(ContainerLayout.SB->NumDirectoryBytes,
+                            ContainerLayout.SB->BlockSize);
+}
+
+uint64_t PDBFile::getBlockMapOffset() const {
+  return (uint64_t)ContainerLayout.SB->BlockMapAddr *
+         ContainerLayout.SB->BlockSize;
+}
+
+uint32_t PDBFile::getNumStreams() const {
+  return ContainerLayout.StreamSizes.size();
+}
+
+uint32_t PDBFile::getMaxStreamSize() const {
+  return *std::max_element(ContainerLayout.StreamSizes.begin(),
+                           ContainerLayout.StreamSizes.end());
+}
+
+uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
+  return ContainerLayout.StreamSizes[StreamIndex];
+}
+
+ArrayRef<support::ulittle32_t>
+PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
+  return ContainerLayout.StreamMap[StreamIndex];
+}
+
+uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
+
+Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
+                                                  uint32_t NumBytes) const {
+  uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
+
+  ArrayRef<uint8_t> Result;
+  if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
+    return std::move(EC);
+  return Result;
+}
+
+Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
+                            ArrayRef<uint8_t> Data) const {
+  return make_error<RawError>(raw_error_code::not_writable,
+                              "PDBFile is immutable");
+}
+
+Error PDBFile::parseFileHeaders() {
+  BinaryStreamReader Reader(*Buffer);
+
+  // Initialize SB.
+  const msf::SuperBlock *SB = nullptr;
+  if (auto EC = Reader.readObject(SB)) {
+    consumeError(std::move(EC));
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "MSF superblock is missing");
+  }
+
+  if (auto EC = msf::validateSuperBlock(*SB))
+    return EC;
+
+  if (Buffer->getLength() % SB->BlockSize != 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "File size is not a multiple of block size");
+  ContainerLayout.SB = SB;
+
+  // Initialize Free Page Map.
+  ContainerLayout.FreePageMap.resize(SB->NumBlocks);
+  // The Fpm exists either at block 1 or block 2 of the MSF.  However, this
+  // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and
+  // thusly an equal number of total blocks in the file.  For a block size
+  // of 4KiB (very common), this would yield 32KiB total blocks in file, for a
+  // maximum file size of 32KiB * 4KiB = 128MiB.  Obviously this won't do, so
+  // the Fpm is split across the file at `getBlockSize()` intervals.  As a
+  // result, every block whose index is of the form |{1,2} + getBlockSize() * k|
+  // for any non-negative integer k is an Fpm block.  In theory, we only really
+  // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but
+  // current versions of the MSF format already expect the Fpm to be arranged
+  // at getBlockSize() intervals, so we have to be compatible.
+  // See the function fpmPn() for more information:
+  // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
+  auto FpmStream =
+      MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator);
+  BinaryStreamReader FpmReader(*FpmStream);
+  ArrayRef<uint8_t> FpmBytes;
+  if (auto EC = FpmReader.readBytes(FpmBytes, FpmReader.bytesRemaining()))
+    return EC;
+  uint32_t BlocksRemaining = getBlockCount();
+  uint32_t BI = 0;
+  for (auto Byte : FpmBytes) {
+    uint32_t BlocksThisByte = std::min(BlocksRemaining, 8U);
+    for (uint32_t I = 0; I < BlocksThisByte; ++I) {
+      if (Byte & (1 << I))
+        ContainerLayout.FreePageMap[BI] = true;
+      --BlocksRemaining;
+      ++BI;
+    }
+  }
+
+  Reader.setOffset(getBlockMapOffset());
+  if (auto EC = Reader.readArray(ContainerLayout.DirectoryBlocks,
+                                 getNumDirectoryBlocks()))
+    return EC;
+
+  return Error::success();
+}
+
+Error PDBFile::parseStreamData() {
+  assert(ContainerLayout.SB);
+  if (DirectoryStream)
+    return Error::success();
+
+  uint32_t NumStreams = 0;
+
+  // Normally you can't use a MappedBlockStream without having fully parsed the
+  // PDB file, because it accesses the directory and various other things, which
+  // is exactly what we are attempting to parse.  By specifying a custom
+  // subclass of IPDBStreamData which only accesses the fields that have already
+  // been parsed, we can avoid this and reuse MappedBlockStream.
+  auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer,
+                                                     Allocator);
+  BinaryStreamReader Reader(*DS);
+  if (auto EC = Reader.readInteger(NumStreams))
+    return EC;
+
+  if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
+    return EC;
+  for (uint32_t I = 0; I < NumStreams; ++I) {
+    uint32_t StreamSize = getStreamByteSize(I);
+    // FIXME: What does StreamSize ~0U mean?
+    uint64_t NumExpectedStreamBlocks =
+        StreamSize == UINT32_MAX
+            ? 0
+            : msf::bytesToBlocks(StreamSize, ContainerLayout.SB->BlockSize);
+
+    // For convenience, we store the block array contiguously.  This is because
+    // if someone calls setStreamMap(), it is more convenient to be able to call
+    // it with an ArrayRef instead of setting up a StreamRef.  Since the
+    // DirectoryStream is cached in the class and thus lives for the life of the
+    // class, we can be guaranteed that readArray() will return a stable
+    // reference, even if it has to allocate from its internal pool.
+    ArrayRef<support::ulittle32_t> Blocks;
+    if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
+      return EC;
+    for (uint32_t Block : Blocks) {
+      uint64_t BlockEndOffset =
+          (uint64_t)(Block + 1) * ContainerLayout.SB->BlockSize;
+      if (BlockEndOffset > getFileSize())
+        return make_error<RawError>(raw_error_code::corrupt_file,
+                                    "Stream block map is corrupt.");
+    }
+    ContainerLayout.StreamMap.push_back(Blocks);
+  }
+
+  // We should have read exactly SB->NumDirectoryBytes bytes.
+  assert(Reader.bytesRemaining() == 0);
+  DirectoryStream = std::move(DS);
+  return Error::success();
+}
+
+ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
+  return ContainerLayout.DirectoryBlocks;
+}
+
+std::unique_ptr<MappedBlockStream> PDBFile::createIndexedStream(uint16_t SN) {
+  if (SN == kInvalidStreamIndex)
+    return nullptr;
+  return MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, SN,
+                                                Allocator);
+}
+
+MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const {
+  MSFStreamLayout Result;
+  auto Blocks = getStreamBlockList(StreamIdx);
+  Result.Blocks.assign(Blocks.begin(), Blocks.end());
+  Result.Length = getStreamByteSize(StreamIdx);
+  return Result;
+}
+
+msf::MSFStreamLayout PDBFile::getFpmStreamLayout() const {
+  return msf::getFpmStreamLayout(ContainerLayout);
+}
+
+Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
+  if (!Globals) {
+    auto DbiS = getPDBDbiStream();
+    if (!DbiS)
+      return DbiS.takeError();
+
+    auto GlobalS = safelyCreateIndexedStream(
+        ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex());
+    if (!GlobalS)
+      return GlobalS.takeError();
+    auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS));
+    if (auto EC = TempGlobals->reload())
+      return std::move(EC);
+    Globals = std::move(TempGlobals);
+  }
+  return *Globals;
+}
+
+Expected<InfoStream &> PDBFile::getPDBInfoStream() {
+  if (!Info) {
+    auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB);
+    if (!InfoS)
+      return InfoS.takeError();
+    auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
+    if (auto EC = TempInfo->reload())
+      return std::move(EC);
+    Info = std::move(TempInfo);
+  }
+  return *Info;
+}
+
+Expected<DbiStream &> PDBFile::getPDBDbiStream() {
+  if (!Dbi) {
+    auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
+    if (!DbiS)
+      return DbiS.takeError();
+    auto TempDbi = llvm::make_unique<DbiStream>(std::move(*DbiS));
+    if (auto EC = TempDbi->reload(this))
+      return std::move(EC);
+    Dbi = std::move(TempDbi);
+  }
+  return *Dbi;
+}
+
+Expected<TpiStream &> PDBFile::getPDBTpiStream() {
+  if (!Tpi) {
+    auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI);
+    if (!TpiS)
+      return TpiS.takeError();
+    auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
+    if (auto EC = TempTpi->reload())
+      return std::move(EC);
+    Tpi = std::move(TempTpi);
+  }
+  return *Tpi;
+}
+
+Expected<TpiStream &> PDBFile::getPDBIpiStream() {
+  if (!Ipi) {
+    if (!hasPDBIpiStream())
+      return make_error<RawError>(raw_error_code::no_stream);
+
+    auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI);
+    if (!IpiS)
+      return IpiS.takeError();
+    auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
+    if (auto EC = TempIpi->reload())
+      return std::move(EC);
+    Ipi = std::move(TempIpi);
+  }
+  return *Ipi;
+}
+
+Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
+  if (!Publics) {
+    auto DbiS = getPDBDbiStream();
+    if (!DbiS)
+      return DbiS.takeError();
+
+    auto PublicS = safelyCreateIndexedStream(
+        ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());
+    if (!PublicS)
+      return PublicS.takeError();
+    auto TempPublics = llvm::make_unique<PublicsStream>(std::move(*PublicS));
+    if (auto EC = TempPublics->reload())
+      return std::move(EC);
+    Publics = std::move(TempPublics);
+  }
+  return *Publics;
+}
+
+Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
+  if (!Symbols) {
+    auto DbiS = getPDBDbiStream();
+    if (!DbiS)
+      return DbiS.takeError();
+
+    uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
+    auto SymbolS =
+        safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum);
+    if (!SymbolS)
+      return SymbolS.takeError();
+
+    auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
+    if (auto EC = TempSymbols->reload())
+      return std::move(EC);
+    Symbols = std::move(TempSymbols);
+  }
+  return *Symbols;
+}
+
+Expected<PDBStringTable &> PDBFile::getStringTable() {
+  if (!Strings) {
+    auto IS = getPDBInfoStream();
+    if (!IS)
+      return IS.takeError();
+
+    Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/names");
+    if (!ExpectedNSI)
+      return ExpectedNSI.takeError();
+    uint32_t NameStreamIndex = *ExpectedNSI;
+
+    auto NS =
+        safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
+    if (!NS)
+      return NS.takeError();
+
+    auto N = llvm::make_unique<PDBStringTable>();
+    BinaryStreamReader Reader(**NS);
+    if (auto EC = N->reload(Reader))
+      return std::move(EC);
+    assert(Reader.bytesRemaining() == 0);
+    StringTableStream = std::move(*NS);
+    Strings = std::move(N);
+  }
+  return *Strings;
+}
+
+uint32_t PDBFile::getPointerSize() {
+  auto DbiS = getPDBDbiStream();
+  if (!DbiS)
+    return 0;
+  PDB_Machine Machine = DbiS->getMachineType();
+  if (Machine == PDB_Machine::Amd64)
+    return 8;
+  return 4;
+}
+
+bool PDBFile::hasPDBDbiStream() const {
+  return StreamDBI < getNumStreams() && getStreamByteSize(StreamDBI) > 0;
+}
+
+bool PDBFile::hasPDBGlobalsStream() {
+  auto DbiS = getPDBDbiStream();
+  if (!DbiS) {
+    consumeError(DbiS.takeError());
+    return false;
+  }
+
+  return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBInfoStream() const { return StreamPDB < getNumStreams(); }
+
+bool PDBFile::hasPDBIpiStream() const {
+  if (!hasPDBInfoStream())
+    return false;
+
+  if (StreamIPI >= getNumStreams())
+    return false;
+
+  auto &InfoStream = cantFail(const_cast<PDBFile *>(this)->getPDBInfoStream());
+  return InfoStream.containsIdStream();
+}
+
+bool PDBFile::hasPDBPublicsStream() {
+  auto DbiS = getPDBDbiStream();
+  if (!DbiS) {
+    consumeError(DbiS.takeError());
+    return false;
+  }
+  return DbiS->getPublicSymbolStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBSymbolStream() {
+  auto DbiS = getPDBDbiStream();
+  if (!DbiS)
+    return false;
+  return DbiS->getSymRecordStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
+
+bool PDBFile::hasPDBStringTable() {
+  auto IS = getPDBInfoStream();
+  if (!IS)
+    return false;
+  Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/names");
+  if (!ExpectedNSI) {
+    consumeError(ExpectedNSI.takeError());
+    return false;
+  }
+  assert(*ExpectedNSI < getNumStreams());
+  return true;
+}
+
+/// Wrapper around MappedBlockStream::createIndexedStream() that checks if a
+/// stream with that index actually exists.  If it does not, the return value
+/// will have an MSFError with code msf_error_code::no_stream.  Else, the return
+/// value will contain the stream returned by createIndexedStream().
+Expected<std::unique_ptr<MappedBlockStream>>
+PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout,
+                                   BinaryStreamRef MsfData,
+                                   uint32_t StreamIndex) const {
+  if (StreamIndex >= getNumStreams())
+    return make_error<RawError>(raw_error_code::no_stream);
+  return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex,
+                                                Allocator);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
new file mode 100644
index 0000000..e0ceb74
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -0,0 +1,358 @@
+//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/xxhash.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
+    : Allocator(Allocator), InjectedSourceHashTraits(Strings),
+      InjectedSourceTable(2, InjectedSourceHashTraits) {}
+
+PDBFileBuilder::~PDBFileBuilder() {}
+
+Error PDBFileBuilder::initialize(uint32_t BlockSize) {
+  auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
+  if (!ExpectedMsf)
+    return ExpectedMsf.takeError();
+  Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
+  return Error::success();
+}
+
+MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
+
+InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
+  if (!Info)
+    Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
+  return *Info;
+}
+
+DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
+  if (!Dbi)
+    Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
+  return *Dbi;
+}
+
+TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
+  if (!Tpi)
+    Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
+  return *Tpi;
+}
+
+TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
+  if (!Ipi)
+    Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
+  return *Ipi;
+}
+
+PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
+  return Strings;
+}
+
+GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
+  if (!Gsi)
+    Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
+  return *Gsi;
+}
+
+Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
+                                                       uint32_t Size) {
+  auto ExpectedStream = Msf->addStream(Size);
+  if (ExpectedStream)
+    NamedStreams.set(Name, *ExpectedStream);
+  return ExpectedStream;
+}
+
+Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
+  Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
+  if (!ExpectedIndex)
+    return ExpectedIndex.takeError();
+  assert(NamedStreamData.count(*ExpectedIndex) == 0);
+  NamedStreamData[*ExpectedIndex] = Data;
+  return Error::success();
+}
+
+void PDBFileBuilder::addInjectedSource(StringRef Name,
+                                       std::unique_ptr<MemoryBuffer> Buffer) {
+  // Stream names must be exact matches, since they get looked up in a hash
+  // table and the hash value is dependent on the exact contents of the string.
+  // link.exe lowercases a path and converts / to \, so we must do the same.
+  SmallString<64> VName;
+  sys::path::native(Name.lower(), VName);
+
+  uint32_t NI = getStringTableBuilder().insert(Name);
+  uint32_t VNI = getStringTableBuilder().insert(VName);
+
+  InjectedSourceDescriptor Desc;
+  Desc.Content = std::move(Buffer);
+  Desc.NameIndex = NI;
+  Desc.VNameIndex = VNI;
+  Desc.StreamName = "/src/files/";
+
+  Desc.StreamName += VName;
+
+  InjectedSources.push_back(std::move(Desc));
+}
+
+Error PDBFileBuilder::finalizeMsfLayout() {
+
+  if (Ipi && Ipi->getRecordCount() > 0) {
+    // In theory newer PDBs always have an ID stream, but by saying that we're
+    // only going to *really* have an ID stream if there is at least one ID
+    // record, we leave open the opportunity to test older PDBs such as those
+    // that don't have an ID stream.
+    auto &Info = getInfoBuilder();
+    Info.addFeature(PdbRaw_FeatureSig::VC140);
+  }
+
+  uint32_t StringsLen = Strings.calculateSerializedSize();
+
+  Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
+  if (!SN)
+    return SN.takeError();
+
+  if (Gsi) {
+    if (auto EC = Gsi->finalizeMsfLayout())
+      return EC;
+    if (Dbi) {
+      Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
+      Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
+      Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
+    }
+  }
+  if (Tpi) {
+    if (auto EC = Tpi->finalizeMsfLayout())
+      return EC;
+  }
+  if (Dbi) {
+    if (auto EC = Dbi->finalizeMsfLayout())
+      return EC;
+  }
+  SN = allocateNamedStream("/names", StringsLen);
+  if (!SN)
+    return SN.takeError();
+
+  if (Ipi) {
+    if (auto EC = Ipi->finalizeMsfLayout())
+      return EC;
+  }
+
+  // Do this last, since it relies on the named stream map being complete, and
+  // that can be updated by previous steps in the finalization.
+  if (Info) {
+    if (auto EC = Info->finalizeMsfLayout())
+      return EC;
+  }
+
+  if (!InjectedSources.empty()) {
+    for (const auto &IS : InjectedSources) {
+      JamCRC CRC(0);
+      CRC.update(makeArrayRef(IS.Content->getBufferStart(),
+                              IS.Content->getBufferSize()));
+
+      SrcHeaderBlockEntry Entry;
+      ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
+      Entry.Size = sizeof(SrcHeaderBlockEntry);
+      Entry.FileSize = IS.Content->getBufferSize();
+      Entry.FileNI = IS.NameIndex;
+      Entry.VFileNI = IS.VNameIndex;
+      Entry.ObjNI = 1;
+      Entry.IsVirtual = 0;
+      Entry.Version =
+          static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+      Entry.CRC = CRC.getCRC();
+      StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
+      InjectedSourceTable.set_as(VName, std::move(Entry));
+    }
+
+    uint32_t SrcHeaderBlockSize =
+        sizeof(SrcHeaderBlockHeader) +
+        InjectedSourceTable.calculateSerializedLength();
+    SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
+    if (!SN)
+      return SN.takeError();
+    for (const auto &IS : InjectedSources) {
+      SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
+      if (!SN)
+        return SN.takeError();
+    }
+  }
+
+  // Do this last, since it relies on the named stream map being complete, and
+  // that can be updated by previous steps in the finalization.
+  if (Info) {
+    if (auto EC = Info->finalizeMsfLayout())
+      return EC;
+  }
+
+  return Error::success();
+}
+
+Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
+  uint32_t SN = 0;
+  if (!NamedStreams.get(Name, SN))
+    return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
+  return SN;
+}
+
+void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+                                          const msf::MSFLayout &Layout) {
+  assert(!InjectedSourceTable.empty());
+
+  uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
+  auto Stream = WritableMappedBlockStream::createIndexedStream(
+      Layout, MsfBuffer, SN, Allocator);
+  BinaryStreamWriter Writer(*Stream);
+
+  SrcHeaderBlockHeader Header;
+  ::memset(&Header, 0, sizeof(Header));
+  Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+  Header.Size = Writer.bytesRemaining();
+
+  cantFail(Writer.writeObject(Header));
+  cantFail(InjectedSourceTable.commit(Writer));
+
+  assert(Writer.bytesRemaining() == 0);
+}
+
+void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
+                                           const msf::MSFLayout &Layout) {
+  if (InjectedSourceTable.empty())
+    return;
+
+  commitSrcHeaderBlock(MsfBuffer, Layout);
+
+  for (const auto &IS : InjectedSources) {
+    uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
+
+    auto SourceStream = WritableMappedBlockStream::createIndexedStream(
+        Layout, MsfBuffer, SN, Allocator);
+    BinaryStreamWriter SourceWriter(*SourceStream);
+    assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
+    cantFail(SourceWriter.writeBytes(
+        arrayRefFromStringRef(IS.Content->getBuffer())));
+  }
+}
+
+Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
+  assert(!Filename.empty());
+  if (auto EC = finalizeMsfLayout())
+    return EC;
+
+  MSFLayout Layout;
+  Expected<FileBufferByteStream> ExpectedMsfBuffer =
+      Msf->commit(Filename, Layout);
+  if (!ExpectedMsfBuffer)
+    return ExpectedMsfBuffer.takeError();
+  FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
+
+  auto ExpectedSN = getNamedStreamIndex("/names");
+  if (!ExpectedSN)
+    return ExpectedSN.takeError();
+
+  auto NS = WritableMappedBlockStream::createIndexedStream(
+      Layout, Buffer, *ExpectedSN, Allocator);
+  BinaryStreamWriter NSWriter(*NS);
+  if (auto EC = Strings.commit(NSWriter))
+    return EC;
+
+  for (const auto &NSE : NamedStreamData) {
+    if (NSE.second.empty())
+      continue;
+
+    auto NS = WritableMappedBlockStream::createIndexedStream(
+        Layout, Buffer, NSE.first, Allocator);
+    BinaryStreamWriter NSW(*NS);
+    if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
+      return EC;
+  }
+
+  if (Info) {
+    if (auto EC = Info->commit(Layout, Buffer))
+      return EC;
+  }
+
+  if (Dbi) {
+    if (auto EC = Dbi->commit(Layout, Buffer))
+      return EC;
+  }
+
+  if (Tpi) {
+    if (auto EC = Tpi->commit(Layout, Buffer))
+      return EC;
+  }
+
+  if (Ipi) {
+    if (auto EC = Ipi->commit(Layout, Buffer))
+      return EC;
+  }
+
+  if (Gsi) {
+    if (auto EC = Gsi->commit(Layout, Buffer))
+      return EC;
+  }
+
+  auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
+  assert(!InfoStreamBlocks.empty());
+  uint64_t InfoStreamFileOffset =
+      blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
+  InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
+      Buffer.getBufferStart() + InfoStreamFileOffset);
+
+  commitInjectedSources(Buffer, Layout);
+
+  // Set the build id at the very end, after every other byte of the PDB
+  // has been written.
+  if (Info->hashPDBContentsToGUID()) {
+    // Compute a hash of all sections of the output file.
+    uint64_t Digest =
+        xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
+
+    H->Age = 1;
+
+    memcpy(H->Guid.Guid, &Digest, 8);
+    // xxhash only gives us 8 bytes, so put some fixed data in the other half.
+    memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
+
+    // Put the hash in the Signature field too.
+    H->Signature = static_cast<uint32_t>(Digest);
+
+    // Return GUID to caller.
+    memcpy(Guid, H->Guid.Guid, 16);
+  } else {
+    H->Age = Info->getAge();
+    H->Guid = Info->getGuid();
+    Optional<uint32_t> Sig = Info->getSignature();
+    H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
+  }
+
+  return Buffer.commit();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
new file mode 100644
index 0000000..afeea32
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -0,0 +1,141 @@
+//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }
+uint32_t PDBStringTable::getNameCount() const { return NameCount; }
+uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
+uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
+
+Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
+  if (auto EC = Reader.readObject(Header))
+    return EC;
+
+  if (Header->Signature != PDBStringTableSignature)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Invalid hash table signature");
+  if (Header->HashVersion != 1 && Header->HashVersion != 2)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Unsupported hash version");
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
+  BinaryStreamRef Stream;
+  if (auto EC = Reader.readStreamRef(Stream))
+    return EC;
+
+  if (auto EC = Strings.initialize(Stream)) {
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Invalid hash table byte length"));
+  }
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+const codeview::DebugStringTableSubsectionRef &
+PDBStringTable::getStringTable() const {
+  return Strings;
+}
+
+Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
+  const support::ulittle32_t *HashCount;
+  if (auto EC = Reader.readObject(HashCount))
+    return EC;
+
+  if (auto EC = Reader.readArray(IDs, *HashCount)) {
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Could not read bucket array"));
+  }
+
+  return Error::success();
+}
+
+Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
+  if (auto EC = Reader.readInteger(NameCount))
+    return EC;
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTable::reload(BinaryStreamReader &Reader) {
+
+  BinaryStreamReader SectionReader;
+
+  std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
+  if (auto EC = readHeader(SectionReader))
+    return EC;
+
+  std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
+  if (auto EC = readStrings(SectionReader))
+    return EC;
+
+  // We don't know how long the hash table is until we parse it, so let the
+  // function responsible for doing that figure it out.
+  if (auto EC = readHashTable(Reader))
+    return EC;
+
+  std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
+  if (auto EC = readEpilogue(SectionReader))
+    return EC;
+
+  assert(Reader.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
+  return Strings.getString(ID);
+}
+
+Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
+  uint32_t Hash =
+      (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
+  size_t Count = IDs.size();
+  uint32_t Start = Hash % Count;
+  for (size_t I = 0; I < Count; ++I) {
+    // The hash is just a starting point for the search, but if it
+    // doesn't work we should find the string no matter what, because
+    // we iterate the entire array.
+    uint32_t Index = (Start + I) % Count;
+
+    // If we find 0, it means the item isn't in the hash table.
+    uint32_t ID = IDs[Index];
+    if (ID == 0)
+      return make_error<RawError>(raw_error_code::no_entry);
+    auto ExpectedStr = getStringForID(ID);
+    if (!ExpectedStr)
+      return ExpectedStr.takeError();
+
+    if (*ExpectedStr == Str)
+      return ID;
+  }
+  return make_error<RawError>(raw_error_code::no_entry);
+}
+
+FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
+  return IDs;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
new file mode 100644
index 0000000..d9dcabf
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
@@ -0,0 +1,212 @@
+//===- PDBStringTableBuilder.cpp - PDB String Table -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+
+#include <map>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+using namespace llvm::pdb;
+
+StringTableHashTraits::StringTableHashTraits(PDBStringTableBuilder &Table)
+    : Table(&Table) {}
+
+uint32_t StringTableHashTraits::hashLookupKey(StringRef S) const {
+  return Table->getIdForString(S);
+}
+
+StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const {
+  return Table->getStringForId(Offset);
+}
+
+uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) {
+  return Table->insert(S);
+}
+
+uint32_t PDBStringTableBuilder::insert(StringRef S) {
+  return Strings.insert(S);
+}
+
+uint32_t PDBStringTableBuilder::getIdForString(StringRef S) const {
+  return Strings.getIdForString(S);
+}
+
+StringRef PDBStringTableBuilder::getStringForId(uint32_t Id) const {
+  return Strings.getStringForId(Id);
+}
+
+// This is a precomputed list of Buckets given the specified number of
+// strings.  Matching the reference algorithm exactly is not strictly
+// necessary for correctness, but it helps when comparing LLD's PDBs with
+// Microsoft's PDBs so as to eliminate superfluous differences.
+static std::map<uint32_t, uint32_t> StringsToBuckets = {
+    {1, 2},
+    {2, 4},
+    {4, 7},
+    {6, 11},
+    {9, 17},
+    {13, 26},
+    {20, 40},
+    {31, 61},
+    {46, 92},
+    {70, 139},
+    {105, 209},
+    {157, 314},
+    {236, 472},
+    {355, 709},
+    {532, 1064},
+    {799, 1597},
+    {1198, 2396},
+    {1798, 3595},
+    {2697, 5393},
+    {4045, 8090},
+    {6068, 12136},
+    {9103, 18205},
+    {13654, 27308},
+    {20482, 40963},
+    {30723, 61445},
+    {46084, 92168},
+    {69127, 138253},
+    {103690, 207380},
+    {155536, 311071},
+    {233304, 466607},
+    {349956, 699911},
+    {524934, 1049867},
+    {787401, 1574801},
+    {1181101, 2362202},
+    {1771652, 3543304},
+    {2657479, 5314957},
+    {3986218, 7972436},
+    {5979328, 11958655},
+    {8968992, 17937983},
+    {13453488, 26906975},
+    {20180232, 40360463},
+    {30270348, 60540695},
+    {45405522, 90811043},
+    {68108283, 136216565},
+    {102162424, 204324848},
+    {153243637, 306487273},
+    {229865455, 459730910},
+    {344798183, 689596366},
+    {517197275, 1034394550},
+    {775795913, 1551591826}};
+
+static uint32_t computeBucketCount(uint32_t NumStrings) {
+  auto Entry = StringsToBuckets.lower_bound(NumStrings);
+  assert(Entry != StringsToBuckets.end());
+  return Entry->second;
+}
+
+uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
+  uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
+  Size += sizeof(uint32_t) * computeBucketCount(Strings.size());
+
+  return Size;
+}
+
+uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
+  uint32_t Size = 0;
+  Size += sizeof(PDBStringTableHeader);
+  Size += Strings.calculateSerializedSize();
+  Size += calculateHashTableSize();
+  Size += sizeof(uint32_t); // The /names stream ends with the string count.
+  return Size;
+}
+
+void PDBStringTableBuilder::setStrings(
+    const codeview::DebugStringTableSubsection &Strings) {
+  this->Strings = Strings;
+}
+
+Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
+  // Write a header
+  PDBStringTableHeader H;
+  H.Signature = PDBStringTableSignature;
+  H.HashVersion = 1;
+  H.ByteSize = Strings.calculateSerializedSize();
+  if (auto EC = Writer.writeObject(H))
+    return EC;
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
+  if (auto EC = Strings.commit(Writer))
+    return EC;
+
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
+  // Write a hash table.
+  uint32_t BucketCount = computeBucketCount(Strings.size());
+  if (auto EC = Writer.writeInteger(BucketCount))
+    return EC;
+  std::vector<ulittle32_t> Buckets(BucketCount);
+
+  for (auto &Pair : Strings) {
+    StringRef S = Pair.getKey();
+    uint32_t Offset = Pair.getValue();
+    uint32_t Hash = hashStringV1(S);
+
+    for (uint32_t I = 0; I != BucketCount; ++I) {
+      uint32_t Slot = (Hash + I) % BucketCount;
+      if (Buckets[Slot] != 0)
+        continue;
+      Buckets[Slot] = Offset;
+      break;
+    }
+  }
+
+  if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
+    return EC;
+
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
+  if (auto EC = Writer.writeInteger<uint32_t>(Strings.size()))
+    return EC;
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
+
+Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
+  BinaryStreamWriter SectionWriter;
+
+  std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
+  if (auto EC = writeHeader(SectionWriter))
+    return EC;
+
+  std::tie(SectionWriter, Writer) =
+      Writer.split(Strings.calculateSerializedSize());
+  if (auto EC = writeStrings(SectionWriter))
+    return EC;
+
+  std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
+  if (auto EC = writeHashTable(SectionWriter))
+    return EC;
+
+  std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
+  if (auto EC = writeEpilogue(SectionWriter))
+    return EC;
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp
new file mode 100644
index 0000000..f6466eb
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp
@@ -0,0 +1,102 @@
+//===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The data structures defined in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+//  - ppdb1->m_fMinimalDbgInfo seems to be always true.
+//  - SMALLBUCKETS macro is defined.
+//
+// The reference doesn't compile, so I learned just by reading code.
+// It's not guaranteed to be correct.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream)
+    : Stream(std::move(Stream)) {}
+
+PublicsStream::~PublicsStream() = default;
+
+uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
+uint16_t PublicsStream::getThunkTableSection() const {
+  return Header->ISectThunkTable;
+}
+uint32_t PublicsStream::getThunkTableOffset() const {
+  return Header->OffThunkTable;
+}
+
+// Publics stream contains fixed-size headers and a serialized hash table.
+// This implementation is not complete yet. It reads till the end of the
+// stream so that we verify the stream is at least not corrupted. However,
+// we skip over the hash table which we believe contains information about
+// public symbols.
+Error PublicsStream::reload() {
+  BinaryStreamReader Reader(*Stream);
+
+  // Check stream size.
+  if (Reader.bytesRemaining() <
+      sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Publics Stream does not contain a header.");
+
+  // Read PSGSIHDR struct.
+  if (Reader.readObject(Header))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Publics Stream does not contain a header.");
+
+  // Read the hash table.
+  if (auto E = PublicsTable.read(Reader))
+    return E;
+
+  // Something called "address map" follows.
+  uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
+  if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Could not read an address map."));
+
+  // Something called "thunk map" follows.
+  if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
+    return joinErrors(std::move(EC),
+                      make_error<RawError>(raw_error_code::corrupt_file,
+                                           "Could not read a thunk map."));
+
+  // Something called "section map" follows.
+  if (Reader.bytesRemaining() > 0) {
+    if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
+      return joinErrors(std::move(EC),
+                        make_error<RawError>(raw_error_code::corrupt_file,
+                                             "Could not read a section map."));
+  }
+
+  if (Reader.bytesRemaining() > 0)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupted publics stream.");
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/RawError.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/RawError.cpp
new file mode 100644
index 0000000..dec9797
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/RawError.cpp
@@ -0,0 +1,51 @@
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class RawErrorCategory : public std::error_category {
+public:
+  const char *name() const noexcept override { return "llvm.pdb.raw"; }
+  std::string message(int Condition) const override {
+    switch (static_cast<raw_error_code>(Condition)) {
+    case raw_error_code::unspecified:
+      return "An unknown error has occurred.";
+    case raw_error_code::feature_unsupported:
+      return "The feature is unsupported by the implementation.";
+    case raw_error_code::invalid_format:
+      return "The record is in an unexpected format.";
+    case raw_error_code::corrupt_file:
+      return "The PDB file is corrupt.";
+    case raw_error_code::insufficient_buffer:
+      return "The buffer is not large enough to read the requested number of "
+             "bytes.";
+    case raw_error_code::no_stream:
+      return "The specified stream could not be loaded.";
+    case raw_error_code::index_out_of_bounds:
+      return "The specified item does not exist in the array.";
+    case raw_error_code::invalid_block_address:
+      return "The specified block address is not valid.";
+    case raw_error_code::duplicate_entry:
+      return "The entry already exists.";
+    case raw_error_code::no_entry:
+      return "The entry does not exist.";
+    case raw_error_code::not_writable:
+      return "The PDB does not support writing.";
+    case raw_error_code::stream_too_long:
+      return "The stream was longer than expected.";
+    case raw_error_code::invalid_tpi_hash:
+      return "The Type record has an invalid hash value.";
+    }
+    llvm_unreachable("Unrecognized raw_error_code");
+  }
+};
+
+static llvm::ManagedStatic<RawErrorCategory> RawCategory;
+const std::error_category &llvm::pdb::RawErrCategory() { return *RawCategory; }
+
+char RawError::ID;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
new file mode 100644
index 0000000..5cdd628
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -0,0 +1,299 @@
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.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/NativeTypeArray.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.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::codeview;
+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::None, PDB_BuiltinType::None, 0},
+    {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
+    {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
+    {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
+    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
+    {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
+    {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
+    {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
+    {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
+    {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
+    {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
+    {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
+    {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
+    {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
+    {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
+    {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
+    {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
+    {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
+    {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<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
+  return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
+  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, std::move(Kinds)));
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
+  return std::unique_ptr<IPDBEnumSymbols>(
+      new NativeEnumGlobals(Session, {Kind}));
+}
+
+SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
+                                         ModifierOptions Mods) {
+  if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
+    return createSymbol<NativeTypePointer>(Index);
+
+  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;
+  return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
+}
+
+SymIndexId
+SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
+                                         codeview::CVType CVT) {
+  ModifierRecord Record;
+  if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
+    consumeError(std::move(EC));
+    return 0;
+  }
+
+  if (Record.ModifiedType.isSimple())
+    return createSimpleType(Record.ModifiedType, Record.Modifiers);
+
+  // Make sure we create and cache a record for the unmodified type.
+  SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
+  NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
+
+  switch (UnmodifiedNRS.getSymTag()) {
+  case PDB_SymType::Enum:
+    return createSymbol<NativeTypeEnum>(
+        static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
+  case PDB_SymType::UDT:
+    return createSymbol<NativeTypeUDT>(
+        static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
+  default:
+    // No other types can be modified.  (LF_POINTER, for example, records
+    // its modifiers a different way.
+    assert(false && "Invalid LF_MODIFIER record");
+    break;
+  }
+  return 0;
+}
+
+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()) {
+    SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
+    assert(TypeIndexToSymbolId.count(Index) == 0);
+    TypeIndexToSymbolId[Index] = Result;
+    return Result;
+  }
+
+  // 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();
+  codeview::CVType CVT = Types.getType(Index);
+
+  if (isUdtForwardRef(CVT)) {
+    Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
+
+    if (!EFD)
+      consumeError(EFD.takeError());
+    else if (*EFD != Index) {
+      assert(!isUdtForwardRef(Types.getType(*EFD)));
+      SymIndexId Result = findSymbolByTypeIndex(*EFD);
+      // Record a mapping from ForwardRef -> SymIndex of complete type so that
+      // we'll take the fast path next time.
+      assert(TypeIndexToSymbolId.count(Index) == 0);
+      TypeIndexToSymbolId[Index] = Result;
+      return Result;
+    }
+  }
+
+  // At this point if we still have a forward ref udt it means the full decl was
+  // not in the PDB.  We just have to deal with it and use the forward ref.
+  SymIndexId Id = 0;
+  switch (CVT.kind()) {
+  case codeview::LF_ENUM:
+    Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
+    break;
+  case codeview::LF_ARRAY:
+    Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
+                                                           std::move(CVT));
+    break;
+  case codeview::LF_CLASS:
+  case codeview::LF_STRUCTURE:
+  case codeview::LF_INTERFACE:
+    Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
+    break;
+  case codeview::LF_UNION:
+    Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
+    break;
+  case codeview::LF_POINTER:
+    Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
+                                                               std::move(CVT));
+    break;
+  case codeview::LF_MODIFIER:
+    Id = createSymbolForModifiedType(Index, std::move(CVT));
+    break;
+  case codeview::LF_PROCEDURE:
+    Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
+        Index, std::move(CVT));
+    break;
+  case codeview::LF_MFUNCTION:
+    Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
+        Index, std::move(CVT));
+    break;
+  case codeview::LF_VTSHAPE:
+    Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
+        Index, std::move(CVT));
+    break;
+  default:
+    Id = createSymbolPlaceholder();
+    break;
+  }
+  if (Id != 0) {
+    assert(TypeIndexToSymbolId.count(Index) == 0);
+    TypeIndexToSymbolId[Index] = Id;
+  }
+  return Id;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+  assert(SymbolId < Cache.size());
+
+  // Id 0 is reserved.
+  if (SymbolId == 0 || SymbolId >= Cache.size())
+    return nullptr;
+
+  // Make sure to handle the case where we've inserted a placeholder symbol
+  // for types we don't yet suppport.
+  NativeRawSymbol *NRS = Cache[SymbolId].get();
+  if (!NRS)
+    return nullptr;
+
+  return PDBSymbol::create(Session, *NRS);
+}
+
+NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
+  return *Cache[SymbolId];
+}
+
+uint32_t SymbolCache::getNumCompilands() const {
+  if (!Dbi)
+    return 0;
+
+  return Dbi->modules().getModuleCount();
+}
+
+SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
+  auto Iter = GlobalOffsetToSymbolId.find(Offset);
+  if (Iter != GlobalOffsetToSymbolId.end())
+    return Iter->second;
+
+  SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+  CVSymbol CVS = SS.readRecord(Offset);
+  SymIndexId Id = 0;
+  switch (CVS.kind()) {
+  case SymbolKind::S_UDT: {
+    UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
+    Id = createSymbol<NativeTypeTypedef>(std::move(US));
+    break;
+  }
+  default:
+    Id = createSymbolPlaceholder();
+    break;
+  }
+  if (Id != 0) {
+    assert(GlobalOffsetToSymbolId.count(Offset) == 0);
+    GlobalOffsetToSymbolId[Offset] = Id;
+  }
+
+  return Id;
+}
+
+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]);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp
new file mode 100644
index 0000000..2d8d04c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp
@@ -0,0 +1,46 @@
+//===- SymbolStream.cpp - PDB Symbol Stream Access ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream)
+    : Stream(std::move(Stream)) {}
+
+SymbolStream::~SymbolStream() {}
+
+Error SymbolStream::reload() {
+  BinaryStreamReader Reader(*Stream);
+
+  if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
+    return EC;
+
+  return Error::success();
+}
+
+iterator_range<codeview::CVSymbolArray::Iterator>
+SymbolStream::getSymbols(bool *HadError) const {
+  return llvm::make_range(SymbolRecords.begin(HadError), SymbolRecords.end());
+}
+
+Error SymbolStream::commit() { return Error::success(); }
+
+codeview::CVSymbol SymbolStream::readRecord(uint32_t Offset) const {
+  return *SymbolRecords.at(Offset);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
new file mode 100644
index 0000000..1870882
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -0,0 +1,132 @@
+//===- TpiHashing.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/Support/JamCRC.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+// Corresponds to `fUDTAnon`.
+static bool isAnonymous(StringRef Name) {
+  return Name == "<unnamed-tag>" || Name == "__unnamed" ||
+         Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
+}
+
+// Computes the hash for a user-defined type record. This could be a struct,
+// class, union, or enum.
+static uint32_t getHashForUdt(const TagRecord &Rec,
+                              ArrayRef<uint8_t> FullRecord) {
+  ClassOptions Opts = Rec.getOptions();
+  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+  bool Scoped = bool(Opts & ClassOptions::Scoped);
+  bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName);
+  bool IsAnon = HasUniqueName && isAnonymous(Rec.getName());
+
+  if (!ForwardRef && !Scoped && !IsAnon)
+    return hashStringV1(Rec.getName());
+  if (!ForwardRef && HasUniqueName && !IsAnon)
+    return hashStringV1(Rec.getUniqueName());
+  return hashBufferV8(FullRecord);
+}
+
+template <typename T>
+static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
+  T Deserialized;
+  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+                                               Deserialized))
+    return std::move(E);
+  return getHashForUdt(Deserialized, Rec.data());
+}
+
+template <typename T>
+static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
+  T Deserialized;
+  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+                                               Deserialized))
+    return std::move(E);
+
+  ClassOptions Opts = Deserialized.getOptions();
+
+  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+
+  uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
+
+  // If we don't have a forward ref we can't compute the hash of it from the
+  // full record because it requires hashing the entire buffer.
+  if (!ForwardRef)
+    return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
+
+  bool Scoped = bool(Opts & ClassOptions::Scoped);
+
+  StringRef NameToHash =
+      Scoped ? Deserialized.getUniqueName() : Deserialized.getName();
+  uint32_t FullHash = hashStringV1(NameToHash);
+  return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
+}
+
+template <typename T>
+static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
+  T Deserialized;
+  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+                                               Deserialized))
+    return std::move(E);
+  char Buf[4];
+  support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
+  return hashStringV1(StringRef(Buf, 4));
+}
+
+Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
+  switch (Type.kind()) {
+  case LF_CLASS:
+  case LF_STRUCTURE:
+  case LF_INTERFACE:
+    return getTagRecordHashForUdt<ClassRecord>(Type);
+  case LF_UNION:
+    return getTagRecordHashForUdt<UnionRecord>(Type);
+  case LF_ENUM:
+    return getTagRecordHashForUdt<EnumRecord>(Type);
+  default:
+    assert(false && "Type is not a tag record!");
+  }
+  return make_error<StringError>("Invalid record type",
+                                 inconvertibleErrorCode());
+}
+
+Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
+  switch (Rec.kind()) {
+  case LF_CLASS:
+  case LF_STRUCTURE:
+  case LF_INTERFACE:
+    return getHashForUdt<ClassRecord>(Rec);
+  case LF_UNION:
+    return getHashForUdt<UnionRecord>(Rec);
+  case LF_ENUM:
+    return getHashForUdt<EnumRecord>(Rec);
+
+  case LF_UDT_SRC_LINE:
+    return getSourceLineHash<UdtSourceLineRecord>(Rec);
+  case LF_UDT_MOD_SRC_LINE:
+    return getSourceLineHash<UdtModSourceLineRecord>(Rec);
+
+  default:
+    break;
+  }
+
+  // Run CRC32 over the bytes. This corresponds to `hashBufv8`.
+  JamCRC JC(/*Init=*/0U);
+  ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()),
+                       Rec.data().size());
+  JC.update(Bytes);
+  return JC.getCRC();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp
new file mode 100644
index 0000000..f234d446
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -0,0 +1,248 @@
+//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::support;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
+    : Pdb(File), Stream(std::move(Stream)) {}
+
+TpiStream::~TpiStream() = default;
+
+Error TpiStream::reload() {
+  BinaryStreamReader Reader(*Stream);
+
+  if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "TPI Stream does not contain a header.");
+
+  if (Reader.readObject(Header))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "TPI Stream does not contain a header.");
+
+  if (Header->Version != PdbTpiV80)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Unsupported TPI Version.");
+
+  if (Header->HeaderSize != sizeof(TpiStreamHeader))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupt TPI Header size.");
+
+  if (Header->HashKeySize != sizeof(ulittle32_t))
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "TPI Stream expected 4 byte hash key size.");
+
+  if (Header->NumHashBuckets < MinTpiHashBuckets ||
+      Header->NumHashBuckets > MaxTpiHashBuckets)
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "TPI Stream Invalid number of hash buckets.");
+
+  // The actual type records themselves come from this stream
+  if (auto EC =
+          Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
+    return EC;
+
+  BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
+  if (auto EC =
+          RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
+    return EC;
+
+  // Hash indices, hash values, etc come from the hash stream.
+  if (Header->HashStreamIndex != kInvalidStreamIndex) {
+    if (Header->HashStreamIndex >= Pdb.getNumStreams())
+      return make_error<RawError>(raw_error_code::corrupt_file,
+                                  "Invalid TPI hash stream index.");
+
+    auto HS = MappedBlockStream::createIndexedStream(
+        Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex,
+        Pdb.getAllocator());
+    BinaryStreamReader HSR(*HS);
+
+    // There should be a hash value for every type record, or no hashes at all.
+    uint32_t NumHashValues =
+        Header->HashValueBuffer.Length / sizeof(ulittle32_t);
+    if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
+      return make_error<RawError>(
+          raw_error_code::corrupt_file,
+          "TPI hash count does not match with the number of type records.");
+    HSR.setOffset(Header->HashValueBuffer.Off);
+    if (auto EC = HSR.readArray(HashValues, NumHashValues))
+      return EC;
+
+    HSR.setOffset(Header->IndexOffsetBuffer.Off);
+    uint32_t NumTypeIndexOffsets =
+        Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
+    if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
+      return EC;
+
+    if (Header->HashAdjBuffer.Length > 0) {
+      HSR.setOffset(Header->HashAdjBuffer.Off);
+      if (auto EC = HashAdjusters.load(HSR))
+        return EC;
+    }
+
+    HashStream = std::move(HS);
+  }
+
+  Types = llvm::make_unique<LazyRandomTypeCollection>(
+      TypeRecords, getNumTypeRecords(), getTypeIndexOffsets());
+  return Error::success();
+}
+
+PdbRaw_TpiVer TpiStream::getTpiVersion() const {
+  uint32_t Value = Header->Version;
+  return static_cast<PdbRaw_TpiVer>(Value);
+}
+
+uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
+
+uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
+
+uint32_t TpiStream::getNumTypeRecords() const {
+  return TypeIndexEnd() - TypeIndexBegin();
+}
+
+uint16_t TpiStream::getTypeHashStreamIndex() const {
+  return Header->HashStreamIndex;
+}
+
+uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
+  return Header->HashAuxStreamIndex;
+}
+
+uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
+uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
+
+void TpiStream::buildHashMap() {
+  if (!HashMap.empty())
+    return;
+  if (HashValues.empty())
+    return;
+
+  HashMap.resize(Header->NumHashBuckets);
+
+  TypeIndex TIB{Header->TypeIndexBegin};
+  TypeIndex TIE{Header->TypeIndexEnd};
+  while (TIB < TIE) {
+    uint32_t HV = HashValues[TIB.toArrayIndex()];
+    HashMap[HV].push_back(TIB++);
+  }
+}
+
+std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const {
+  if (!supportsTypeLookup())
+    const_cast<TpiStream*>(this)->buildHashMap();
+
+  uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets;
+  if (Bucket > HashMap.size())
+    return {};
+
+  std::vector<TypeIndex> Result;
+  for (TypeIndex TI : HashMap[Bucket]) {
+    std::string ThisName = computeTypeName(*Types, TI);
+    if (ThisName == Name)
+      Result.push_back(TI);
+  }
+  return Result;
+}
+
+bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
+
+Expected<TypeIndex>
+TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
+  if (!supportsTypeLookup())
+    const_cast<TpiStream*>(this)->buildHashMap();
+
+  CVType F = Types->getType(ForwardRefTI);
+  if (!isUdtForwardRef(F))
+    return ForwardRefTI;
+
+  Expected<TagRecordHash> ForwardTRH = hashTagRecord(F);
+  if (!ForwardTRH)
+    return ForwardTRH.takeError();
+
+  uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets;
+
+  for (TypeIndex TI : HashMap[BucketIdx]) {
+    CVType CVT = Types->getType(TI);
+    if (CVT.kind() != F.kind())
+      continue;
+
+    Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);
+    if (!FullTRH)
+      return FullTRH.takeError();
+    if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)
+      continue;
+    TagRecord &ForwardTR = ForwardTRH->getRecord();
+    TagRecord &FullTR = FullTRH->getRecord();
+
+    if (!ForwardTR.hasUniqueName()) {
+      if (ForwardTR.getName() == FullTR.getName())
+        return TI;
+      continue;
+    }
+
+    if (!FullTR.hasUniqueName())
+      continue;
+    if (ForwardTR.getUniqueName() == FullTR.getUniqueName())
+      return TI;
+  }
+  return ForwardRefTI;
+}
+
+codeview::CVType TpiStream::getType(codeview::TypeIndex Index) {
+  assert(!Index.isSimple());
+  return Types->getType(Index);
+}
+
+BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
+  return TypeRecordsSubstream;
+}
+
+FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {
+  return HashValues;
+}
+
+FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const {
+  return TypeIndexOffsets;
+}
+
+HashTable<support::ulittle32_t> &TpiStream::getHashAdjusters() {
+  return HashAdjusters;
+}
+
+CVTypeRange TpiStream::types(bool *HadError) const {
+  return make_range(TypeRecords.begin(HadError), TypeRecords.end());
+}
+
+Error TpiStream::commit() { return Error::success(); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
new file mode 100644
index 0000000..8dd3001
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
@@ -0,0 +1,176 @@
+//===- TpiStreamBuilder.cpp -   -------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
+    : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
+}
+
+TpiStreamBuilder::~TpiStreamBuilder() = default;
+
+void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
+  VerHeader = Version;
+}
+
+void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
+                                     Optional<uint32_t> Hash) {
+  // If we just crossed an 8KB threshold, add a type index offset.
+  size_t NewSize = TypeRecordBytes + Record.size();
+  constexpr size_t EightKB = 8 * 1024;
+  if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) {
+    TypeIndexOffsets.push_back(
+        {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex +
+                             TypeRecords.size()),
+         ulittle32_t(TypeRecordBytes)});
+  }
+  TypeRecordBytes = NewSize;
+
+  TypeRecords.push_back(Record);
+  if (Hash)
+    TypeHashes.push_back(*Hash);
+}
+
+Error TpiStreamBuilder::finalize() {
+  if (Header)
+    return Error::success();
+
+  TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
+
+  uint32_t Count = TypeRecords.size();
+
+  H->Version = VerHeader;
+  H->HeaderSize = sizeof(TpiStreamHeader);
+  H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
+  H->TypeIndexEnd = H->TypeIndexBegin + Count;
+  H->TypeRecordBytes = TypeRecordBytes;
+
+  H->HashStreamIndex = HashStreamIndex;
+  H->HashAuxStreamIndex = kInvalidStreamIndex;
+  H->HashKeySize = sizeof(ulittle32_t);
+  H->NumHashBuckets = MinTpiHashBuckets;
+
+  // Recall that hash values go into a completely different stream identified by
+  // the `HashStreamIndex` field of the `TpiStreamHeader`.  Therefore, the data
+  // begins at offset 0 of this independent stream.
+  H->HashValueBuffer.Off = 0;
+  H->HashValueBuffer.Length = calculateHashBufferSize();
+
+  // We never write any adjustments into our PDBs, so this is usually some
+  // offset with zero length.
+  H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length;
+  H->HashAdjBuffer.Length = 0;
+
+  H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length;
+  H->IndexOffsetBuffer.Length = calculateIndexOffsetSize();
+
+  Header = H;
+  return Error::success();
+}
+
+uint32_t TpiStreamBuilder::calculateSerializedLength() {
+  return sizeof(TpiStreamHeader) + TypeRecordBytes;
+}
+
+uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
+  assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) &&
+         "either all or no type records should have hashes");
+  return TypeHashes.size() * sizeof(ulittle32_t);
+}
+
+uint32_t TpiStreamBuilder::calculateIndexOffsetSize() const {
+  return TypeIndexOffsets.size() * sizeof(codeview::TypeIndexOffset);
+}
+
+Error TpiStreamBuilder::finalizeMsfLayout() {
+  uint32_t Length = calculateSerializedLength();
+  if (auto EC = Msf.setStreamSize(Idx, Length))
+    return EC;
+
+  uint32_t HashStreamSize =
+      calculateHashBufferSize() + calculateIndexOffsetSize();
+
+  if (HashStreamSize == 0)
+    return Error::success();
+
+  auto ExpectedIndex = Msf.addStream(HashStreamSize);
+  if (!ExpectedIndex)
+    return ExpectedIndex.takeError();
+  HashStreamIndex = *ExpectedIndex;
+  if (!TypeHashes.empty()) {
+    ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
+    MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
+    for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
+      HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets;
+    }
+    ArrayRef<uint8_t> Bytes(
+        reinterpret_cast<const uint8_t *>(HashBuffer.data()),
+        calculateHashBufferSize());
+    HashValueStream =
+        llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little);
+  }
+  return Error::success();
+}
+
+Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
+                               WritableBinaryStreamRef Buffer) {
+  if (auto EC = finalize())
+    return EC;
+
+  auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
+                                                              Idx, Allocator);
+
+  BinaryStreamWriter Writer(*InfoS);
+  if (auto EC = Writer.writeObject(*Header))
+    return EC;
+
+  for (auto Rec : TypeRecords)
+    if (auto EC = Writer.writeBytes(Rec))
+      return EC;
+
+  if (HashStreamIndex != kInvalidStreamIndex) {
+    auto HVS = WritableMappedBlockStream::createIndexedStream(
+        Layout, Buffer, HashStreamIndex, Allocator);
+    BinaryStreamWriter HW(*HVS);
+    if (HashValueStream) {
+      if (auto EC = HW.writeStreamRef(*HashValueStream))
+        return EC;
+    }
+
+    for (auto &IndexOffset : TypeIndexOffsets) {
+      if (auto EC = HW.writeObject(IndexOffset))
+        return EC;
+    }
+  }
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDB.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDB.cpp
new file mode 100644
index 0000000..fc1ad8b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDB.cpp
@@ -0,0 +1,55 @@
+//===- PDB.cpp - base header file for creating a PDB reader ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/GenericError.h"
+#if LLVM_ENABLE_DIA_SDK
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#endif
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+                                std::unique_ptr<IPDBSession> &Session) {
+  // Create the correct concrete instance type based on the value of Type.
+  if (Type == PDB_ReaderType::Native) {
+    ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
+        MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+                                     /*RequiresNullTerminator=*/false);
+    if (!ErrorOrBuffer)
+      return errorCodeToError(ErrorOrBuffer.getError());
+
+    return NativeSession::createFromPdb(std::move(*ErrorOrBuffer), Session);
+  }
+
+#if LLVM_ENABLE_DIA_SDK
+  return DIASession::createFromPdb(Path, Session);
+#else
+  return make_error<PDBError>(pdb_error_code::dia_sdk_not_present);
+#endif
+}
+
+Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+                                std::unique_ptr<IPDBSession> &Session) {
+  // Create the correct concrete instance type based on the value of Type.
+  if (Type == PDB_ReaderType::Native)
+    return NativeSession::createFromExe(Path, Session);
+
+#if LLVM_ENABLE_DIA_SDK
+  return DIASession::createFromExe(Path, Session);
+#else
+  return make_error<PDBError>(pdb_error_code::dia_sdk_not_present);
+#endif
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBContext.cpp
new file mode 100644
index 0000000..df0feac
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -0,0 +1,119 @@
+//===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===/
+
+#include "llvm/DebugInfo/PDB/PDBContext.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Object/COFF.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::pdb;
+
+PDBContext::PDBContext(const COFFObjectFile &Object,
+                       std::unique_ptr<IPDBSession> PDBSession)
+    : DIContext(CK_PDB), Session(std::move(PDBSession)) {
+  ErrorOr<uint64_t> ImageBase = Object.getImageBase();
+  if (ImageBase)
+    Session->setLoadAddress(ImageBase.get());
+}
+
+void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
+
+DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
+                                             DILineInfoSpecifier Specifier) {
+  DILineInfo Result;
+  Result.FunctionName = getFunctionName(Address, Specifier.FNKind);
+
+  uint32_t Length = 1;
+  std::unique_ptr<PDBSymbol> Symbol =
+      Session->findSymbolByAddress(Address, PDB_SymType::None);
+  if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
+    Length = Func->getLength();
+  } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
+    Length = Data->getLength();
+  }
+
+  // If we couldn't find a symbol, then just assume 1 byte, so that we get
+  // only the line number of the first instruction.
+  auto LineNumbers = Session->findLineNumbersByAddress(Address, Length);
+  if (!LineNumbers || LineNumbers->getChildCount() == 0)
+    return Result;
+
+  auto LineInfo = LineNumbers->getNext();
+  assert(LineInfo);
+  auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId());
+
+  if (SourceFile &&
+      Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
+    Result.FileName = SourceFile->getFileName();
+  Result.Column = LineInfo->getColumnNumber();
+  Result.Line = LineInfo->getLineNumber();
+  return Result;
+}
+
+DILineInfoTable
+PDBContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+                                       DILineInfoSpecifier Specifier) {
+  if (Size == 0)
+    return DILineInfoTable();
+
+  DILineInfoTable Table;
+  auto LineNumbers = Session->findLineNumbersByAddress(Address, Size);
+  if (!LineNumbers || LineNumbers->getChildCount() == 0)
+    return Table;
+
+  while (auto LineInfo = LineNumbers->getNext()) {
+    DILineInfo LineEntry =
+        getLineInfoForAddress(LineInfo->getVirtualAddress(), Specifier);
+    Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
+  }
+  return Table;
+}
+
+DIInliningInfo
+PDBContext::getInliningInfoForAddress(uint64_t Address,
+                                      DILineInfoSpecifier Specifier) {
+  DIInliningInfo InlineInfo;
+  DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
+  InlineInfo.addFrame(Frame);
+  return InlineInfo;
+}
+
+std::string PDBContext::getFunctionName(uint64_t Address,
+                                        DINameKind NameKind) const {
+  if (NameKind == DINameKind::None)
+    return std::string();
+
+  std::unique_ptr<PDBSymbol> FuncSymbol =
+      Session->findSymbolByAddress(Address, PDB_SymType::Function);
+  auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get());
+
+  if (NameKind == DINameKind::LinkageName) {
+    // It is not possible to get the mangled linkage name through a
+    // PDBSymbolFunc.  For that we have to specifically request a
+    // PDBSymbolPublicSymbol.
+    auto PublicSym =
+        Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
+    if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) {
+      // If we also have a function symbol, prefer the use of public symbol name
+      // only if it refers to the same address. The public symbol uses the
+      // linkage name while the function does not.
+      if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress())
+        return PS->getName();
+    }
+  }
+
+  return Func ? Func->getName() : std::string();
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
new file mode 100644
index 0000000..0d8af23
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
@@ -0,0 +1,366 @@
+//===- PDBExtras.cpp - helper functions and classes for PDBs --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+#define CASE_OUTPUT_ENUM_CLASS_STR(Class, Value, Str, Stream)                  \
+  case Class::Value:                                                           \
+    Stream << Str;                                                             \
+    break;
+
+#define CASE_OUTPUT_ENUM_CLASS_NAME(Class, Value, Stream)                      \
+  CASE_OUTPUT_ENUM_CLASS_STR(Class, Value, #Value, Stream)
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_VariantType &Type) {
+  switch (Type) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Bool, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Single, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Double, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int8, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int16, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int32, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int64, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt8, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt16, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt32, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt64, OS)
+    default:
+      OS << "Unknown";
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_BuiltinType &Type) {
+  switch (Type) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, None, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Void, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, WCharT, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Int, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, UInt, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Float, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, BCD, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Bool, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Long, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, ULong, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Currency, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Date, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Variant, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Complex, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Bitfield, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, BSTR, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, HResult, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char16, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char32, OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_CallingConv &Conv) {
+  OS << "__";
+  switch (Conv) {
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearC      , "cdecl", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarC       , "cdecl", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearPascal , "pascal", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarPascal  , "pascal", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearFast   , "fastcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarFast    , "fastcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearStdCall, "stdcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarStdCall , "stdcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearSysCall, "syscall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarSysCall , "syscall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, ThisCall   , "thiscall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, MipsCall   , "mipscall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Generic    , "genericcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, AlphaCall  , "alphacall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, PpcCall    , "ppccall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, SHCall     , "superhcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, ArmCall    , "armcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, AM33Call   , "am33call", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, TriCall    , "tricall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, SH5Call    , "sh5call", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, M32RCall   , "m32rcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, ClrCall    , "clrcall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Inline     , "inlinecall", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearVector , "vectorcall", OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_DataKind &Data) {
+  switch (Data) {
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Unknown, "unknown", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Local, "local", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, StaticLocal, "static local", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Param, "param", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, ObjectPtr, "this ptr", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, FileStatic, "static global", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Global, "global", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Member, "member", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, StaticMember, "static member", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Constant, "const", OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const codeview::RegisterId &Reg) {
+  switch (Reg) {
+#define CV_REGISTER(name, val) case codeview::RegisterId::name: OS << #name; return OS;
+#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
+#undef CV_REGISTER
+  }
+  OS << static_cast<int>(Reg);
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_LocType &Loc) {
+  switch (Loc) {
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Static, "static", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, TLS, "tls", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, RegRel, "regrel", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, ThisRel, "thisrel", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Enregistered, "register", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, BitField, "bitfield", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Slot, "slot", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, IlRel, "IL rel", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, MetaData, "metadata", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Constant, "constant", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, RegRelAliasIndir,
+                               "regrelaliasindir", OS)
+  default:
+    OS << "Unknown";
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const codeview::ThunkOrdinal &Thunk) {
+  switch (Thunk) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, BranchIsland, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, Pcode, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, Standard, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, ThisAdjustor, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, TrampIncremental, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, UnknownLoad, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(codeview::ThunkOrdinal, Vcall, OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_Checksum &Checksum) {
+  switch (Checksum) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, None, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, MD5, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, SHA1, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, SHA256, OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_Lang &Lang) {
+  switch (Lang) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, C, OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_Lang, Cpp, "C++", OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Fortran, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Masm, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Pascal, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Basic, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cobol, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Link, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cvtres, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cvtpgd, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, CSharp, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, VB, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, ILAsm, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Java, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, JScript, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, MSIL, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, HLSL, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, D, OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_SymType &Tag) {
+  switch (Tag) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Exe, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Compiland, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CompilandDetails, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CompilandEnv, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Function, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Block, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Data, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Annotation, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Label, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, PublicSymbol, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, UDT, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Enum, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FunctionSig, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, PointerType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, ArrayType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BuiltinType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Typedef, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BaseClass, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Friend, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FunctionArg, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FuncDebugStart, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FuncDebugEnd, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, UsingNamespace, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VTableShape, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VTable, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Custom, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Thunk, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CustomType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, ManagedType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Dimension, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CallSite, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, InlineSite, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BaseInterface, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VectorType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, MatrixType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, HLSLType, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Caller, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Callee, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Export, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, HeapAllocationSite, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CoffGroup, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Inlinee, OS)
+  default:
+    OS << "Unknown SymTag " << uint32_t(Tag);
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_MemberAccess &Access) {
+  switch (Access) {
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Public, "public", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Protected, "protected", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Private, "private", OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
+  switch (Type) {
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Struct, "struct", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Interface, "interface", OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Union, "union", OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_Machine &Machine) {
+  switch (Machine) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Am33, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Amd64, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Arm, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, ArmNT, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Ebc, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, x86, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Ia64, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, M32R, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Mips16, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, MipsFpu, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, MipsFpu16, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, PowerPC, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, PowerPCFP, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, R4000, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH3, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH3DSP, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH4, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, SH5, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, Thumb, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Machine, WceMipsV2, OS)
+  default:
+    OS << "Unknown";
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const PDB_SourceCompression &Compression) {
+  switch (Compression) {
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, None, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, Huffman, OS)
+    CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, LZ, OS)
+    CASE_OUTPUT_ENUM_CLASS_STR(PDB_SourceCompression, RunLengthEncoded, "RLE",
+                               OS)
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) {
+  switch (Value.Type) {
+    case PDB_VariantType::Bool:
+      OS << (Value.Value.Bool ? "true" : "false");
+      break;
+    case PDB_VariantType::Double:
+      OS << Value.Value.Double;
+      break;
+    case PDB_VariantType::Int16:
+      OS << Value.Value.Int16;
+      break;
+    case PDB_VariantType::Int32:
+      OS << Value.Value.Int32;
+      break;
+    case PDB_VariantType::Int64:
+      OS << Value.Value.Int64;
+      break;
+    case PDB_VariantType::Int8:
+      OS << static_cast<int>(Value.Value.Int8);
+      break;
+    case PDB_VariantType::Single:
+      OS << Value.Value.Single;
+      break;
+    case PDB_VariantType::UInt16:
+      OS << Value.Value.UInt16;
+      break;
+    case PDB_VariantType::UInt32:
+      OS << Value.Value.UInt32;
+      break;
+    case PDB_VariantType::UInt64:
+      OS << Value.Value.UInt64;
+      break;
+    case PDB_VariantType::UInt8:
+      OS << static_cast<unsigned>(Value.Value.UInt8);
+      break;
+    case PDB_VariantType::String:
+      OS << Value.Value.String;
+      break;
+    default:
+      OS << Value.Type;
+  }
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
+                                   const VersionInfo &Version) {
+  OS << Version.Major << "." << Version.Minor << "." << Version.Build;
+  return OS;
+}
+
+raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const TagStats &Stats) {
+  for (auto Tag : Stats) {
+    OS << Tag.first << ":" << Tag.second << " ";
+  }
+  return OS;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
new file mode 100644
index 0000000..9519092
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
@@ -0,0 +1,40 @@
+//===- PDBInterfaceAnchors.h - defines class anchor funcions ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Class anchors are necessary per the LLVM Coding style guide, to ensure that
+// the vtable is only generated in this object file, and not in every object
+// file that incldues the corresponding header.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
+#include "llvm/DebugInfo/PDB/IPDBFrameData.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBTable.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+IPDBSession::~IPDBSession() = default;
+
+IPDBDataStream::~IPDBDataStream() = default;
+
+IPDBRawSymbol::~IPDBRawSymbol() = default;
+
+IPDBLineNumber::~IPDBLineNumber() = default;
+
+IPDBTable::~IPDBTable() = default;
+
+IPDBInjectedSource::~IPDBInjectedSource() = default;
+
+IPDBSectionContrib::~IPDBSectionContrib() = default;
+
+IPDBFrameData::~IPDBFrameData() = default;
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
new file mode 100644
index 0000000..2f81931
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
@@ -0,0 +1,147 @@
+//===- PDBSymDumper.cpp - ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+#define PDB_SYMDUMP_UNREACHABLE(Type)                                          \
+  if (RequireImpl)                                                             \
+    llvm_unreachable("Attempt to dump " #Type " with no dump implementation");
+
+PDBSymDumper::PDBSymDumper(bool ShouldRequireImpl)
+    : RequireImpl(ShouldRequireImpl) {}
+
+PDBSymDumper::~PDBSymDumper() = default;
+
+void PDBSymDumper::dump(const PDBSymbolAnnotation &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolAnnotation)
+}
+
+void PDBSymDumper::dump(const PDBSymbolBlock &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolBlock)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompiland &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompiland)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompilandDetails &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandDetails)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompilandEnv &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandEnv)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCustom &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolCustom)
+}
+
+void PDBSymDumper::dump(const PDBSymbolData &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolData)
+}
+
+void PDBSymDumper::dump(const PDBSymbolExe &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolExe)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFunc &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolFunc)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFuncDebugEnd &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugEnd)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFuncDebugStart &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugStart)
+}
+
+void PDBSymDumper::dump(const PDBSymbolLabel &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolLabel)
+}
+
+void PDBSymDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolPublicSymbol)
+}
+
+void PDBSymDumper::dump(const PDBSymbolThunk &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolThunk)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeArray &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeArray)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBaseClass)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBuiltin)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeCustom &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeCustom)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeDimension &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeDimension)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeEnum)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFriend &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFriend)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionArg)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionSig)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeManaged &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeManaged)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypePointer &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypePointer)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeTypedef)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeUDT)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTable)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTableShape)
+}
+
+void PDBSymDumper::dump(const PDBSymbolUnknown &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolUnknown)
+}
+
+void PDBSymDumper::dump(const PDBSymbolUsingNamespace &Symbol) {
+  PDB_SYMDUMP_UNREACHABLE(PDBSymbolUsingNamespace)
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
new file mode 100644
index 0000000..d492eda
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -0,0 +1,215 @@
+//===- PDBSymbol.cpp - base class for user-facing symbol types --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include <algorithm>
+#include <memory>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+PDBSymbol::PDBSymbol(const IPDBSession &PDBSession) : Session(PDBSession) {}
+
+PDBSymbol::PDBSymbol(PDBSymbol &&Other)
+    : Session(Other.Session), RawSymbol(std::move(Other.RawSymbol)) {}
+
+PDBSymbol::~PDBSymbol() = default;
+
+#define FACTORY_SYMTAG_CASE(Tag, Type)                                         \
+  case PDB_SymType::Tag:                                                       \
+    return std::unique_ptr<PDBSymbol>(new Type(PDBSession));
+
+std::unique_ptr<PDBSymbol>
+PDBSymbol::createSymbol(const IPDBSession &PDBSession, PDB_SymType Tag) {
+  switch (Tag) {
+    FACTORY_SYMTAG_CASE(Exe, PDBSymbolExe)
+    FACTORY_SYMTAG_CASE(Compiland, PDBSymbolCompiland)
+    FACTORY_SYMTAG_CASE(CompilandDetails, PDBSymbolCompilandDetails)
+    FACTORY_SYMTAG_CASE(CompilandEnv, PDBSymbolCompilandEnv)
+    FACTORY_SYMTAG_CASE(Function, PDBSymbolFunc)
+    FACTORY_SYMTAG_CASE(Block, PDBSymbolBlock)
+    FACTORY_SYMTAG_CASE(Data, PDBSymbolData)
+    FACTORY_SYMTAG_CASE(Annotation, PDBSymbolAnnotation)
+    FACTORY_SYMTAG_CASE(Label, PDBSymbolLabel)
+    FACTORY_SYMTAG_CASE(PublicSymbol, PDBSymbolPublicSymbol)
+    FACTORY_SYMTAG_CASE(UDT, PDBSymbolTypeUDT)
+    FACTORY_SYMTAG_CASE(Enum, PDBSymbolTypeEnum)
+    FACTORY_SYMTAG_CASE(FunctionSig, PDBSymbolTypeFunctionSig)
+    FACTORY_SYMTAG_CASE(PointerType, PDBSymbolTypePointer)
+    FACTORY_SYMTAG_CASE(ArrayType, PDBSymbolTypeArray)
+    FACTORY_SYMTAG_CASE(BuiltinType, PDBSymbolTypeBuiltin)
+    FACTORY_SYMTAG_CASE(Typedef, PDBSymbolTypeTypedef)
+    FACTORY_SYMTAG_CASE(BaseClass, PDBSymbolTypeBaseClass)
+    FACTORY_SYMTAG_CASE(Friend, PDBSymbolTypeFriend)
+    FACTORY_SYMTAG_CASE(FunctionArg, PDBSymbolTypeFunctionArg)
+    FACTORY_SYMTAG_CASE(FuncDebugStart, PDBSymbolFuncDebugStart)
+    FACTORY_SYMTAG_CASE(FuncDebugEnd, PDBSymbolFuncDebugEnd)
+    FACTORY_SYMTAG_CASE(UsingNamespace, PDBSymbolUsingNamespace)
+    FACTORY_SYMTAG_CASE(VTableShape, PDBSymbolTypeVTableShape)
+    FACTORY_SYMTAG_CASE(VTable, PDBSymbolTypeVTable)
+    FACTORY_SYMTAG_CASE(Custom, PDBSymbolCustom)
+    FACTORY_SYMTAG_CASE(Thunk, PDBSymbolThunk)
+    FACTORY_SYMTAG_CASE(CustomType, PDBSymbolTypeCustom)
+    FACTORY_SYMTAG_CASE(ManagedType, PDBSymbolTypeManaged)
+    FACTORY_SYMTAG_CASE(Dimension, PDBSymbolTypeDimension)
+  default:
+    return std::unique_ptr<PDBSymbol>(new PDBSymbolUnknown(PDBSession));
+  }
+}
+
+std::unique_ptr<PDBSymbol>
+PDBSymbol::create(const IPDBSession &PDBSession,
+                  std::unique_ptr<IPDBRawSymbol> RawSymbol) {
+  auto SymbolPtr = createSymbol(PDBSession, RawSymbol->getSymTag());
+  SymbolPtr->RawSymbol = RawSymbol.get();
+  SymbolPtr->OwnedRawSymbol = std::move(RawSymbol);
+  return SymbolPtr;
+}
+
+std::unique_ptr<PDBSymbol> PDBSymbol::create(const IPDBSession &PDBSession,
+                                             IPDBRawSymbol &RawSymbol) {
+  auto SymbolPtr = createSymbol(PDBSession, RawSymbol.getSymTag());
+  SymbolPtr->RawSymbol = &RawSymbol;
+  return SymbolPtr;
+}
+
+void PDBSymbol::defaultDump(raw_ostream &OS, int Indent,
+                            PdbSymbolIdField ShowFlags,
+                            PdbSymbolIdField RecurseFlags) const {
+  RawSymbol->dump(OS, Indent, ShowFlags, RecurseFlags);
+}
+
+void PDBSymbol::dumpProperties() const {
+  outs() << "\n";
+  defaultDump(outs(), 0, PdbSymbolIdField::All, PdbSymbolIdField::None);
+  outs().flush();
+}
+
+void PDBSymbol::dumpChildStats() const {
+  TagStats Stats;
+  getChildStats(Stats);
+  outs() << "\n";
+  for (auto &Stat : Stats) {
+    outs() << Stat.first << ": " << Stat.second << "\n";
+  }
+  outs().flush();
+}
+
+PDB_SymType PDBSymbol::getSymTag() const { return RawSymbol->getSymTag(); }
+uint32_t PDBSymbol::getSymIndexId() const { return RawSymbol->getSymIndexId(); }
+
+std::unique_ptr<IPDBEnumSymbols> PDBSymbol::findAllChildren() const {
+  return findAllChildren(PDB_SymType::None);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findAllChildren(PDB_SymType Type) const {
+  return RawSymbol->findChildren(Type);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findChildren(PDB_SymType Type, StringRef Name,
+                        PDB_NameSearchFlags Flags) const {
+  return RawSymbol->findChildren(Type, Name, Flags);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+                             PDB_NameSearchFlags Flags, uint32_t RVA) const {
+  return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+  return RawSymbol->findInlineFramesByRVA(RVA);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::getChildStats(TagStats &Stats) const {
+  std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
+  if (!Result)
+    return nullptr;
+  Stats.clear();
+  while (auto Child = Result->getNext()) {
+    ++Stats[Child->getSymTag()];
+  }
+  Result->reset();
+  return Result;
+}
+
+std::unique_ptr<PDBSymbol> PDBSymbol::getSymbolByIdHelper(uint32_t Id) const {
+  return Session.getSymbolById(Id);
+}
+
+void llvm::pdb::dumpSymbolIdField(raw_ostream &OS, StringRef Name,
+                                  SymIndexId Value, int Indent,
+                                  const IPDBSession &Session,
+                                  PdbSymbolIdField FieldId,
+                                  PdbSymbolIdField ShowFlags,
+                                  PdbSymbolIdField RecurseFlags) {
+  if ((FieldId & ShowFlags) == PdbSymbolIdField::None)
+    return;
+
+  OS << "\n";
+  OS.indent(Indent);
+  OS << Name << ": " << Value;
+  // Don't recurse unless the user requested it.
+  if ((FieldId & RecurseFlags) == PdbSymbolIdField::None)
+    return;
+  // And obviously don't recurse on the symbol itself.
+  if (FieldId == PdbSymbolIdField::SymIndexId)
+    return;
+
+  auto Child = Session.getSymbolById(Value);
+
+  // It could have been a placeholder symbol for a type we don't yet support,
+  // so just exit in that case.
+  if (!Child)
+    return;
+
+  // Don't recurse more than once, so pass PdbSymbolIdField::None) for the
+  // recurse flags.
+  Child->defaultDump(OS, Indent + 2, ShowFlags, PdbSymbolIdField::None);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
new file mode 100644
index 0000000..cb1a9be
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
@@ -0,0 +1,21 @@
+//===- PDBSymbolAnnotation.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolAnnotation::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
new file mode 100644
index 0000000..13eec97
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
@@ -0,0 +1,20 @@
+//===- PDBSymbolBlock.cpp - -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolBlock::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
new file mode 100644
index 0000000..bbc5e6d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
@@ -0,0 +1,110 @@
+//===- PDBSymbolCompiland.cpp - compiland details ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Path.h"
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
+
+std::string PDBSymbolCompiland::getSourceFileName() const {
+  return sys::path::filename(getSourceFileFullPath()).str();
+}
+
+std::string PDBSymbolCompiland::getSourceFileFullPath() const {
+  std::string SourceFileFullPath;
+
+  // RecordedResult could be the basename, relative path or full path of the
+  // source file. Usually it is retrieved and recorded from the command that
+  // compiles this compiland.
+  //
+  //  cmd FileName          -> RecordedResult = .\\FileName
+  //  cmd (Path)\\FileName  -> RecordedResult = (Path)\\FileName
+  //
+  std::string RecordedResult = RawSymbol->getSourceFileName();
+
+  if (RecordedResult.empty()) {
+    if (auto Envs = findAllChildren<PDBSymbolCompilandEnv>()) {
+      std::string EnvWorkingDir, EnvSrc;
+
+      while (auto Env = Envs->getNext()) {
+        std::string Var = Env->getName();
+        if (Var == "cwd") {
+          EnvWorkingDir = Env->getValue();
+          continue;
+        }
+        if (Var == "src") {
+          EnvSrc = Env->getValue();
+          if (sys::path::is_absolute(EnvSrc))
+            return EnvSrc;
+          RecordedResult = EnvSrc;
+          continue;
+        }
+      }
+      if (!EnvWorkingDir.empty() && !EnvSrc.empty()) {
+        auto Len = EnvWorkingDir.length();
+        if (EnvWorkingDir[Len - 1] != '/' && EnvWorkingDir[Len - 1] != '\\') {
+          std::string Path = EnvWorkingDir + "\\" + EnvSrc;
+          std::replace(Path.begin(), Path.end(), '/', '\\');
+          // We will return it as full path if we can't find a better one.
+          if (sys::path::is_absolute(Path))
+            SourceFileFullPath = Path;
+        }
+      }
+    }
+  }
+
+  if (!RecordedResult.empty()) {
+    if (sys::path::is_absolute(RecordedResult))
+      return RecordedResult;
+
+    // This searches name that has same basename as the one in RecordedResult.
+    auto OneSrcFile = Session.findOneSourceFile(
+        this, RecordedResult, PDB_NameSearchFlags::NS_CaseInsensitive);
+    if (OneSrcFile)
+      return OneSrcFile->getFileName();
+  }
+
+  // At this point, we have to walk through all source files of this compiland,
+  // and determine the right source file if any that is used to generate this
+  // compiland based on language indicated in compilanddetails language field.
+  auto Details = findOneChild<PDBSymbolCompilandDetails>();
+  PDB_Lang Lang = Details ? Details->getLanguage() : PDB_Lang::Cpp;
+  auto SrcFiles = Session.getSourceFilesForCompiland(*this);
+  if (SrcFiles) {
+    bool LangC = (Lang == PDB_Lang::Cpp || Lang == PDB_Lang::C);
+    while (auto File = SrcFiles->getNext()) {
+      std::string FileName = File->getFileName();
+      auto file_extension = sys::path::extension(FileName);
+      if (StringSwitch<bool>(file_extension.lower())
+              .Case(".cpp", LangC)
+              .Case(".c", LangC)
+              .Case(".cc", LangC)
+              .Case(".cxx", LangC)
+              .Case(".asm", Lang == PDB_Lang::Masm)
+              .Default(false))
+        return File->getFileName();
+    }
+  }
+
+  return SourceFileFullPath;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
new file mode 100644
index 0000000..bdd8535
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolCompilandDetails.cpp - compiland details --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolCompilandDetails::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
new file mode 100644
index 0000000..f88df2d
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
@@ -0,0 +1,30 @@
+//===- PDBSymbolCompilandEnv.cpp - compiland env variables ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+std::string PDBSymbolCompilandEnv::getValue() const {
+  Variant Value = RawSymbol->getValue();
+  if (Value.Type != PDB_VariantType::String)
+    return std::string();
+  return std::string(Value.Value.String);
+}
+
+void PDBSymbolCompilandEnv::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
new file mode 100644
index 0000000..10a2180
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolCustom.cpp - compiler-specific types ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h"
+
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolCustom::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) {
+  RawSymbol->getDataBytes(bytes);
+}
+
+void PDBSymbolCustom::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
new file mode 100644
index 0000000..7de9467
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
@@ -0,0 +1,69 @@
+//===- PDBSymbolData.cpp - PDB data (e.g. variable) accessors ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolData::getLineNumbers() const {
+  auto Len = RawSymbol->getLength();
+  Len = Len ? Len : 1;
+  if (auto RVA = RawSymbol->getRelativeVirtualAddress())
+    return Session.findLineNumbersByRVA(RVA, Len);
+
+  if (auto Section = RawSymbol->getAddressSection())
+    return Session.findLineNumbersBySectOffset(
+        Section, RawSymbol->getAddressOffset(), Len);
+
+  return nullptr;
+}
+
+uint32_t PDBSymbolData::getCompilandId() const {
+  if (auto Lines = getLineNumbers()) {
+    if (auto FirstLine = Lines->getNext())
+      return FirstLine->getCompilandId();
+  }
+
+  uint32_t DataSection = RawSymbol->getAddressSection();
+  uint32_t DataOffset = RawSymbol->getAddressOffset();
+  if (DataSection == 0) {
+    if (auto RVA = RawSymbol->getRelativeVirtualAddress())
+      Session.addressForRVA(RVA, DataSection, DataOffset);
+  }
+
+  if (DataSection) {
+    if (auto SecContribs = Session.getSectionContribs()) {
+      while (auto Section = SecContribs->getNext()) {
+        if (Section->getAddressSection() == DataSection &&
+            Section->getAddressOffset() <= DataOffset &&
+            (Section->getAddressOffset() + Section->getLength()) > DataOffset)
+          return Section->getCompilandId();
+      }
+    }
+  } else {
+    auto LexParentId = RawSymbol->getLexicalParentId();
+    while (auto LexParent = Session.getSymbolById(LexParentId)) {
+      if (LexParent->getSymTag() == PDB_SymType::Exe)
+        break;
+      if (LexParent->getSymTag() == PDB_SymType::Compiland)
+        return LexParentId;
+      LexParentId = LexParent->getRawSymbol().getLexicalParentId();
+    }
+  }
+
+  return 0;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
new file mode 100644
index 0000000..eb40941
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
@@ -0,0 +1,30 @@
+//===- PDBSymbolExe.cpp - ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+uint32_t PDBSymbolExe::getPointerByteSize() const {
+  auto Pointer = findOneChild<PDBSymbolTypePointer>();
+  if (Pointer)
+    return Pointer->getLength();
+
+  if (getMachineType() == PDB_Machine::x86)
+    return 4;
+  return 8;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
new file mode 100644
index 0000000..75063cb
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -0,0 +1,112 @@
+//===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace {
+class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
+public:
+  typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType;
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        const PDBSymbolFunc &PDBFunc)
+      : Session(PDBSession), Func(PDBFunc) {
+    // Arguments can appear multiple times if they have live range
+    // information, so we only take the first occurrence.
+    std::unordered_set<std::string> SeenNames;
+    auto DataChildren = Func.findAllChildren<PDBSymbolData>();
+    while (auto Child = DataChildren->getNext()) {
+      if (Child->getDataKind() == PDB_DataKind::Param) {
+        std::string Name = Child->getName();
+        if (SeenNames.find(Name) != SeenNames.end())
+          continue;
+        Args.push_back(std::move(Child));
+        SeenNames.insert(Name);
+      }
+    }
+    reset();
+  }
+
+  uint32_t getChildCount() const override { return Args.size(); }
+
+  std::unique_ptr<PDBSymbolData>
+  getChildAtIndex(uint32_t Index) const override {
+    if (Index >= Args.size())
+      return nullptr;
+
+    return Session.getConcreteSymbolById<PDBSymbolData>(
+        Args[Index]->getSymIndexId());
+  }
+
+  std::unique_ptr<PDBSymbolData> getNext() override {
+    if (CurIter == Args.end())
+      return nullptr;
+    const auto &Result = **CurIter;
+    ++CurIter;
+    return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId());
+  }
+
+  void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); }
+
+private:
+  typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType;
+  const IPDBSession &Session;
+  const PDBSymbolFunc &Func;
+  ArgListType Args;
+  ArgListType::const_iterator CurIter;
+};
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolData>>
+PDBSymbolFunc::getArguments() const {
+  return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+bool PDBSymbolFunc::isDestructor() const {
+  std::string Name = getName();
+  if (Name.empty())
+    return false;
+  if (Name[0] == '~')
+    return true;
+  if (Name == "__vecDelDtor")
+    return true;
+  return false;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const {
+  auto Len = RawSymbol->getLength();
+  return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(),
+                                          Len ? Len : 1);
+}
+
+uint32_t PDBSymbolFunc::getCompilandId() const {
+  if (auto Lines = getLineNumbers()) {
+    if (auto FirstLine = Lines->getNext()) {
+      return FirstLine->getCompilandId();
+    }
+  }
+  return 0;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
new file mode 100644
index 0000000..af8aafa
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolFuncDebugEnd.cpp - ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolFuncDebugEnd::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
new file mode 100644
index 0000000..77b5108
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolFuncDebugStart.cpp - ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolFuncDebugStart::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
new file mode 100644
index 0000000..c802b97
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
@@ -0,0 +1,19 @@
+//===- PDBSymbolLabel.cpp - -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolLabel::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
new file mode 100644
index 0000000..a2dd2ab
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolPublicSymbol.cpp - ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolPublicSymbol::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
new file mode 100644
index 0000000..d227e3a
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
@@ -0,0 +1,19 @@
+//===- PDBSymbolThunk.cpp - -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolThunk::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
new file mode 100644
index 0000000..a2064d1
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolTypeArray.cpp - ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeArray::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
+
+void PDBSymbolTypeArray::dumpRight(PDBSymDumper &Dumper) const {
+  Dumper.dumpRight(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
new file mode 100644
index 0000000..f0376c0
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeBaseClass.cpp - -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeBaseClass::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
new file mode 100644
index 0000000..a9f59e5
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
@@ -0,0 +1,21 @@
+//===- PDBSymbolTypeBuiltin.cpp - ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeBuiltin::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
new file mode 100644
index 0000000..cfb347f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeCustom.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeCustom::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
new file mode 100644
index 0000000..4eb4899
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeDimension.cpp - --------------------------------*- C++
+//-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+void PDBSymbolTypeDimension::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
new file mode 100644
index 0000000..2e88d9e
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
@@ -0,0 +1,20 @@
+//===- PDBSymbolTypeEnum.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
new file mode 100644
index 0000000..00d2d51
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeFriend.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeFriend::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
new file mode 100644
index 0000000..0399e11
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
@@ -0,0 +1,21 @@
+//===- PDBSymbolTypeFunctionArg.cpp - --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeFunctionArg::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
new file mode 100644
index 0000000..c0564d3
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
@@ -0,0 +1,94 @@
+//===- PDBSymbolTypeFunctionSig.cpp - --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace {
+class FunctionArgEnumerator : public IPDBEnumSymbols {
+public:
+  typedef ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg> ArgEnumeratorType;
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        const PDBSymbolTypeFunctionSig &Sig)
+      : Session(PDBSession),
+        Enumerator(Sig.findAllChildren<PDBSymbolTypeFunctionArg>()) {}
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        std::unique_ptr<ArgEnumeratorType> ArgEnumerator)
+      : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {}
+
+  uint32_t getChildCount() const override {
+    return Enumerator->getChildCount();
+  }
+
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
+    auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index);
+    if (!FunctionArgSymbol)
+      return nullptr;
+    return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+  }
+
+  std::unique_ptr<PDBSymbol> getNext() override {
+    auto FunctionArgSymbol = Enumerator->getNext();
+    if (!FunctionArgSymbol)
+      return nullptr;
+    return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+  }
+
+  void reset() override { Enumerator->reset(); }
+
+private:
+  const IPDBSession &Session;
+  std::unique_ptr<ArgEnumeratorType> Enumerator;
+};
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbolTypeFunctionSig::getArguments() const {
+  return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+void PDBSymbolTypeFunctionSig::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
+
+void PDBSymbolTypeFunctionSig::dumpRight(PDBSymDumper &Dumper) const {
+  Dumper.dumpRight(*this);
+}
+
+bool PDBSymbolTypeFunctionSig::isCVarArgs() const {
+  auto SigArguments = getArguments();
+  if (!SigArguments)
+    return false;
+  uint32_t NumArgs = SigArguments->getChildCount();
+  if (NumArgs == 0)
+    return false;
+  auto Last = SigArguments->getChildAtIndex(NumArgs - 1);
+  if (auto Builtin = llvm::dyn_cast_or_null<PDBSymbolTypeBuiltin>(Last.get())) {
+    if (Builtin->getBuiltinType() == PDB_BuiltinType::None)
+      return true;
+  }
+
+  // Note that for a variadic template signature, this method always returns
+  // false since the parameters of the template are specialized.
+  return false;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
new file mode 100644
index 0000000..1faaf9c
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymboTypelManaged.cpp - ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeManaged::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
new file mode 100644
index 0000000..cf5a369
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
@@ -0,0 +1,26 @@
+//===- PDBSymbolTypePointer.cpp -----------------------------------*- C++ -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypePointer::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
+
+void PDBSymbolTypePointer::dumpRight(PDBSymDumper &Dumper) const {
+  Dumper.dumpRight(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
new file mode 100644
index 0000000..1838f16
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
@@ -0,0 +1,21 @@
+//===- PDBSymbolTypeTypedef.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeTypedef::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
new file mode 100644
index 0000000..2f5222f
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
@@ -0,0 +1,26 @@
+//===- PDBSymbolTypeUDT.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeUDT::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
new file mode 100644
index 0000000..0262f91
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
@@ -0,0 +1,21 @@
+//===- PDBSymbolTypeVTable.cpp - --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeVTable::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
new file mode 100644
index 0000000..16c3a36
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeVTableShape.cpp - ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolTypeVTableShape::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
new file mode 100644
index 0000000..7bcf945
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
@@ -0,0 +1,20 @@
+//===- PDBSymbolUnknown.cpp - -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolUnknown::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
new file mode 100644
index 0000000..ecf2126
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolUsingNamespace.cpp - ------------------- --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+void PDBSymbolUsingNamespace::dump(PDBSymDumper &Dumper) const {
+  Dumper.dump(*this);
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/src/llvm-project/llvm/lib/DebugInfo/PDB/UDTLayout.cpp
new file mode 100644
index 0000000..5f4390b
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/PDB/UDTLayout.cpp
@@ -0,0 +1,303 @@
+//===- UDTLayout.cpp ------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <memory>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
+  const IPDBSession &Session = Symbol.getSession();
+  const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
+  uint32_t TypeId = RawSymbol.getTypeId();
+  return Session.getSymbolById(TypeId);
+}
+
+static uint32_t getTypeLength(const PDBSymbol &Symbol) {
+  auto SymbolType = getSymbolType(Symbol);
+  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
+
+  return RawType.getLength();
+}
+
+LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent,
+                               const PDBSymbol *Symbol, const std::string &Name,
+                               uint32_t OffsetInParent, uint32_t Size,
+                               bool IsElided)
+    : Symbol(Symbol), Parent(Parent), Name(Name),
+      OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
+      IsElided(IsElided) {
+  UsedBytes.resize(SizeOf, true);
+}
+
+uint32_t LayoutItemBase::deepPaddingSize() const {
+  return UsedBytes.size() - UsedBytes.count();
+}
+
+uint32_t LayoutItemBase::tailPadding() const {
+  int Last = UsedBytes.find_last();
+
+  return UsedBytes.size() - (Last + 1);
+}
+
+DataMemberLayoutItem::DataMemberLayoutItem(
+    const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
+    : LayoutItemBase(&Parent, Member.get(), Member->getName(),
+                     Member->getOffset(), getTypeLength(*Member), false),
+      DataMember(std::move(Member)) {
+  auto Type = DataMember->getType();
+  if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
+    UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
+    UsedBytes = UdtLayout->usedBytes();
+  }
+}
+
+VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent,
+                                 std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
+                                 uint32_t Offset, uint32_t Size)
+    : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
+      Type(std::move(Sym)) {
+}
+
+const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
+  return *dyn_cast<PDBSymbolData>(Symbol);
+}
+
+bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
+
+const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
+  return *UdtLayout;
+}
+
+VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
+                                   std::unique_ptr<PDBSymbolTypeVTable> VT)
+    : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
+      VTable(std::move(VT)) {
+  auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
+  ElementSize = VTableType->getLength();
+}
+
+UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
+                             const std::string &Name, uint32_t OffsetInParent,
+                             uint32_t Size, bool IsElided)
+    : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
+  // UDT storage comes from a union of all the children's storage, so start out
+  // uninitialized.
+  UsedBytes.reset(0, Size);
+
+  initializeChildren(Sym);
+  if (LayoutSize < Size)
+    UsedBytes.resize(LayoutSize);
+}
+
+uint32_t UDTLayoutBase::tailPadding() const {
+  uint32_t Abs = LayoutItemBase::tailPadding();
+  if (!LayoutItems.empty()) {
+    const LayoutItemBase *Back = LayoutItems.back();
+    uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
+    if (Abs < ChildPadding)
+      Abs = 0;
+    else
+      Abs -= ChildPadding;
+  }
+  return Abs;
+}
+
+ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
+    : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
+      UDT(UDT) {
+  ImmediateUsedBytes.resize(SizeOf, false);
+  for (auto &LI : LayoutItems) {
+    uint32_t Begin = LI->getOffsetInParent();
+    uint32_t End = Begin + LI->getLayoutSize();
+    End = std::min(SizeOf, End);
+    ImmediateUsedBytes.set(Begin, End);
+  }
+}
+
+ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
+    : ClassLayout(*UDT) {
+  OwnedStorage = std::move(UDT);
+}
+
+uint32_t ClassLayout::immediatePadding() const {
+  return SizeOf - ImmediateUsedBytes.count();
+}
+
+BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
+                                 uint32_t OffsetInParent, bool Elide,
+                                 std::unique_ptr<PDBSymbolTypeBaseClass> B)
+    : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
+                    Elide),
+      Base(std::move(B)) {
+  if (isEmptyBase()) {
+    // Special case an empty base so that it doesn't get treated as padding.
+    UsedBytes.resize(1);
+    UsedBytes.set(0);
+  }
+  IsVirtualBase = Base->isVirtualBaseClass();
+}
+
+void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
+  // Handled bases first, followed by VTables, followed by data members,
+  // followed by functions, followed by other.  This ordering is necessary
+  // so that bases and vtables get initialized before any functions which
+  // may override them.
+  UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
+  UniquePtrVector<PDBSymbolTypeVTable> VTables;
+  UniquePtrVector<PDBSymbolData> Members;
+  UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;
+
+  auto Children = Sym.findAllChildren();
+  while (auto Child = Children->getNext()) {
+    if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
+      if (Base->isVirtualBaseClass())
+        VirtualBaseSyms.push_back(std::move(Base));
+      else
+        Bases.push_back(std::move(Base));
+    }
+    else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
+      if (Data->getDataKind() == PDB_DataKind::Member)
+        Members.push_back(std::move(Data));
+      else
+        Other.push_back(std::move(Data));
+    } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
+      VTables.push_back(std::move(VT));
+    else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
+      Funcs.push_back(std::move(Func));
+    else {
+      Other.push_back(std::move(Child));
+    }
+  }
+
+  // We don't want to have any re-allocations in the list of bases, so make
+  // sure to reserve enough space so that our ArrayRefs don't get invalidated.
+  AllBases.reserve(Bases.size() + VirtualBaseSyms.size());
+
+  // Only add non-virtual bases to the class first.  Only at the end of the
+  // class, after all non-virtual bases and data members have been added do we
+  // add virtual bases.  This way the offsets are correctly aligned when we go
+  // to lay out virtual bases.
+  for (auto &Base : Bases) {
+    uint32_t Offset = Base->getOffset();
+    // Non-virtual bases never get elided.
+    auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false,
+                                                 std::move(Base));
+
+    AllBases.push_back(BL.get());
+    addChildToLayout(std::move(BL));
+  }
+  NonVirtualBases = AllBases;
+
+  assert(VTables.size() <= 1);
+  if (!VTables.empty()) {
+    auto VTLayout =
+        llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));
+
+    VTable = VTLayout.get();
+
+    addChildToLayout(std::move(VTLayout));
+  }
+
+  for (auto &Data : Members) {
+    auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
+
+    addChildToLayout(std::move(DM));
+  }
+
+  // Make sure add virtual bases before adding functions, since functions may be
+  // overrides of virtual functions declared in a virtual base, so the VTables
+  // and virtual intros need to be correctly initialized.
+  for (auto &VB : VirtualBaseSyms) {
+    int VBPO = VB->getVirtualBasePointerOffset();
+    if (!hasVBPtrAtOffset(VBPO)) {
+      if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
+        auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
+                                                       VBPO, VBP->getLength());
+        VBPtr = VBPL.get();
+        addChildToLayout(std::move(VBPL));
+      }
+    }
+
+    // Virtual bases always go at the end.  So just look for the last place we
+    // ended when writing something, and put our virtual base there.
+    // Note that virtual bases get elided unless this is a top-most derived
+    // class.
+    uint32_t Offset = UsedBytes.find_last() + 1;
+    bool Elide = (Parent != nullptr);
+    auto BL =
+        llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
+    AllBases.push_back(BL.get());
+
+    // Only lay this virtual base out directly inside of *this* class if this
+    // is a top-most derived class.  Keep track of it regardless, but only
+    // physically lay it out if it's a topmost derived class.
+    addChildToLayout(std::move(BL));
+  }
+  VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());
+
+  if (Parent != nullptr)
+    LayoutSize = UsedBytes.find_last() + 1;
+}
+
+bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const {
+  if (VBPtr && VBPtr->getOffsetInParent() == Off)
+    return true;
+  for (BaseClassLayout *BL : AllBases) {
+    if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
+      return true;
+  }
+  return false;
+}
+
+void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
+  uint32_t Begin = Child->getOffsetInParent();
+
+  if (!Child->isElided()) {
+    BitVector ChildBytes = Child->usedBytes();
+
+    // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
+    // class.  When we call ChildBytes.resize(32), the Child's storage will
+    // still begin at offset 0, so we need to shift it left by offset bytes
+    // to get it into the right position.
+    ChildBytes.resize(UsedBytes.size());
+    ChildBytes <<= Child->getOffsetInParent();
+    UsedBytes |= ChildBytes;
+
+    if (ChildBytes.count() > 0) {
+      auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
+                                  [](uint32_t Off, const LayoutItemBase *Item) {
+                                    return (Off < Item->getOffsetInParent());
+                                  });
+
+      LayoutItems.insert(Loc, Child.get());
+    }
+  }
+
+  ChildStorage.push_back(std::move(Child));
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
new file mode 100644
index 0000000..fe5c4bf
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_llvm_library(LLVMSymbolize
+  DIPrinter.cpp
+  SymbolizableObjectFile.cpp
+  Symbolize.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/Symbolize
+  )
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
new file mode 100644
index 0000000..c1e2536
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
@@ -0,0 +1,121 @@
+//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DIPrinter class, which is responsible for printing
+// structures defined in DebugInfo/DIContext.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+
+namespace llvm {
+namespace symbolize {
+
+// By default, DILineInfo contains "<invalid>" for function/filename it
+// cannot fetch. We replace it to "??" to make our output closer to addr2line.
+static const char kDILineInfoBadString[] = "<invalid>";
+static const char kBadString[] = "??";
+
+// Prints source code around in the FileName the Line.
+void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
+  if (PrintSourceContext <= 0)
+    return;
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+      MemoryBuffer::getFile(FileName);
+  if (!BufOrErr)
+    return;
+
+  std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
+  int64_t FirstLine =
+      std::max(static_cast<int64_t>(1), Line - PrintSourceContext / 2);
+  int64_t LastLine = FirstLine + PrintSourceContext;
+  size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
+
+  for (line_iterator I = line_iterator(*Buf, false);
+       !I.is_at_eof() && I.line_number() <= LastLine; ++I) {
+    int64_t L = I.line_number();
+    if (L >= FirstLine && L <= LastLine) {
+      OS << format_decimal(L, MaxLineNumberWidth);
+      if (L == Line)
+        OS << " >: ";
+      else
+        OS << "  : ";
+      OS << *I << "\n";
+    }
+  }
+}
+
+void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
+  if (PrintFunctionNames) {
+    std::string FunctionName = Info.FunctionName;
+    if (FunctionName == kDILineInfoBadString)
+      FunctionName = kBadString;
+
+    StringRef Delimiter = PrintPretty ? " at " : "\n";
+    StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
+    OS << Prefix << FunctionName << Delimiter;
+  }
+  std::string Filename = Info.FileName;
+  if (Filename == kDILineInfoBadString)
+    Filename = kBadString;
+  if (!Verbose) {
+    OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
+    printContext(Filename, Info.Line);
+    return;
+  }
+  OS << "  Filename: " << Filename << "\n";
+  if (Info.StartLine)
+    OS << "Function start line: " << Info.StartLine << "\n";
+  OS << "  Line: " << Info.Line << "\n";
+  OS << "  Column: " << Info.Column << "\n";
+  if (Info.Discriminator)
+    OS << "  Discriminator: " << Info.Discriminator << "\n";
+}
+
+DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
+  print(Info, false);
+  return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
+  uint32_t FramesNum = Info.getNumberOfFrames();
+  if (FramesNum == 0) {
+    print(DILineInfo(), false);
+    return *this;
+  }
+  for (uint32_t i = 0; i < FramesNum; i++)
+    print(Info.getFrame(i), i > 0);
+  return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
+  std::string Name = Global.Name;
+  if (Name == kDILineInfoBadString)
+    Name = kBadString;
+  OS << Name << "\n";
+  OS << Global.Start << " " << Global.Size << "\n";
+  return *this;
+}
+
+} // end namespace symbolize
+} // end namespace llvm
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/LLVMBuild.txt b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/LLVMBuild.txt
new file mode 100644
index 0000000..06498a8
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/DebugInfo/Symbolize/LLVMBuild.txt ------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = Symbolize
+parent = DebugInfo
+required_libraries = DebugInfoDWARF DebugInfoPDB Object Support Demangle
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
new file mode 100644
index 0000000..08be524
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
@@ -0,0 +1,271 @@
+//===- SymbolizableObjectFile.cpp -----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of SymbolizableObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolizableObjectFile.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolSize.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace object;
+using namespace symbolize;
+
+static DILineInfoSpecifier
+getDILineInfoSpecifier(FunctionNameKind FNKind) {
+  return DILineInfoSpecifier(
+      DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FNKind);
+}
+
+ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
+SymbolizableObjectFile::create(object::ObjectFile *Obj,
+                               std::unique_ptr<DIContext> DICtx) {
+  std::unique_ptr<SymbolizableObjectFile> res(
+      new SymbolizableObjectFile(Obj, std::move(DICtx)));
+  std::unique_ptr<DataExtractor> OpdExtractor;
+  uint64_t OpdAddress = 0;
+  // Find the .opd (function descriptor) section if any, for big-endian
+  // PowerPC64 ELF.
+  if (Obj->getArch() == Triple::ppc64) {
+    for (section_iterator Section : Obj->sections()) {
+      StringRef Name;
+      StringRef Data;
+      if (auto EC = Section->getName(Name))
+        return EC;
+      if (Name == ".opd") {
+        if (auto EC = Section->getContents(Data))
+          return EC;
+        OpdExtractor.reset(new DataExtractor(Data, Obj->isLittleEndian(),
+                                             Obj->getBytesInAddress()));
+        OpdAddress = Section->getAddress();
+        break;
+      }
+    }
+  }
+  std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
+      computeSymbolSizes(*Obj);
+  for (auto &P : Symbols)
+    res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
+
+  // If this is a COFF object and we didn't find any symbols, try the export
+  // table.
+  if (Symbols.empty()) {
+    if (auto *CoffObj = dyn_cast<COFFObjectFile>(Obj))
+      if (auto EC = res->addCoffExportSymbols(CoffObj))
+        return EC;
+  }
+  return std::move(res);
+}
+
+SymbolizableObjectFile::SymbolizableObjectFile(ObjectFile *Obj,
+                                               std::unique_ptr<DIContext> DICtx)
+    : Module(Obj), DebugInfoContext(std::move(DICtx)) {}
+
+namespace {
+
+struct OffsetNamePair {
+  uint32_t Offset;
+  StringRef Name;
+
+  bool operator<(const OffsetNamePair &R) const {
+    return Offset < R.Offset;
+  }
+};
+
+} // end anonymous namespace
+
+std::error_code SymbolizableObjectFile::addCoffExportSymbols(
+    const COFFObjectFile *CoffObj) {
+  // Get all export names and offsets.
+  std::vector<OffsetNamePair> ExportSyms;
+  for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) {
+    StringRef Name;
+    uint32_t Offset;
+    if (auto EC = Ref.getSymbolName(Name))
+      return EC;
+    if (auto EC = Ref.getExportRVA(Offset))
+      return EC;
+    ExportSyms.push_back(OffsetNamePair{Offset, Name});
+  }
+  if (ExportSyms.empty())
+    return std::error_code();
+
+  // Sort by ascending offset.
+  array_pod_sort(ExportSyms.begin(), ExportSyms.end());
+
+  // Approximate the symbol sizes by assuming they run to the next symbol.
+  // FIXME: This assumes all exports are functions.
+  uint64_t ImageBase = CoffObj->getImageBase();
+  for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
+    OffsetNamePair &Export = *I;
+    // FIXME: The last export has a one byte size now.
+    uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
+    uint64_t SymbolStart = ImageBase + Export.Offset;
+    uint64_t SymbolSize = NextOffset - Export.Offset;
+    SymbolDesc SD = {SymbolStart, SymbolSize};
+    Functions.insert(std::make_pair(SD, Export.Name));
+  }
+  return std::error_code();
+}
+
+std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
+                                                  uint64_t SymbolSize,
+                                                  DataExtractor *OpdExtractor,
+                                                  uint64_t OpdAddress) {
+  Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType();
+  if (!SymbolTypeOrErr)
+    return errorToErrorCode(SymbolTypeOrErr.takeError());
+  SymbolRef::Type SymbolType = *SymbolTypeOrErr;
+  if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
+    return std::error_code();
+  Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
+  if (!SymbolAddressOrErr)
+    return errorToErrorCode(SymbolAddressOrErr.takeError());
+  uint64_t SymbolAddress = *SymbolAddressOrErr;
+  if (OpdExtractor) {
+    // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
+    // function descriptors. The first word of the descriptor is a pointer to
+    // the function's code.
+    // For the purposes of symbolization, pretend the symbol's address is that
+    // of the function's code, not the descriptor.
+    uint64_t OpdOffset = SymbolAddress - OpdAddress;
+    uint32_t OpdOffset32 = OpdOffset;
+    if (OpdOffset == OpdOffset32 &&
+        OpdExtractor->isValidOffsetForAddress(OpdOffset32))
+      SymbolAddress = OpdExtractor->getAddress(&OpdOffset32);
+  }
+  Expected<StringRef> SymbolNameOrErr = Symbol.getName();
+  if (!SymbolNameOrErr)
+    return errorToErrorCode(SymbolNameOrErr.takeError());
+  StringRef SymbolName = *SymbolNameOrErr;
+  // Mach-O symbol table names have leading underscore, skip it.
+  if (Module->isMachO() && !SymbolName.empty() && SymbolName[0] == '_')
+    SymbolName = SymbolName.drop_front();
+  // FIXME: If a function has alias, there are two entries in symbol table
+  // with same address size. Make sure we choose the correct one.
+  auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
+  SymbolDesc SD = { SymbolAddress, SymbolSize };
+  M.insert(std::make_pair(SD, SymbolName));
+  return std::error_code();
+}
+
+// Return true if this is a 32-bit x86 PE COFF module.
+bool SymbolizableObjectFile::isWin32Module() const {
+  auto *CoffObject = dyn_cast<COFFObjectFile>(Module);
+  return CoffObject && CoffObject->getMachine() == COFF::IMAGE_FILE_MACHINE_I386;
+}
+
+uint64_t SymbolizableObjectFile::getModulePreferredBase() const {
+  if (auto *CoffObject = dyn_cast<COFFObjectFile>(Module))
+    return CoffObject->getImageBase();
+  return 0;
+}
+
+bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type,
+                                                    uint64_t Address,
+                                                    std::string &Name,
+                                                    uint64_t &Addr,
+                                                    uint64_t &Size) const {
+  const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects;
+  if (SymbolMap.empty())
+    return false;
+  SymbolDesc SD = { Address, Address };
+  auto SymbolIterator = SymbolMap.upper_bound(SD);
+  if (SymbolIterator == SymbolMap.begin())
+    return false;
+  --SymbolIterator;
+  if (SymbolIterator->first.Size != 0 &&
+      SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address)
+    return false;
+  Name = SymbolIterator->second.str();
+  Addr = SymbolIterator->first.Addr;
+  Size = SymbolIterator->first.Size;
+  return true;
+}
+
+bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
+    FunctionNameKind FNKind, bool UseSymbolTable) const {
+  // When DWARF is used with -gline-tables-only / -gmlt, the symbol table gives
+  // better answers for linkage names than the DIContext. Otherwise, we are
+  // probably using PEs and PDBs, and we shouldn't do the override. PE files
+  // generally only contain the names of exported symbols.
+  return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&
+         isa<DWARFContext>(DebugInfoContext.get());
+}
+
+DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset,
+                                                 FunctionNameKind FNKind,
+                                                 bool UseSymbolTable) const {
+  DILineInfo LineInfo;
+  if (DebugInfoContext) {
+    LineInfo = DebugInfoContext->getLineInfoForAddress(
+        ModuleOffset, getDILineInfoSpecifier(FNKind));
+  }
+  // Override function name from symbol table if necessary.
+  if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
+    std::string FunctionName;
+    uint64_t Start, Size;
+    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+                               FunctionName, Start, Size)) {
+      LineInfo.FunctionName = FunctionName;
+    }
+  }
+  return LineInfo;
+}
+
+DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode(
+    uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const {
+  DIInliningInfo InlinedContext;
+
+  if (DebugInfoContext)
+    InlinedContext = DebugInfoContext->getInliningInfoForAddress(
+        ModuleOffset, getDILineInfoSpecifier(FNKind));
+  // Make sure there is at least one frame in context.
+  if (InlinedContext.getNumberOfFrames() == 0)
+    InlinedContext.addFrame(DILineInfo());
+
+  // Override the function name in lower frame with name from symbol table.
+  if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
+    std::string FunctionName;
+    uint64_t Start, Size;
+    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+                               FunctionName, Start, Size)) {
+      InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1)
+          ->FunctionName = FunctionName;
+    }
+  }
+
+  return InlinedContext;
+}
+
+DIGlobal SymbolizableObjectFile::symbolizeData(uint64_t ModuleOffset) const {
+  DIGlobal Res;
+  getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Res.Name, Res.Start,
+                         Res.Size);
+  return Res;
+}
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
new file mode 100644
index 0000000..216cca8
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
@@ -0,0 +1,90 @@
+//===- SymbolizableObjectFile.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SymbolizableObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
+#define LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
+#include "llvm/Support/ErrorOr.h"
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+
+namespace llvm {
+
+class DataExtractor;
+
+namespace symbolize {
+
+class SymbolizableObjectFile : public SymbolizableModule {
+public:
+  static ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
+  create(object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx);
+
+  DILineInfo symbolizeCode(uint64_t ModuleOffset, FunctionNameKind FNKind,
+                           bool UseSymbolTable) const override;
+  DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset,
+                                      FunctionNameKind FNKind,
+                                      bool UseSymbolTable) const override;
+  DIGlobal symbolizeData(uint64_t ModuleOffset) const override;
+
+  // Return true if this is a 32-bit x86 PE COFF module.
+  bool isWin32Module() const override;
+
+  // Returns the preferred base of the module, i.e. where the loader would place
+  // it in memory assuming there were no conflicts.
+  uint64_t getModulePreferredBase() const override;
+
+private:
+  bool shouldOverrideWithSymbolTable(FunctionNameKind FNKind,
+                                     bool UseSymbolTable) const;
+
+  bool getNameFromSymbolTable(object::SymbolRef::Type Type, uint64_t Address,
+                              std::string &Name, uint64_t &Addr,
+                              uint64_t &Size) const;
+  // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd
+  // (function descriptor) section and OpdExtractor refers to its contents.
+  std::error_code addSymbol(const object::SymbolRef &Symbol,
+                            uint64_t SymbolSize,
+                            DataExtractor *OpdExtractor = nullptr,
+                            uint64_t OpdAddress = 0);
+  std::error_code addCoffExportSymbols(const object::COFFObjectFile *CoffObj);
+
+  object::ObjectFile *Module;
+  std::unique_ptr<DIContext> DebugInfoContext;
+
+  struct SymbolDesc {
+    uint64_t Addr;
+    // If size is 0, assume that symbol occupies the whole memory range up to
+    // the following symbol.
+    uint64_t Size;
+
+    friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
+      return s1.Addr < s2.Addr;
+    }
+  };
+  std::map<SymbolDesc, StringRef> Functions;
+  std::map<SymbolDesc, StringRef> Objects;
+
+  SymbolizableObjectFile(object::ObjectFile *Obj,
+                         std::unique_ptr<DIContext> DICtx);
+};
+
+} // end namespace symbolize
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
diff --git a/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
new file mode 100644
index 0000000..59a85d6
--- /dev/null
+++ b/src/llvm-project/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -0,0 +1,505 @@
+//===-- LLVMSymbolize.cpp -------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+
+#include "SymbolizableObjectFile.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBContext.h"
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+
+#if defined(_MSC_VER)
+#include <Windows.h>
+
+// This must be included after windows.h.
+#include <DbgHelp.h>
+#pragma comment(lib, "dbghelp.lib")
+
+// Windows.h conflicts with our COFF header definitions.
+#ifdef IMAGE_FILE_MACHINE_I386
+#undef IMAGE_FILE_MACHINE_I386
+#endif
+#endif
+
+namespace llvm {
+namespace symbolize {
+
+Expected<DILineInfo>
+LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+                              uint64_t ModuleOffset, StringRef DWPName) {
+  SymbolizableModule *Info;
+  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName))
+    Info = InfoOrErr.get();
+  else
+    return InfoOrErr.takeError();
+
+  // A null module means an error has already been reported. Return an empty
+  // result.
+  if (!Info)
+    return DILineInfo();
+
+  // If the user is giving us relative addresses, add the preferred base of the
+  // object to the offset before we do the query. It's what DIContext expects.
+  if (Opts.RelativeAddresses)
+    ModuleOffset += Info->getModulePreferredBase();
+
+  DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions,
+                                            Opts.UseSymbolTable);
+  if (Opts.Demangle)
+    LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
+  return LineInfo;
+}
+
+Expected<DIInliningInfo>
+LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
+                                     uint64_t ModuleOffset, StringRef DWPName) {
+  SymbolizableModule *Info;
+  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName, DWPName))
+    Info = InfoOrErr.get();
+  else
+    return InfoOrErr.takeError();
+
+  // A null module means an error has already been reported. Return an empty
+  // result.
+  if (!Info)
+    return DIInliningInfo();
+
+  // If the user is giving us relative addresses, add the preferred base of the
+  // object to the offset before we do the query. It's what DIContext expects.
+  if (Opts.RelativeAddresses)
+    ModuleOffset += Info->getModulePreferredBase();
+
+  DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
+      ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable);
+  if (Opts.Demangle) {
+    for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
+      auto *Frame = InlinedContext.getMutableFrame(i);
+      Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
+    }
+  }
+  return InlinedContext;
+}
+
+Expected<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+                                                 uint64_t ModuleOffset) {
+  SymbolizableModule *Info;
+  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
+    Info = InfoOrErr.get();
+  else
+    return InfoOrErr.takeError();
+
+  // A null module means an error has already been reported. Return an empty
+  // result.
+  if (!Info)
+    return DIGlobal();
+
+  // If the user is giving us relative addresses, add the preferred base of
+  // the object to the offset before we do the query. It's what DIContext
+  // expects.
+  if (Opts.RelativeAddresses)
+    ModuleOffset += Info->getModulePreferredBase();
+
+  DIGlobal Global = Info->symbolizeData(ModuleOffset);
+  if (Opts.Demangle)
+    Global.Name = DemangleName(Global.Name, Info);
+  return Global;
+}
+
+void LLVMSymbolizer::flush() {
+  ObjectForUBPathAndArch.clear();
+  BinaryForPath.clear();
+  ObjectPairForPathArch.clear();
+  Modules.clear();
+}
+
+namespace {
+
+// For Path="/path/to/foo" and Basename="foo" assume that debug info is in
+// /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
+// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
+// /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
+std::string getDarwinDWARFResourceForPath(
+    const std::string &Path, const std::string &Basename) {
+  SmallString<16> ResourceName = StringRef(Path);
+  if (sys::path::extension(Path) != ".dSYM") {
+    ResourceName += ".dSYM";
+  }
+  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
+  sys::path::append(ResourceName, Basename);
+  return ResourceName.str();
+}
+
+bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
+      MemoryBuffer::getFileOrSTDIN(Path);
+  if (!MB)
+    return false;
+  return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer());
+}
+
+bool findDebugBinary(const std::string &OrigPath,
+                     const std::string &DebuglinkName, uint32_t CRCHash,
+                     std::string &Result) {
+  std::string OrigRealPath = OrigPath;
+#if defined(HAVE_REALPATH)
+  if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
+    OrigRealPath = RP;
+    free(RP);
+  }
+#endif
+  SmallString<16> OrigDir(OrigRealPath);
+  llvm::sys::path::remove_filename(OrigDir);
+  SmallString<16> DebugPath = OrigDir;
+  // Try /path/to/original_binary/debuglink_name
+  llvm::sys::path::append(DebugPath, DebuglinkName);
+  if (checkFileCRC(DebugPath, CRCHash)) {
+    Result = DebugPath.str();
+    return true;
+  }
+  // Try /path/to/original_binary/.debug/debuglink_name
+  DebugPath = OrigDir;
+  llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
+  if (checkFileCRC(DebugPath, CRCHash)) {
+    Result = DebugPath.str();
+    return true;
+  }
+#if defined(__NetBSD__)
+  // Try /usr/libdata/debug/path/to/original_binary/debuglink_name
+  DebugPath = "/usr/libdata/debug";
+#else
+  // Try /usr/lib/debug/path/to/original_binary/debuglink_name
+  DebugPath = "/usr/lib/debug";
+#endif
+  llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
+                          DebuglinkName);
+  if (checkFileCRC(DebugPath, CRCHash)) {
+    Result = DebugPath.str();
+    return true;
+  }
+  return false;
+}
+
+bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
+                             uint32_t &CRCHash) {
+  if (!Obj)
+    return false;
+  for (const SectionRef &Section : Obj->sections()) {
+    StringRef Name;
+    Section.getName(Name);
+    Name = Name.substr(Name.find_first_not_of("._"));
+    if (Name == "gnu_debuglink") {
+      StringRef Data;
+      Section.getContents(Data);
+      DataExtractor DE(Data, Obj->isLittleEndian(), 0);
+      uint32_t Offset = 0;
+      if (const char *DebugNameStr = DE.getCStr(&Offset)) {
+        // 4-byte align the offset.
+        Offset = (Offset + 3) & ~0x3;
+        if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
+          DebugName = DebugNameStr;
+          CRCHash = DE.getU32(&Offset);
+          return true;
+        }
+      }
+      break;
+    }
+  }
+  return false;
+}
+
+bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
+                             const MachOObjectFile *Obj) {
+  ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
+  ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
+  if (dbg_uuid.empty() || bin_uuid.empty())
+    return false;
+  return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
+}
+
+} // end anonymous namespace
+
+ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
+    const MachOObjectFile *MachExeObj, const std::string &ArchName) {
+  // On Darwin we may find DWARF in separate object file in
+  // resource directory.
+  std::vector<std::string> DsymPaths;
+  StringRef Filename = sys::path::filename(ExePath);
+  DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename));
+  for (const auto &Path : Opts.DsymHints) {
+    DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
+  }
+  for (const auto &Path : DsymPaths) {
+    auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
+    if (!DbgObjOrErr) {
+      // Ignore errors, the file might not exist.
+      consumeError(DbgObjOrErr.takeError());
+      continue;
+    }
+    ObjectFile *DbgObj = DbgObjOrErr.get();
+    if (!DbgObj)
+      continue;
+    const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
+    if (!MachDbgObj)
+      continue;
+    if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
+      return DbgObj;
+  }
+  return nullptr;
+}
+
+ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
+                                                  const ObjectFile *Obj,
+                                                  const std::string &ArchName) {
+  std::string DebuglinkName;
+  uint32_t CRCHash;
+  std::string DebugBinaryPath;
+  if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
+    return nullptr;
+  if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
+    return nullptr;
+  auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
+  if (!DbgObjOrErr) {
+    // Ignore errors, the file might not exist.
+    consumeError(DbgObjOrErr.takeError());
+    return nullptr;
+  }
+  return DbgObjOrErr.get();
+}
+
+Expected<LLVMSymbolizer::ObjectPair>
+LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
+                                      const std::string &ArchName) {
+  const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
+  if (I != ObjectPairForPathArch.end()) {
+    return I->second;
+  }
+
+  auto ObjOrErr = getOrCreateObject(Path, ArchName);
+  if (!ObjOrErr) {
+    ObjectPairForPathArch.insert(std::make_pair(std::make_pair(Path, ArchName),
+                                                ObjectPair(nullptr, nullptr)));
+    return ObjOrErr.takeError();
+  }
+
+  ObjectFile *Obj = ObjOrErr.get();
+  assert(Obj != nullptr);
+  ObjectFile *DbgObj = nullptr;
+
+  if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
+    DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
+  if (!DbgObj)
+    DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
+  if (!DbgObj)
+    DbgObj = Obj;
+  ObjectPair Res = std::make_pair(Obj, DbgObj);
+  ObjectPairForPathArch.insert(
+      std::make_pair(std::make_pair(Path, ArchName), Res));
+  return Res;
+}
+
+Expected<ObjectFile *>
+LLVMSymbolizer::getOrCreateObject(const std::string &Path,
+                                  const std::string &ArchName) {
+  const auto &I = BinaryForPath.find(Path);
+  Binary *Bin = nullptr;
+  if (I == BinaryForPath.end()) {
+    Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
+    if (!BinOrErr) {
+      BinaryForPath.insert(std::make_pair(Path, OwningBinary<Binary>()));
+      return BinOrErr.takeError();
+    }
+    Bin = BinOrErr->getBinary();
+    BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get())));
+  } else {
+    Bin = I->second.getBinary();
+  }
+
+  if (!Bin)
+    return static_cast<ObjectFile *>(nullptr);
+
+  if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
+    const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
+    if (I != ObjectForUBPathAndArch.end()) {
+      return I->second.get();
+    }
+    Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
+        UB->getObjectForArch(ArchName);
+    if (!ObjOrErr) {
+      ObjectForUBPathAndArch.insert(std::make_pair(
+          std::make_pair(Path, ArchName), std::unique_ptr<ObjectFile>()));
+      return ObjOrErr.takeError();
+    }
+    ObjectFile *Res = ObjOrErr->get();
+    ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName),
+                                                 std::move(ObjOrErr.get())));
+    return Res;
+  }
+  if (Bin->isObject()) {
+    return cast<ObjectFile>(Bin);
+  }
+  return errorCodeToError(object_error::arch_not_found);
+}
+
+Expected<SymbolizableModule *>
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName,
+                                      StringRef DWPName) {
+  const auto &I = Modules.find(ModuleName);
+  if (I != Modules.end()) {
+    return I->second.get();
+  }
+  std::string BinaryName = ModuleName;
+  std::string ArchName = Opts.DefaultArch;
+  size_t ColonPos = ModuleName.find_last_of(':');
+  // Verify that substring after colon form a valid arch name.
+  if (ColonPos != std::string::npos) {
+    std::string ArchStr = ModuleName.substr(ColonPos + 1);
+    if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
+      BinaryName = ModuleName.substr(0, ColonPos);
+      ArchName = ArchStr;
+    }
+  }
+  auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
+  if (!ObjectsOrErr) {
+    // Failed to find valid object file.
+    Modules.insert(
+        std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>()));
+    return ObjectsOrErr.takeError();
+  }
+  ObjectPair Objects = ObjectsOrErr.get();
+
+  std::unique_ptr<DIContext> Context;
+  // If this is a COFF object containing PDB info, use a PDBContext to
+  // symbolize. Otherwise, use DWARF.
+  if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
+    const codeview::DebugInfo *DebugInfo;
+    StringRef PDBFileName;
+    auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
+    if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
+      using namespace pdb;
+      std::unique_ptr<IPDBSession> Session;
+      if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
+                                    Objects.first->getFileName(), Session)) {
+        Modules.insert(
+            std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>()));
+        // Return along the PDB filename to provide more context
+        return createFileError(PDBFileName, std::move(Err));
+      }
+      Context.reset(new PDBContext(*CoffObject, std::move(Session)));
+    }
+  }
+  if (!Context)
+    Context = DWARFContext::create(*Objects.second, nullptr,
+                                   DWARFContext::defaultErrorHandler, DWPName);
+  assert(Context);
+  auto InfoOrErr =
+      SymbolizableObjectFile::create(Objects.first, std::move(Context));
+  std::unique_ptr<SymbolizableModule> SymMod;
+  if (InfoOrErr)
+    SymMod = std::move(InfoOrErr.get());
+  auto InsertResult =
+      Modules.insert(std::make_pair(ModuleName, std::move(SymMod)));
+  assert(InsertResult.second);
+  if (auto EC = InfoOrErr.getError())
+    return errorCodeToError(EC);
+  return InsertResult.first->second.get();
+}
+
+namespace {
+
+// Undo these various manglings for Win32 extern "C" functions:
+// cdecl       - _foo
+// stdcall     - _foo@12
+// fastcall    - @foo@12
+// vectorcall  - foo@@12
+// These are all different linkage names for 'foo'.
+StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
+  // Remove any '_' or '@' prefix.
+  char Front = SymbolName.empty() ? '\0' : SymbolName[0];
+  if (Front == '_' || Front == '@')
+    SymbolName = SymbolName.drop_front();
+
+  // Remove any '@[0-9]+' suffix.
+  if (Front != '?') {
+    size_t AtPos = SymbolName.rfind('@');
+    if (AtPos != StringRef::npos &&
+        std::all_of(SymbolName.begin() + AtPos + 1, SymbolName.end(),
+                    [](char C) { return C >= '0' && C <= '9'; })) {
+      SymbolName = SymbolName.substr(0, AtPos);
+    }
+  }
+
+  // Remove any ending '@' for vectorcall.
+  if (SymbolName.endswith("@"))
+    SymbolName = SymbolName.drop_back();
+
+  return SymbolName;
+}
+
+} // end anonymous namespace
+
+std::string
+LLVMSymbolizer::DemangleName(const std::string &Name,
+                             const SymbolizableModule *DbiModuleDescriptor) {
+  // We can spoil names of symbols with C linkage, so use an heuristic
+  // approach to check if the name should be demangled.
+  if (Name.substr(0, 2) == "_Z") {
+    int status = 0;
+    char *DemangledName = itaniumDemangle(Name.c_str(), nullptr, nullptr, &status);
+    if (status != 0)
+      return Name;
+    std::string Result = DemangledName;
+    free(DemangledName);
+    return Result;
+  }
+
+#if defined(_MSC_VER)
+  if (!Name.empty() && Name.front() == '?') {
+    // Only do MSVC C++ demangling on symbols starting with '?'.
+    char DemangledName[1024] = {0};
+    DWORD result = ::UnDecorateSymbolName(
+        Name.c_str(), DemangledName, 1023,
+        UNDNAME_NO_ACCESS_SPECIFIERS |       // Strip public, private, protected
+            UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
+            UNDNAME_NO_THROW_SIGNATURES |    // Strip throw() specifications
+            UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
+            UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
+            UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
+    return (result == 0) ? Name : std::string(DemangledName);
+  }
+#endif
+  if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
+    return std::string(demanglePE32ExternCFunc(Name));
+  return Name;
+}
+
+} // namespace symbolize
+} // namespace llvm