[llvm] [DWARFLinkerParallel] Add support for -odr mode. (PR #68721)

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 22 15:17:26 PST 2023


https://github.com/avl-llvm updated https://github.com/llvm/llvm-project/pull/68721

>From 66b03b27346d02c747ea481cf0825c61b7aca525 Mon Sep 17 00:00:00 2001
From: Alexey Lapshin <a.v.lapshin at mail.ru>
Date: Mon, 9 Oct 2023 16:25:14 +0200
Subject: [PATCH] [DWARFLinkerParallel] Add support for -odr mode.

This patch is extracted from D96035, it adds support for the type
deduplication mode. With this patch DWARFLinkerParallel handles
--odr option. It also processes clang modules.
---
 .../AcceleratorRecordsSaver.cpp               | 295 ++++++
 .../AcceleratorRecordsSaver.h                 |  70 ++
 llvm/lib/DWARFLinkerParallel/ArrayList.h      |  26 +-
 llvm/lib/DWARFLinkerParallel/CMakeLists.txt   |   3 +
 .../DIEAttributeCloner.cpp                    | 297 +++---
 .../DWARFLinkerParallel/DIEAttributeCloner.h  |  73 +-
 llvm/lib/DWARFLinkerParallel/DIEGenerator.h   |  21 +-
 llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp  |   1 +
 .../DWARFLinkerCompileUnit.cpp                | 843 +++++++++++-------
 .../DWARFLinkerCompileUnit.h                  | 269 ++++--
 .../DWARFLinkerGlobalData.h                   |   1 +
 .../DWARFLinkerParallel/DWARFLinkerImpl.cpp   | 440 ++++++---
 .../lib/DWARFLinkerParallel/DWARFLinkerImpl.h |  58 +-
 .../DWARFLinkerTypeUnit.cpp                   | 391 ++++++++
 .../DWARFLinkerParallel/DWARFLinkerTypeUnit.h | 138 +++
 .../DWARFLinkerParallel/DWARFLinkerUnit.cpp   |  50 +-
 .../lib/DWARFLinkerParallel/DWARFLinkerUnit.h | 108 +--
 .../DebugLineSectionEmitter.h                 |   1 +
 .../DWARFLinkerParallel/DependencyTracker.cpp | 830 +++++++++++++----
 .../DWARFLinkerParallel/DependencyTracker.h   | 235 ++++-
 .../DWARFLinkerParallel/OutputSections.cpp    | 164 +++-
 llvm/lib/DWARFLinkerParallel/OutputSections.h |  93 +-
 .../SyntheticTypeNameBuilder.cpp              | 767 ++++++++++++++++
 .../SyntheticTypeNameBuilder.h                | 155 ++++
 llvm/lib/DWARFLinkerParallel/TypePool.h       | 177 ++++
 llvm/lib/DWARFLinkerParallel/Utils.h          |  40 +
 .../accel-imported-declarations.test          |  80 ++
 .../ARM/accel-imported-declarations.test      |  20 +-
 .../tools/dsymutil/ARM/dwarf5-addr-base.test  |  43 +-
 .../ARM/dwarf5-dwarf4-combination-macho.test  |  28 +-
 .../test/tools/dsymutil/ARM/dwarf5-macho.test |  20 +-
 .../ARM/dwarf5-str-offsets-base-strx.test     |  65 +-
 .../X86/DWARFLinkerParallel/dead-stripped.cpp |  67 ++
 .../X86/DWARFLinkerParallel/empty-CU.test     |   5 +
 .../inlined-static-variable.cpp               |  74 ++
 .../X86/DWARFLinkerParallel/keep-func.test    |  36 +
 .../odr-anon-namespace.cpp                    |  68 ++
 .../odr-fwd-declaration.test                  | 101 +++
 .../odr-fwd-declaration2.test                 | 131 +++
 .../odr-fwd-declaration3.test                 | 381 ++++++++
 .../odr-member-functions.cpp                  | 192 ++++
 .../odr-namespace-extension.test              | 157 ++++
 .../odr-nested-types1.test                    | 384 ++++++++
 .../odr-nested-types2.test                    | 374 ++++++++
 .../X86/DWARFLinkerParallel/odr-parents.test  | 238 +++++
 .../odr-predictable-output.test               | 117 +++
 .../odr-predictable-output2.test              | 120 +++
 .../odr-recursive-dependence.test             | 245 +++++
 .../X86/DWARFLinkerParallel/odr-string.test   | 180 ++++
 .../odr-template-parameters.test              | 201 +++++
 .../odr-two-units-in-single-file.test         | 205 +++++
 .../odr-types-in-subprogram1.test             | 431 +++++++++
 .../X86/DWARFLinkerParallel/odr-uniquing.cpp  | 475 ++++++++++
 .../tools/dsymutil/X86/Inputs/String/foo1.o   | Bin 0 -> 47448 bytes
 .../tools/dsymutil/X86/Inputs/String/foo2.o   | Bin 0 -> 56860 bytes
 .../tools/dsymutil/X86/Inputs/String/foo3.o   | Bin 0 -> 61128 bytes
 .../tools/dsymutil/X86/Inputs/String/main.o   | Bin 0 -> 50140 bytes
 .../test/tools/dsymutil/X86/dead-stripped.cpp |   5 -
 .../tools/dsymutil/X86/dummy-debug-map.map    |   4 +-
 .../tools/dsymutil/X86/dwarf5-rnglists.test   |   4 +-
 llvm/test/tools/dsymutil/X86/empty-CU.test    |   2 -
 .../dsymutil/X86/inlined-static-variable.cpp  |  18 +-
 llvm/test/tools/dsymutil/X86/keep-func.test   |   5 -
 .../X86/linker-llvm-union-fwd-decl.test       |  65 ++
 .../dsymutil/X86/location-expression.test     |   6 +-
 llvm/test/tools/dsymutil/X86/modules-empty.m  |   6 +-
 llvm/test/tools/dsymutil/X86/odr-uniquing.cpp |   2 +
 llvm/test/tools/dsymutil/X86/op-convert.test  |  12 +-
 .../tools/dsymutil/X86/union-fwd-decl.test    |   3 -
 .../ELF/X86/dwarf5-addresses.test             |   2 +-
 .../ELF/X86/dwarf5-rnglists.test              |  24 +-
 .../llvm-dwarfutil/ELF/X86/gc-default.test    |  18 +-
 .../gc-func-overlapping-address-ranges.test   |   4 +-
 .../llvm-dwarfutil/ELF/X86/gc-maxpc.test      |   8 +-
 .../llvm-dwarfutil/ELF/X86/gc-no-garbage.test |   4 +-
 .../gc-unit-overlapping-address-ranges.test   |   4 +-
 llvm/tools/dsymutil/DwarfLinkerForBinary.cpp  |   1 -
 77 files changed, 9062 insertions(+), 1119 deletions(-)
 create mode 100644 llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp
 create mode 100644 llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h
 create mode 100644 llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp
 create mode 100644 llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h
 create mode 100644 llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp
 create mode 100644 llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h
 create mode 100644 llvm/lib/DWARFLinkerParallel/TypePool.h
 create mode 100644 llvm/lib/DWARFLinkerParallel/Utils.h
 create mode 100644 llvm/test/tools/dsymutil/ARM/DWARFLinkerParallel/accel-imported-declarations.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/dead-stripped.cpp
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/empty-CU.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/inlined-static-variable.cpp
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/keep-func.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-anon-namespace.cpp
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration2.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration3.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-member-functions.cpp
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-namespace-extension.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types1.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types2.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-parents.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output2.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-recursive-dependence.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-string.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-template-parameters.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-two-units-in-single-file.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-types-in-subprogram1.test
 create mode 100644 llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-uniquing.cpp
 create mode 100644 llvm/test/tools/dsymutil/X86/Inputs/String/foo1.o
 create mode 100644 llvm/test/tools/dsymutil/X86/Inputs/String/foo2.o
 create mode 100644 llvm/test/tools/dsymutil/X86/Inputs/String/foo3.o
 create mode 100644 llvm/test/tools/dsymutil/X86/Inputs/String/main.o
 create mode 100644 llvm/test/tools/dsymutil/X86/linker-llvm-union-fwd-decl.test

diff --git a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp b/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp
new file mode 100644
index 000000000000000..5ec25cfe5fd26e1
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp
@@ -0,0 +1,295 @@
+//=== AcceleratorRecordsSaver.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AcceleratorRecordsSaver.h"
+#include "Utils.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/Support/DJB.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE,
+                                       int ChildRecurseDepth = 0) {
+  const char *Name = nullptr;
+  CompileUnit *CU = &InputCU;
+  std::optional<DWARFFormValue> RefVal;
+
+  if (Error Err = finiteLoop([&]() -> Expected<bool> {
+        if (const char *CurrentName = InputDIE.getName(DINameKind::ShortName))
+          Name = CurrentName;
+
+        if (!(RefVal = InputDIE.find(dwarf::DW_AT_specification)) &&
+            !(RefVal = InputDIE.find(dwarf::DW_AT_abstract_origin)))
+          return false;
+
+        if (!RefVal->isFormClass(DWARFFormValue::FC_Reference))
+          return false;
+
+        std::optional<UnitEntryPairTy> RefDie = CU->resolveDIEReference(
+            *RefVal, ResolveInterCUReferencesMode::Resolve);
+        if (!RefDie)
+          return false;
+
+        if (!RefDie->DieEntry)
+          return false;
+
+        CU = RefDie->CU;
+        InputDIE = RefDie->CU->getDIE(RefDie->DieEntry);
+        return true;
+      })) {
+    consumeError(std::move(Err));
+  }
+
+  if (!Name && InputDIE.getTag() == dwarf::DW_TAG_namespace)
+    Name = "(anonymous namespace)";
+
+  DWARFDie ParentDie = InputDIE.getParent();
+  if (!ParentDie.isValid() || ParentDie.getTag() == dwarf::DW_TAG_compile_unit)
+    return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
+
+  return djbHash(
+      (Name ? Name : ""),
+      djbHash((Name ? "::" : ""),
+              hashFullyQualifiedName(*CU, ParentDie, ++ChildRecurseDepth)));
+}
+
+void AcceleratorRecordsSaver::save(const DWARFDebugInfoEntry *InputDieEntry,
+                                   DIE *OutDIE, AttributesInfo &AttrInfo,
+                                   TypeEntry *TypeEntry) {
+  if (GlobalData.getOptions().AccelTables.empty())
+    return;
+
+  DWARFDie InputDIE = InUnit.getDIE(InputDieEntry);
+
+  // Look for short name recursively if short name is not known yet.
+  if (AttrInfo.Name == nullptr)
+    if (const char *ShortName = InputDIE.getShortName())
+      AttrInfo.Name = GlobalData.getStringPool().insert(ShortName).first;
+
+  switch (InputDieEntry->getTag()) {
+  case dwarf::DW_TAG_array_type:
+  case dwarf::DW_TAG_class_type:
+  case dwarf::DW_TAG_enumeration_type:
+  case dwarf::DW_TAG_pointer_type:
+  case dwarf::DW_TAG_reference_type:
+  case dwarf::DW_TAG_string_type:
+  case dwarf::DW_TAG_structure_type:
+  case dwarf::DW_TAG_subroutine_type:
+  case dwarf::DW_TAG_typedef:
+  case dwarf::DW_TAG_union_type:
+  case dwarf::DW_TAG_ptr_to_member_type:
+  case dwarf::DW_TAG_set_type:
+  case dwarf::DW_TAG_subrange_type:
+  case dwarf::DW_TAG_base_type:
+  case dwarf::DW_TAG_const_type:
+  case dwarf::DW_TAG_constant:
+  case dwarf::DW_TAG_file_type:
+  case dwarf::DW_TAG_namelist:
+  case dwarf::DW_TAG_packed_type:
+  case dwarf::DW_TAG_volatile_type:
+  case dwarf::DW_TAG_restrict_type:
+  case dwarf::DW_TAG_atomic_type:
+  case dwarf::DW_TAG_interface_type:
+  case dwarf::DW_TAG_unspecified_type:
+  case dwarf::DW_TAG_shared_type:
+  case dwarf::DW_TAG_immutable_type:
+  case dwarf::DW_TAG_rvalue_reference_type: {
+    if (!AttrInfo.IsDeclaration && AttrInfo.Name != nullptr &&
+        !AttrInfo.Name->getKey().empty()) {
+      uint32_t Hash = hashFullyQualifiedName(InUnit, InputDIE);
+
+      uint64_t RuntimeLang =
+          dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
+              .value_or(0);
+
+      bool ObjCClassIsImplementation =
+          (RuntimeLang == dwarf::DW_LANG_ObjC ||
+           RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
+          dwarf::toUnsigned(
+              InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
+              .value_or(0);
+
+      saveTypeRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(), Hash,
+                     ObjCClassIsImplementation, TypeEntry);
+    }
+  } break;
+  case dwarf::DW_TAG_namespace: {
+    if (AttrInfo.Name == nullptr)
+      AttrInfo.Name =
+          GlobalData.getStringPool().insert("(anonymous namespace)").first;
+
+    saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
+                        TypeEntry);
+  } break;
+  case dwarf::DW_TAG_imported_declaration: {
+    if (AttrInfo.Name != nullptr)
+      saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
+                          TypeEntry);
+  } break;
+  case dwarf::DW_TAG_compile_unit:
+  case dwarf::DW_TAG_lexical_block: {
+    // Nothing to do.
+  } break;
+  default:
+    if (TypeEntry)
+      // Do not store this kind of accelerator entries for type entries.
+      return;
+
+    if (AttrInfo.HasLiveAddress || AttrInfo.HasRanges) {
+      if (AttrInfo.Name)
+        saveNameRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
+                       InputDieEntry->getTag() ==
+                           dwarf::DW_TAG_inlined_subroutine);
+
+      // Look for mangled name recursively if mangled name is not known yet.
+      if (!AttrInfo.MangledName)
+        if (const char *LinkageName = InputDIE.getLinkageName())
+          AttrInfo.MangledName =
+              GlobalData.getStringPool().insert(LinkageName).first;
+
+      if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
+        saveNameRecord(AttrInfo.MangledName, OutDIE, InputDieEntry->getTag(),
+                       InputDieEntry->getTag() ==
+                           dwarf::DW_TAG_inlined_subroutine);
+
+      // Strip template parameters from the short name.
+      if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
+          (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
+        if (std::optional<StringRef> Name =
+                StripTemplateParameters(AttrInfo.Name->getKey())) {
+          StringEntry *NameWithoutTemplateParams =
+              GlobalData.getStringPool().insert(*Name).first;
+
+          saveNameRecord(NameWithoutTemplateParams, OutDIE,
+                         InputDieEntry->getTag(), true);
+        }
+      }
+
+      if (AttrInfo.Name)
+        saveObjC(InputDieEntry, OutDIE, AttrInfo);
+    }
+    break;
+  }
+}
+
+void AcceleratorRecordsSaver::saveObjC(const DWARFDebugInfoEntry *InputDieEntry,
+                                       DIE *OutDIE, AttributesInfo &AttrInfo) {
+  std::optional<ObjCSelectorNames> Names =
+      getObjCNamesIfSelector(AttrInfo.Name->getKey());
+  if (!Names)
+    return;
+
+  StringEntry *Selector =
+      GlobalData.getStringPool().insert(Names->Selector).first;
+  saveNameRecord(Selector, OutDIE, InputDieEntry->getTag(), true);
+  StringEntry *ClassName =
+      GlobalData.getStringPool().insert(Names->ClassName).first;
+  saveObjCNameRecord(ClassName, OutDIE, InputDieEntry->getTag());
+  if (Names->ClassNameNoCategory) {
+    StringEntry *ClassNameNoCategory =
+        GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
+    saveObjCNameRecord(ClassNameNoCategory, OutDIE, InputDieEntry->getTag());
+  }
+  if (Names->MethodNameNoCategory) {
+    StringEntry *MethodNameNoCategory =
+        GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
+    saveNameRecord(MethodNameNoCategory, OutDIE, InputDieEntry->getTag(), true);
+  }
+}
+
+void AcceleratorRecordsSaver::saveNameRecord(StringEntry *Name, DIE *OutDIE,
+                                             dwarf::Tag Tag,
+                                             bool AvoidForPubSections) {
+  DwarfUnit::AccelInfo Info;
+
+  Info.Type = DwarfUnit::AccelType::Name;
+  Info.String = Name;
+  Info.OutOffset = OutDIE->getOffset();
+  Info.Tag = Tag;
+  Info.AvoidForPubSections = AvoidForPubSections;
+
+  OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
+}
+void AcceleratorRecordsSaver::saveNamespaceRecord(StringEntry *Name,
+                                                  DIE *OutDIE, dwarf::Tag Tag,
+                                                  TypeEntry *TypeEntry) {
+  if (OutUnit.isCompileUnit()) {
+    assert(TypeEntry == nullptr);
+    DwarfUnit::AccelInfo Info;
+
+    Info.Type = DwarfUnit::AccelType::Namespace;
+    Info.String = Name;
+    Info.OutOffset = OutDIE->getOffset();
+    Info.Tag = Tag;
+
+    OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
+    return;
+  }
+
+  assert(TypeEntry != nullptr);
+  TypeUnit::TypeUnitAccelInfo Info;
+  Info.Type = DwarfUnit::AccelType::Namespace;
+  Info.String = Name;
+  Info.OutOffset = 0xbaddef;
+  Info.Tag = Tag;
+  Info.OutDIE = OutDIE;
+  Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
+
+  OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
+}
+
+void AcceleratorRecordsSaver::saveObjCNameRecord(StringEntry *Name, DIE *OutDIE,
+                                                 dwarf::Tag Tag) {
+  DwarfUnit::AccelInfo Info;
+
+  Info.Type = DwarfUnit::AccelType::ObjC;
+  Info.String = Name;
+  Info.OutOffset = OutDIE->getOffset();
+  Info.Tag = Tag;
+  Info.AvoidForPubSections = true;
+
+  OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
+}
+
+void AcceleratorRecordsSaver::saveTypeRecord(StringEntry *Name, DIE *OutDIE,
+                                             dwarf::Tag Tag,
+                                             uint32_t QualifiedNameHash,
+                                             bool ObjcClassImplementation,
+                                             TypeEntry *TypeEntry) {
+  if (OutUnit.isCompileUnit()) {
+    assert(TypeEntry == nullptr);
+    DwarfUnit::AccelInfo Info;
+
+    Info.Type = DwarfUnit::AccelType::Type;
+    Info.String = Name;
+    Info.OutOffset = OutDIE->getOffset();
+    Info.Tag = Tag;
+    Info.QualifiedNameHash = QualifiedNameHash;
+    Info.ObjcClassImplementation = ObjcClassImplementation;
+
+    OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
+    return;
+  }
+
+  assert(TypeEntry != nullptr);
+  TypeUnit::TypeUnitAccelInfo Info;
+
+  Info.Type = DwarfUnit::AccelType::Type;
+  Info.String = Name;
+  Info.OutOffset = 0xbaddef;
+  Info.Tag = Tag;
+  Info.QualifiedNameHash = QualifiedNameHash;
+  Info.ObjcClassImplementation = ObjcClassImplementation;
+  Info.OutDIE = OutDIE;
+  Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
+  OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
+}
+
+} // end of namespace dwarflinker_parallel
+} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h b/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h
new file mode 100644
index 000000000000000..5e7f4d0c3166fd1
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h
@@ -0,0 +1,70 @@
+//===- AcceleratorRecordsSaver.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
+#define LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
+
+#include "DIEAttributeCloner.h"
+#include "DWARFLinkerCompileUnit.h"
+#include "DWARFLinkerGlobalData.h"
+#include "DWARFLinkerTypeUnit.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+/// This class helps to store information for accelerator entries.
+/// It prepares accelerator info for the certain DIE and store it inside
+/// OutUnit.
+class AcceleratorRecordsSaver {
+public:
+  AcceleratorRecordsSaver(LinkingGlobalData &GlobalData, CompileUnit &InUnit,
+                          CompileUnit *OutUnit)
+      : AcceleratorRecordsSaver(GlobalData, InUnit,
+                                CompileUnit::OutputUnitVariantPtr(OutUnit)) {}
+
+  AcceleratorRecordsSaver(LinkingGlobalData &GlobalData, CompileUnit &InUnit,
+                          TypeUnit *OutUnit)
+      : AcceleratorRecordsSaver(GlobalData, InUnit,
+                                CompileUnit::OutputUnitVariantPtr(OutUnit)) {}
+
+  /// Save accelerator info for the specified \p OutDIE inside OutUnit.
+  /// Side effects: set attributes in \p AttrInfo.
+  void save(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE,
+            AttributesInfo &AttrInfo, TypeEntry *TypeEntry);
+
+protected:
+  AcceleratorRecordsSaver(LinkingGlobalData &GlobalData, CompileUnit &InUnit,
+                          CompileUnit::OutputUnitVariantPtr OutUnit)
+      : GlobalData(GlobalData), InUnit(InUnit), OutUnit(OutUnit) {}
+
+  void saveObjC(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE,
+                AttributesInfo &AttrInfo);
+
+  void saveNameRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag,
+                      bool AvoidForPubSections);
+  void saveNamespaceRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag,
+                           TypeEntry *TypeEntry);
+  void saveObjCNameRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag);
+  void saveTypeRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag,
+                      uint32_t QualifiedNameHash, bool ObjcClassImplementation,
+                      TypeEntry *TypeEntry);
+
+  /// Global linking data.
+  LinkingGlobalData &GlobalData;
+
+  /// Comiple unit corresponding to input DWARF.
+  CompileUnit &InUnit;
+
+  /// Compile unit or Artificial type unit corresponding to the output DWARF.
+  CompileUnit::OutputUnitVariantPtr OutUnit;
+};
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
diff --git a/llvm/lib/DWARFLinkerParallel/ArrayList.h b/llvm/lib/DWARFLinkerParallel/ArrayList.h
index 58d550982c8dfc0..def83f91bc6f319 100644
--- a/llvm/lib/DWARFLinkerParallel/ArrayList.h
+++ b/llvm/lib/DWARFLinkerParallel/ArrayList.h
@@ -21,6 +21,9 @@ namespace dwarflinker_parallel {
 /// Method add() can be called asynchronously.
 template <typename T, size_t ItemsGroupSize = 512> class ArrayList {
 public:
+  ArrayList(parallel::PerThreadBumpPtrAllocator *Allocator)
+      : Allocator(Allocator) {}
+
   /// Add specified \p Item to the list.
   T &add(const T &Item) {
     assert(Allocator);
@@ -73,8 +76,27 @@ template <typename T, size_t ItemsGroupSize = 512> class ArrayList {
     LastGroup = nullptr;
   }
 
-  void setAllocator(parallel::PerThreadBumpPtrAllocator *Allocator) {
-    this->Allocator = Allocator;
+  void sort(function_ref<bool(const T &LHS, const T &RHS)> Comparator) {
+    SmallVector<T> SortedItems;
+    forEach([&](T &Item) { SortedItems.push_back(Item); });
+
+    if (SortedItems.size()) {
+      std::sort(SortedItems.begin(), SortedItems.end(), Comparator);
+
+      size_t SortedItemIdx = 0;
+      forEach([&](T &Item) { Item = SortedItems[SortedItemIdx++]; });
+      assert(SortedItemIdx == SortedItems.size());
+    }
+  }
+
+  size_t size() {
+    size_t Result = 0;
+
+    for (ItemsGroup *CurGroup = GroupsHead; CurGroup != nullptr;
+         CurGroup = CurGroup->Next)
+      Result += CurGroup->getItemsCount();
+
+    return Result;
   }
 
 protected:
diff --git a/llvm/lib/DWARFLinkerParallel/CMakeLists.txt b/llvm/lib/DWARFLinkerParallel/CMakeLists.txt
index d321ecf8d5ce847..b0f0b3910e586ab 100644
--- a/llvm/lib/DWARFLinkerParallel/CMakeLists.txt
+++ b/llvm/lib/DWARFLinkerParallel/CMakeLists.txt
@@ -1,14 +1,17 @@
 add_llvm_component_library(LLVMDWARFLinkerParallel
+  AcceleratorRecordsSaver.cpp
   DependencyTracker.cpp
   DIEAttributeCloner.cpp
   DWARFEmitterImpl.cpp
   DWARFFile.cpp
   DWARFLinker.cpp
   DWARFLinkerCompileUnit.cpp
+  DWARFLinkerTypeUnit.cpp
   DWARFLinkerImpl.cpp
   DWARFLinkerUnit.cpp
   OutputSections.cpp
   StringPool.cpp
+  SyntheticTypeNameBuilder.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinkerParallel
diff --git a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp b/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp
index d05fd8d61b85743..81fc57f7cabbb79 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp
@@ -13,18 +13,16 @@ namespace llvm {
 namespace dwarflinker_parallel {
 
 void DIEAttributeCloner::clone() {
-  DWARFUnit &U = CU.getOrigUnit();
-
   // Extract and clone every attribute.
-  DWARFDataExtractor Data = U.getDebugInfoExtractor();
+  DWARFDataExtractor Data = InUnit.getOrigUnit().getDebugInfoExtractor();
 
   uint64_t Offset = InputDieEntry->getOffset();
   // Point to the next DIE (generally there is always at least a NULL
   // entry after the current one). If this is a lone
   // DW_TAG_compile_unit without any children, point to the next unit.
-  uint64_t NextOffset = (InputDIEIdx + 1 < U.getNumDIEs())
-                            ? U.getDIEAtIndex(InputDIEIdx + 1).getOffset()
-                            : U.getNextUnitOffset();
+  uint64_t NextOffset = (InputDIEIdx + 1 < InUnit.getOrigUnit().getNumDIEs())
+                            ? InUnit.getDIEAtIndex(InputDIEIdx + 1).getOffset()
+                            : InUnit.getOrigUnit().getNextUnitOffset();
 
   // We could copy the data only if we need to apply a relocation to it. After
   // testing, it seems there is no performance downside to doing the copy
@@ -34,8 +32,8 @@ void DIEAttributeCloner::clone() {
       DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
 
   // Modify the copy with relocated addresses.
-  CU.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,
-                                                   Data.isLittleEndian());
+  InUnit.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,
+                                                       Data.isLittleEndian());
 
   // Reset the Offset to 0 as we will be working on the local copy of
   // the data.
@@ -45,17 +43,18 @@ void DIEAttributeCloner::clone() {
   Offset += getULEB128Size(Abbrev->getCode());
 
   // Set current output offset.
-  AttrOutOffset = OutDIE->getOffset();
+  AttrOutOffset = OutUnit.isCompileUnit() ? OutDIE->getOffset() : 0;
   for (const auto &AttrSpec : Abbrev->attributes()) {
     // Check whether current attribute should be skipped.
     if (shouldSkipAttribute(AttrSpec)) {
       DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
-                                U.getFormParams());
+                                InUnit.getFormParams());
       continue;
     }
 
     DWARFFormValue Val = AttrSpec.getFormValue();
-    Val.extractValue(Data, &Offset, U.getFormParams(), &U);
+    Val.extractValue(Data, &Offset, InUnit.getFormParams(),
+                     &InUnit.getOrigUnit());
 
     // Clone current attribute.
     switch (AttrSpec.Form) {
@@ -107,10 +106,10 @@ void DIEAttributeCloner::clone() {
       AttrOutOffset += cloneAddressAttr(Val, AttrSpec);
       break;
     default:
-      CU.warn("unsupported attribute form " +
-                  dwarf::FormEncodingString(AttrSpec.Form) +
-                  " in DieAttributeCloner::clone(). Dropping.",
-              InputDieEntry);
+      InUnit.warn("unsupported attribute form " +
+                      dwarf::FormEncodingString(AttrSpec.Form) +
+                      " in DieAttributeCloner::clone(). Dropping.",
+                  InputDieEntry);
     }
   }
 
@@ -118,19 +117,20 @@ void DIEAttributeCloner::clone() {
   // Check if original compile unit already has DW_AT_str_offsets_base
   // attribute.
   if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
-      CU.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {
+      InUnit.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {
     DebugInfoOutputSection.notePatchWithOffsetUpdate(
-        DebugOffsetPatch{
-            AttrOutOffset,
-            &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets),
-            true},
+        DebugOffsetPatch{AttrOutOffset,
+                         &OutUnit->getOrCreateSectionDescriptor(
+                             DebugSectionKind::DebugStrOffsets),
+                         true},
         PatchesOffsets);
 
-    AttrOutOffset += Generator
-                         .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
-                                             dwarf::DW_FORM_sec_offset,
-                                             CU.getDebugStrOffsetsHeaderSize())
-                         .second;
+    AttrOutOffset +=
+        Generator
+            .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
+                                dwarf::DW_FORM_sec_offset,
+                                OutUnit->getDebugStrOffsetsHeaderSize())
+            .second;
   }
 }
 
@@ -142,28 +142,28 @@ bool DIEAttributeCloner::shouldSkipAttribute(
   case dwarf::DW_AT_low_pc:
   case dwarf::DW_AT_high_pc:
   case dwarf::DW_AT_ranges:
-    if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
+    if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
       return false;
 
     // Skip address attribute if we are in function scope and function does not
     // reference live address.
-    return CU.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
+    return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
            !FuncAddressAdjustment.has_value();
   case dwarf::DW_AT_rnglists_base:
     // In case !Update the .debug_addr table is not generated/preserved.
     // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
     // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
     // DW_AT_rnglists_base is removed.
-    return !CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
+    return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
   case dwarf::DW_AT_loclists_base:
     // In case !Update the .debug_addr table is not generated/preserved.
     // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
     // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
     // DW_AT_loclists_base is removed.
-    return !CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
+    return !InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
   case dwarf::DW_AT_location:
   case dwarf::DW_AT_frame_base:
-    if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
+    if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
       return false;
 
     // When location expression contains an address: skip this attribute
@@ -173,7 +173,7 @@ bool DIEAttributeCloner::shouldSkipAttribute(
 
     // Skip location attribute if we are in function scope and function does not
     // reference live address.
-    return CU.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
+    return InUnit.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
            !FuncAddressAdjustment.has_value();
   }
 }
@@ -183,19 +183,12 @@ size_t DIEAttributeCloner::cloneStringAttr(
     const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
   std::optional<const char *> String = dwarf::toString(Val);
   if (!String) {
-    CU.warn("cann't read string attribute.");
+    InUnit.warn("cann't read string attribute.");
     return 0;
   }
 
   StringEntry *StringInPool =
-      CU.getGlobalData().getStringPool().insert(*String).first;
-  if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
-    DebugInfoOutputSection.notePatchWithOffsetUpdate(
-        DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
-    return Generator
-        .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
-        .second;
-  }
+      InUnit.getGlobalData().getStringPool().insert(*String).first;
 
   // Update attributes info.
   if (AttrSpec.Attr == dwarf::DW_AT_name)
@@ -204,9 +197,29 @@ size_t DIEAttributeCloner::cloneStringAttr(
            AttrSpec.Attr == dwarf::DW_AT_linkage_name)
     AttrInfo.MangledName = StringInPool;
 
-  if (CU.getVersion() < 5) {
-    DebugInfoOutputSection.notePatchWithOffsetUpdate(
-        DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
+  if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
+    if (OutUnit.isTypeUnit()) {
+      DebugInfoOutputSection.notePatch(DebugTypeLineStrPatch{
+          AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
+          StringInPool});
+    } else {
+      DebugInfoOutputSection.notePatchWithOffsetUpdate(
+          DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
+    }
+    return Generator
+        .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
+        .second;
+  }
+
+  if (Use_DW_FORM_strp) {
+    if (OutUnit.isTypeUnit()) {
+      DebugInfoOutputSection.notePatch(
+          DebugTypeStrPatch{AttrOutOffset, OutDIE,
+                            InUnit.getDieTypeEntry(InputDIEIdx), StringInPool});
+    } else {
+      DebugInfoOutputSection.notePatchWithOffsetUpdate(
+          DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
+    }
 
     return Generator
         .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
@@ -215,7 +228,7 @@ size_t DIEAttributeCloner::cloneStringAttr(
 
   return Generator
       .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
-                                 CU.getDebugStrIndex(StringInPool))
+                                 OutUnit->getDebugStrIndex(StringInPool))
       .second;
 }
 
@@ -225,22 +238,48 @@ size_t DIEAttributeCloner::cloneDieRefAttr(
   if (AttrSpec.Attr == dwarf::DW_AT_sibling)
     return 0;
 
-  std::optional<std::pair<CompileUnit *, uint32_t>> RefDiePair =
-      CU.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);
-  if (!RefDiePair) {
+  std::optional<UnitEntryPairTy> RefDiePair =
+      InUnit.resolveDIEReference(Val, ResolveInterCUReferencesMode::Resolve);
+  if (!RefDiePair || !RefDiePair->DieEntry) {
     // If the referenced DIE is not found,  drop the attribute.
-    CU.warn("cann't find referenced DIE.", InputDieEntry);
+    InUnit.warn("cann't find referenced DIE.", InputDieEntry);
     return 0;
   }
-  assert(RefDiePair->first->getStage() >= CompileUnit::Stage::Loaded);
-  assert(RefDiePair->second != 0);
+
+  TypeEntry *RefTypeName = nullptr;
+  const CompileUnit::DIEInfo &RefDIEInfo =
+      RefDiePair->CU->getDIEInfo(RefDiePair->DieEntry);
+  if (RefDIEInfo.needToPlaceInTypeTable())
+    RefTypeName = RefDiePair->CU->getDieTypeEntry(RefDiePair->DieEntry);
+
+  if (OutUnit.isTypeUnit()) {
+    assert(RefTypeName && "Type name for referenced DIE is not set");
+    assert(InUnit.getDieTypeEntry(InputDIEIdx) &&
+           "Type name for DIE is not set");
+
+    DebugInfoOutputSection.notePatch(DebugType2TypeDieRefPatch{
+        AttrOutOffset, OutDIE, InUnit.getDieTypeEntry(InputDIEIdx),
+        RefTypeName});
+
+    return Generator
+        .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref4, 0xBADDEF)
+        .second;
+  }
+
+  if (RefTypeName) {
+    DebugInfoOutputSection.notePatchWithOffsetUpdate(
+        DebugDieTypeRefPatch{AttrOutOffset, RefTypeName}, PatchesOffsets);
+
+    return Generator
+        .addScalarAttribute(AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 0xBADDEF)
+        .second;
+  }
 
   // Get output offset for referenced DIE.
-  uint64_t OutDieOffset =
-      RefDiePair->first->getDieOutOffset(RefDiePair->second);
+  uint64_t OutDieOffset = RefDiePair->CU->getDieOutOffset(RefDiePair->DieEntry);
 
   // Examine whether referenced DIE is in current compile unit.
-  bool IsLocal = CU.getUniqueID() == RefDiePair->first->getUniqueID();
+  bool IsLocal = OutUnit->getUniqueID() == RefDiePair->CU->getUniqueID();
 
   // Set attribute form basing on the kind of referenced DIE(local or not?).
   dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
@@ -254,8 +293,9 @@ size_t DIEAttributeCloner::cloneDieRefAttr(
   // If offset value is not known at this point then create patch for the
   // reference value and write dummy value into the attribute.
   DebugInfoOutputSection.notePatchWithOffsetUpdate(
-      DebugDieRefPatch{AttrOutOffset, &CU, RefDiePair->first,
-                       RefDiePair->second},
+      DebugDieRefPatch{AttrOutOffset, OutUnit.getAsCompileUnit(),
+                       RefDiePair->CU,
+                       RefDiePair->CU->getDIEIndex(RefDiePair->DieEntry)},
       PatchesOffsets);
   return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
 }
@@ -267,41 +307,47 @@ size_t DIEAttributeCloner::cloneScalarAttr(
   // Create patches for attribute referencing other non invariant section.
   // Invariant section could not be updated here as this section and
   // reference to it do not change value in case --update.
-  if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
+  switch (AttrSpec.Attr) {
+  case dwarf::DW_AT_macro_info: {
     if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
       const DWARFDebugMacro *Macro =
-          CU.getContaingFile().Dwarf->getDebugMacinfo();
+          InUnit.getContaingFile().Dwarf->getDebugMacinfo();
       if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
         return 0;
 
       DebugInfoOutputSection.notePatchWithOffsetUpdate(
-          DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
-                                              DebugSectionKind::DebugMacinfo)},
+          DebugOffsetPatch{AttrOutOffset,
+                           &OutUnit->getOrCreateSectionDescriptor(
+                               DebugSectionKind::DebugMacinfo)},
           PatchesOffsets);
     }
-  } else if (AttrSpec.Attr == dwarf::DW_AT_macros) {
+  } break;
+  case dwarf::DW_AT_macros: {
     if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
       const DWARFDebugMacro *Macro =
-          CU.getContaingFile().Dwarf->getDebugMacro();
+          InUnit.getContaingFile().Dwarf->getDebugMacro();
       if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
         return 0;
 
       DebugInfoOutputSection.notePatchWithOffsetUpdate(
-          DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
-                                              DebugSectionKind::DebugMacro)},
+          DebugOffsetPatch{AttrOutOffset,
+                           &OutUnit->getOrCreateSectionDescriptor(
+                               DebugSectionKind::DebugMacro)},
           PatchesOffsets);
     }
-  } else if (AttrSpec.Attr == dwarf::DW_AT_stmt_list) {
+  } break;
+  case dwarf::DW_AT_stmt_list: {
     DebugInfoOutputSection.notePatchWithOffsetUpdate(
-        DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
+        DebugOffsetPatch{AttrOutOffset, &OutUnit->getOrCreateSectionDescriptor(
                                             DebugSectionKind::DebugLine)},
         PatchesOffsets);
-  } else if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
+  } break;
+  case dwarf::DW_AT_str_offsets_base: {
     DebugInfoOutputSection.notePatchWithOffsetUpdate(
-        DebugOffsetPatch{
-            AttrOutOffset,
-            &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets),
-            true},
+        DebugOffsetPatch{AttrOutOffset,
+                         &OutUnit->getOrCreateSectionDescriptor(
+                             DebugSectionKind::DebugStrOffsets),
+                         true},
         PatchesOffsets);
 
     // Use size of .debug_str_offsets header as attribute value. The offset
@@ -309,9 +355,36 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     AttrInfo.HasStringOffsetBaseAttr = true;
     return Generator
         .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
-                            CU.getDebugStrOffsetsHeaderSize())
+                            OutUnit->getDebugStrOffsetsHeaderSize())
         .second;
-  }
+  } break;
+  case dwarf::DW_AT_decl_file: {
+    // Value of DW_AT_decl_file may exceed original form. Longer
+    // form can affect offsets to the following attributes. To not
+    // update offsets of the following attributes we always remove
+    // original DW_AT_decl_file and attach it to the last position
+    // later.
+    if (OutUnit.isTypeUnit()) {
+      if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
+              InUnit.getDirAndFilenameFromLineTable(Val))
+        DebugInfoOutputSection.notePatch(DebugTypeDeclFilePatch{
+            OutDIE,
+            InUnit.getDieTypeEntry(InputDIEIdx),
+            OutUnit->getGlobalData()
+                .getStringPool()
+                .insert(DirAndFilename->first)
+                .first,
+            OutUnit->getGlobalData()
+                .getStringPool()
+                .insert(DirAndFilename->second)
+                .first,
+        });
+      return 0;
+    }
+  } break;
+  default: {
+  } break;
+  };
 
   uint64_t Value;
   if (AttrSpec.Attr == dwarf::DW_AT_const_value &&
@@ -319,7 +392,7 @@ size_t DIEAttributeCloner::cloneScalarAttr(
        InputDieEntry->getTag() == dwarf::DW_TAG_constant))
     AttrInfo.HasLiveAddress = true;
 
-  if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly) {
+  if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly) {
     if (auto OptionalValue = Val.getAsUnsignedConstant())
       Value = *OptionalValue;
     else if (auto OptionalValue = Val.getAsSignedConstant())
@@ -327,8 +400,8 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     else if (auto OptionalValue = Val.getAsSectionOffset())
       Value = *OptionalValue;
     else {
-      CU.warn("unsupported scalar attribute form. Dropping attribute.",
-              InputDieEntry);
+      InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
+                  InputDieEntry);
       return 0;
     }
 
@@ -350,12 +423,13 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     // to DW_FORM_sec_offset here.
     std::optional<uint64_t> Index = Val.getAsSectionOffset();
     if (!Index) {
-      CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
+      InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
       return 0;
     }
-    std::optional<uint64_t> Offset = CU.getOrigUnit().getRnglistOffset(*Index);
+    std::optional<uint64_t> Offset =
+        InUnit.getOrigUnit().getRnglistOffset(*Index);
     if (!Offset) {
-      CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
+      InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
       return 0;
     }
 
@@ -367,12 +441,13 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     // to DW_FORM_sec_offset here.
     std::optional<uint64_t> Index = Val.getAsSectionOffset();
     if (!Index) {
-      CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
+      InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
       return 0;
     }
-    std::optional<uint64_t> Offset = CU.getOrigUnit().getLoclistOffset(*Index);
+    std::optional<uint64_t> Offset =
+        InUnit.getOrigUnit().getLoclistOffset(*Index);
     if (!Offset) {
-      CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
+      InUnit.warn("cann't read the attribute. Dropping.", InputDieEntry);
       return 0;
     }
 
@@ -380,11 +455,14 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     ResultingForm = dwarf::DW_FORM_sec_offset;
   } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
              InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
-    std::optional<uint64_t> LowPC = CU.getLowPc();
+    if (!OutUnit.isCompileUnit())
+      return 0;
+
+    std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc();
     if (!LowPC)
       return 0;
     // Dwarf >= 4 high_pc is an size, not an address.
-    Value = CU.getHighPc() - *LowPC;
+    Value = OutUnit.getAsCompileUnit()->getHighPc() - *LowPC;
   } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
     Value = *Val.getAsSectionOffset();
   else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
@@ -392,8 +470,8 @@ size_t DIEAttributeCloner::cloneScalarAttr(
   else if (auto OptionalValue = Val.getAsUnsignedConstant())
     Value = *OptionalValue;
   else {
-    CU.warn("unsupported scalar attribute form. Dropping attribute.",
-            InputDieEntry);
+    InUnit.warn("unsupported scalar attribute form. Dropping attribute.",
+                InputDieEntry);
     return 0;
   }
 
@@ -408,7 +486,7 @@ size_t DIEAttributeCloner::cloneScalarAttr(
   } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
              dwarf::doesFormBelongToClass(AttrSpec.Form,
                                           DWARFFormValue::FC_SectionOffset,
-                                          CU.getOrigUnit().getVersion())) {
+                                          InUnit.getOrigUnit().getVersion())) {
     int64_t AddrAdjustmentValue = 0;
     if (VarAddressAdjustment)
       AddrAdjustmentValue = *VarAddressAdjustment;
@@ -422,7 +500,7 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     DebugInfoOutputSection.notePatchWithOffsetUpdate(
         DebugOffsetPatch{
             AttrOutOffset,
-            &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
+            &OutUnit->getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
             true},
         PatchesOffsets);
 
@@ -430,7 +508,7 @@ size_t DIEAttributeCloner::cloneScalarAttr(
     // .debug_addr would be added later while patching.
     return Generator
         .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
-                            CU.getDebugAddrHeaderSize())
+                            OutUnit->getDebugAddrHeaderSize())
         .second;
   } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
     AttrInfo.IsDeclaration = true;
@@ -443,6 +521,9 @@ size_t DIEAttributeCloner::cloneBlockAttr(
     const DWARFFormValue &Val,
     const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
 
+  if (OutUnit.isTypeUnit())
+    return 0;
+
   size_t NumberOfPatchesAtStart = PatchesOffsets.size();
 
   // If the block is a DWARF Expression, clone it into the temporary
@@ -452,15 +533,14 @@ size_t DIEAttributeCloner::cloneBlockAttr(
   if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&
       (Val.isFormClass(DWARFFormValue::FC_Block) ||
        Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
-    DWARFUnit &OrigUnit = CU.getOrigUnit();
     DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
-                       OrigUnit.isLittleEndian(),
-                       OrigUnit.getAddressByteSize());
-    DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
-                         OrigUnit.getFormParams().Format);
+                       InUnit.getOrigUnit().isLittleEndian(),
+                       InUnit.getOrigUnit().getAddressByteSize());
+    DWARFExpression Expr(Data, InUnit.getOrigUnit().getAddressByteSize(),
+                         InUnit.getFormParams().Format);
 
-    CU.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
-                              VarAddressAdjustment, PatchesOffsets);
+    InUnit.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
+                                  VarAddressAdjustment, PatchesOffsets);
     Bytes = Buffer;
   }
 
@@ -491,7 +571,7 @@ size_t DIEAttributeCloner::cloneBlockAttr(
   if (HasLocationExpressionAddress)
     AttrInfo.HasLiveAddress =
         VarAddressAdjustment.has_value() ||
-        CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
+        InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly;
 
   return FinalAttributeSize;
 }
@@ -502,11 +582,14 @@ size_t DIEAttributeCloner::cloneAddressAttr(
   if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
     AttrInfo.HasLiveAddress = true;
 
-  if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
+  if (InUnit.getGlobalData().getOptions().UpdateIndexTablesOnly)
     return Generator
         .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
         .second;
 
+  if (OutUnit.isTypeUnit())
+    return 0;
+
   // Cloned Die may have address attributes relocated to a
   // totally unrelated value. This can happen:
   //   - If high_pc is an address (Dwarf version == 2), then it might have been
@@ -520,25 +603,25 @@ size_t DIEAttributeCloner::cloneAddressAttr(
   //  Info.PCOffset here.
 
   std::optional<DWARFFormValue> AddrAttribute =
-      CU.find(InputDieEntry, AttrSpec.Attr);
+      InUnit.find(InputDieEntry, AttrSpec.Attr);
   if (!AddrAttribute)
     llvm_unreachable("Cann't find attribute");
 
   std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
   if (!Addr) {
-    CU.warn("cann't read address attribute value.");
+    InUnit.warn("cann't read address attribute value.");
     return 0;
   }
 
   if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
       AttrSpec.Attr == dwarf::DW_AT_low_pc) {
-    if (std::optional<uint64_t> LowPC = CU.getLowPc())
+    if (std::optional<uint64_t> LowPC = OutUnit.getAsCompileUnit()->getLowPc())
       Addr = *LowPC;
     else
       return 0;
   } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
              AttrSpec.Attr == dwarf::DW_AT_high_pc) {
-    if (uint64_t HighPc = CU.getHighPc())
+    if (uint64_t HighPc = OutUnit.getAsCompileUnit()->getHighPc())
       Addr = HighPc;
     else
       return 0;
@@ -556,20 +639,14 @@ size_t DIEAttributeCloner::cloneAddressAttr(
 
   return Generator
       .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
-                          CU.getDebugAddrIndex(*Addr))
+                          OutUnit.getAsCompileUnit()->getDebugAddrIndex(*Addr))
       .second;
 }
 
 unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
-  size_t SizeOfAbbreviationNumber =
-      Generator.finalizeAbbreviations(HasChildrenToClone);
-
-  // We need to update patches offsets after we know the size of the
-  // abbreviation number.
-  updatePatchesWithSizeOfAbbreviationNumber(SizeOfAbbreviationNumber);
-
   // Add the size of the abbreviation number to the output offset.
-  AttrOutOffset += SizeOfAbbreviationNumber;
+  AttrOutOffset +=
+      Generator.finalizeAbbreviations(HasChildrenToClone, &PatchesOffsets);
 
   return AttrOutOffset;
 }
diff --git a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h b/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h
index 74d80e131480171..e18c0a15cefc63d 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h
+++ b/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h
@@ -13,6 +13,7 @@
 #include "DIEGenerator.h"
 #include "DWARFLinkerCompileUnit.h"
 #include "DWARFLinkerGlobalData.h"
+#include "DWARFLinkerTypeUnit.h"
 
 namespace llvm {
 namespace dwarflinker_parallel {
@@ -44,20 +45,28 @@ struct AttributesInfo {
 /// attribute, adds cloned attribute to the output DIE.
 class DIEAttributeCloner {
 public:
-  DIEAttributeCloner(DIE *OutDIE, CompileUnit &CU,
+  DIEAttributeCloner(DIE *OutDIE, CompileUnit &InUnit, CompileUnit *OutUnit,
                      const DWARFDebugInfoEntry *InputDieEntry,
                      DIEGenerator &Generator,
                      std::optional<int64_t> FuncAddressAdjustment,
                      std::optional<int64_t> VarAddressAdjustment,
                      bool HasLocationExpressionAddress)
-      : OutDIE(OutDIE), CU(CU),
-        DebugInfoOutputSection(
-            CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)),
-        InputDieEntry(InputDieEntry), Generator(Generator),
-        FuncAddressAdjustment(FuncAddressAdjustment),
-        VarAddressAdjustment(VarAddressAdjustment),
-        HasLocationExpressionAddress(HasLocationExpressionAddress) {
-    InputDIEIdx = CU.getDIEIndex(InputDieEntry);
+      : DIEAttributeCloner(OutDIE, InUnit,
+                           CompileUnit::OutputUnitVariantPtr(OutUnit),
+                           InputDieEntry, Generator, FuncAddressAdjustment,
+                           VarAddressAdjustment, HasLocationExpressionAddress) {
+  }
+
+  DIEAttributeCloner(DIE *OutDIE, CompileUnit &InUnit, TypeUnit *OutUnit,
+                     const DWARFDebugInfoEntry *InputDieEntry,
+                     DIEGenerator &Generator,
+                     std::optional<int64_t> FuncAddressAdjustment,
+                     std::optional<int64_t> VarAddressAdjustment,
+                     bool HasLocationExpressionAddress)
+      : DIEAttributeCloner(OutDIE, InUnit,
+                           CompileUnit::OutputUnitVariantPtr(OutUnit),
+                           InputDieEntry, Generator, FuncAddressAdjustment,
+                           VarAddressAdjustment, HasLocationExpressionAddress) {
   }
 
   /// Clone attributes of input DIE.
@@ -69,7 +78,36 @@ class DIEAttributeCloner {
   /// Cannot be used concurrently.
   AttributesInfo AttrInfo;
 
+  unsigned getOutOffset() { return AttrOutOffset; }
+
 protected:
+  DIEAttributeCloner(DIE *OutDIE, CompileUnit &InUnit,
+                     CompileUnit::OutputUnitVariantPtr OutUnit,
+                     const DWARFDebugInfoEntry *InputDieEntry,
+                     DIEGenerator &Generator,
+                     std::optional<int64_t> FuncAddressAdjustment,
+                     std::optional<int64_t> VarAddressAdjustment,
+                     bool HasLocationExpressionAddress)
+      : OutDIE(OutDIE), InUnit(InUnit), OutUnit(OutUnit),
+        DebugInfoOutputSection(
+            OutUnit->getSectionDescriptor(DebugSectionKind::DebugInfo)),
+        InputDieEntry(InputDieEntry), Generator(Generator),
+        FuncAddressAdjustment(FuncAddressAdjustment),
+        VarAddressAdjustment(VarAddressAdjustment),
+        HasLocationExpressionAddress(HasLocationExpressionAddress) {
+    InputDIEIdx = InUnit.getDIEIndex(InputDieEntry);
+
+    // Use DW_FORM_strp form for string attributes for DWARF version less than 5
+    // or if output unit is type unit and we need to produce deterministic
+    // result. (We can not generate deterministic results for debug_str_offsets
+    // section when attributes are cloned parallelly).
+    Use_DW_FORM_strp =
+        (InUnit.getVersion() < 5) ||
+        (OutUnit.isTypeUnit() &&
+         ((InUnit.getGlobalData().getOptions().Threads != 1) &&
+          !InUnit.getGlobalData().getOptions().AllowNonDeterministicOutput));
+  }
+
   /// Clone string attribute.
   size_t
   cloneStringAttr(const DWARFFormValue &Val,
@@ -99,18 +137,14 @@ class DIEAttributeCloner {
   bool
   shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec);
 
-  /// Update patches offsets with the size of abbreviation number.
-  void
-  updatePatchesWithSizeOfAbbreviationNumber(unsigned SizeOfAbbreviationNumber) {
-    for (uint64_t *OffsetPtr : PatchesOffsets)
-      *OffsetPtr += SizeOfAbbreviationNumber;
-  }
-
   /// Output DIE.
   DIE *OutDIE = nullptr;
 
-  /// Compile unit for the output DIE.
-  CompileUnit &CU;
+  /// Input compilation unit.
+  CompileUnit &InUnit;
+
+  /// Output unit(either "plain" compilation unit, either artificial type unit).
+  CompileUnit::OutputUnitVariantPtr OutUnit;
 
   /// .debug_info section descriptor.
   SectionDescriptor &DebugInfoOutputSection;
@@ -139,6 +173,9 @@ class DIEAttributeCloner {
 
   /// Patches for the cloned attributes.
   OffsetsPtrVector PatchesOffsets;
+
+  /// This flag forces using DW_FORM_strp for string attributes.
+  bool Use_DW_FORM_strp = false;
 };
 
 } // end of namespace dwarflinker_parallel
diff --git a/llvm/lib/DWARFLinkerParallel/DIEGenerator.h b/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
index c0bbce0f520143c..42bf00f55ff1801 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
+++ b/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
@@ -23,6 +23,9 @@ class DIEGenerator {
   DIEGenerator(BumpPtrAllocator &Allocator, DwarfUnit &CU)
       : Allocator(Allocator), CU(CU) {}
 
+  DIEGenerator(DIE *OutputDIE, BumpPtrAllocator &Allocator, DwarfUnit &CU)
+      : Allocator(Allocator), CU(CU), OutputDIE(OutputDIE) {}
+
   /// Creates a DIE of specified tag \p DieTag and \p OutOffset.
   DIE *createDIE(dwarf::Tag DieTag, uint32_t OutOffset) {
     OutputDIE = DIE::get(Allocator, DieTag);
@@ -32,6 +35,8 @@ class DIEGenerator {
     return OutputDIE;
   }
 
+  DIE *getDIE() { return OutputDIE; }
+
   /// Adds a specified \p Child to the current DIE.
   void addChild(DIE *Child) {
     assert(Child != nullptr);
@@ -126,8 +131,10 @@ class DIEGenerator {
   }
 
   /// Creates appreviations for the current DIE. Returns value of
-  /// abbreviation number.
-  size_t finalizeAbbreviations(bool CHILDREN_yes) {
+  /// abbreviation number. Updates offsets with the size of abbreviation
+  /// number.
+  size_t finalizeAbbreviations(bool CHILDREN_yes,
+                               OffsetsPtrVector *OffsetsList) {
     // Create abbreviations for output DIE.
     DIEAbbrev NewAbbrev = OutputDIE->generateAbbrev();
     if (CHILDREN_yes)
@@ -136,7 +143,15 @@ class DIEGenerator {
     CU.assignAbbrev(NewAbbrev);
     OutputDIE->setAbbrevNumber(NewAbbrev.getNumber());
 
-    return getULEB128Size(OutputDIE->getAbbrevNumber());
+    size_t AbbrevNumberSize = getULEB128Size(OutputDIE->getAbbrevNumber());
+
+    // Add size of abbreviation number to the offsets.
+    if (OffsetsList != nullptr) {
+      for (uint64_t *OffsetPtr : *OffsetsList)
+        *OffsetPtr += AbbrevNumberSize;
+    }
+
+    return AbbrevNumberSize;
   }
 
 protected:
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp
index f082fd603610038..269f24b1a13b9ab 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DWARFLinkerImpl.h"
+#include "DependencyTracker.h"
 
 std::unique_ptr<llvm::dwarflinker_parallel::DWARFLinker>
 llvm::dwarflinker_parallel::DWARFLinker::createLinker(
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp
index c1181a264f879f0..48e7cb1fd7e2f36 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp
@@ -7,17 +7,65 @@
 //===----------------------------------------------------------------------===//
 
 #include "DWARFLinkerCompileUnit.h"
+#include "AcceleratorRecordsSaver.h"
 #include "DIEAttributeCloner.h"
 #include "DIEGenerator.h"
-#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "DependencyTracker.h"
+#include "SyntheticTypeNameBuilder.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
 #include "llvm/Support/DJB.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+#include <utility>
 
 using namespace llvm;
 using namespace llvm::dwarflinker_parallel;
 
+CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
+                         StringRef ClangModuleName, DWARFFile &File,
+                         OffsetToUnitTy UnitFromOffset,
+                         dwarf::FormParams Format, llvm::endianness Endianess)
+    : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
+      getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),
+      AcceleratorRecords(&GlobalData.getAllocator()) {
+  UnitName = File.FileName;
+  setOutputFormat(Format, Endianess);
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+}
+
+CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,
+                         unsigned ID, StringRef ClangModuleName,
+                         DWARFFile &File, OffsetToUnitTy UnitFromOffset,
+                         dwarf::FormParams Format, llvm::endianness Endianess)
+    : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
+      OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
+      Stage(Stage::CreatedNotLoaded),
+      AcceleratorRecords(&GlobalData.getAllocator()) {
+  setOutputFormat(Format, Endianess);
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+
+  DWARFDie CUDie = OrigUnit.getUnitDIE();
+  if (!CUDie)
+    return;
+
+  if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {
+    uint16_t LangVal = dwarf::toUnsigned(Val, 0);
+    if (isODRLanguage(LangVal))
+      Language = LangVal;
+  }
+
+  if (!GlobalData.getOptions().NoODR && Language.has_value())
+    NoODR = false;
+
+  if (const char *CUName = CUDie.getName(DINameKind::ShortName))
+    UnitName = CUName;
+  else
+    UnitName = File.FileName;
+  SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();
+}
+
 void CompileUnit::loadLineTable() {
   LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
 }
@@ -39,6 +87,7 @@ void CompileUnit::maybeResetToLoadedStage() {
   HighPc = 0;
   Labels.clear();
   Ranges.clear();
+  Dependencies.reset(nullptr);
 
   if (getStage() < Stage::Cloned) {
     setStage(Stage::Loaded);
@@ -53,6 +102,8 @@ void CompileUnit::maybeResetToLoadedStage() {
 
   for (uint64_t &Offset : OutDieOffsetArray)
     Offset = 0;
+  for (TypeEntry *&Name : TypeEntries)
+    Name = nullptr;
   eraseSections();
 
   setStage(Stage::CreatedNotLoaded);
@@ -66,21 +117,30 @@ bool CompileUnit::loadInputDIEs() {
   // load input dies, resize Info structures array.
   DieInfoArray.resize(getOrigUnit().getNumDIEs());
   OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
+  if (!NoODR)
+    TypeEntries.resize(getOrigUnit().getNumDIEs());
   return true;
 }
 
 void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
-                                           bool IsInModule, bool IsInFunction) {
+                                           bool IsODRUnavailableFunctionScope) {
+  CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);
+
   for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
        CurChild && CurChild->getAbbreviationDeclarationPtr();
        CurChild = getSiblingEntry(CurChild)) {
     CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
+    bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
 
-    if (IsInModule)
+    if (DieInfo.getIsInMouduleScope())
       ChildInfo.setIsInMouduleScope();
-    if (IsInFunction)
+
+    if (DieInfo.getIsInFunctionScope())
       ChildInfo.setIsInFunctionScope();
 
+    if (DieInfo.getIsInAnonNamespaceScope())
+      ChildInfo.setIsInAnonNamespaceScope();
+
     switch (CurChild->getTag()) {
     case dwarf::DW_TAG_module:
       ChildInfo.setIsInMouduleScope();
@@ -91,19 +151,35 @@ void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
       break;
     case dwarf::DW_TAG_subprogram:
       ChildInfo.setIsInFunctionScope();
+      if (!ChildIsODRUnavailableFunctionScope &&
+          !ChildInfo.getIsInMouduleScope()) {
+        if (find(CurChild,
+                 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
+          ChildIsODRUnavailableFunctionScope = true;
+      }
       break;
+    case dwarf::DW_TAG_namespace: {
+      UnitEntryPairTy NamespaceEntry = {this, CurChild};
+
+      if (find(CurChild, dwarf::DW_AT_extension))
+        NamespaceEntry = NamespaceEntry.getNamespaceOrigin();
+
+      if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
+        ChildInfo.setIsInAnonNamespaceScope();
+    } break;
     default:
       break;
     }
 
-    if (IsInModule)
-      ChildInfo.setIsInMouduleScope();
-    if (IsInFunction)
-      ChildInfo.setIsInFunctionScope();
+    if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)
+      ChildInfo.setTrackLiveness();
+
+    if ((!ChildInfo.getIsInAnonNamespaceScope() &&
+         !ChildIsODRUnavailableFunctionScope && !NoODR))
+      ChildInfo.setODRAvailable();
 
     if (CurChild->hasChildren())
-      analyzeDWARFStructureRec(CurChild, ChildInfo.getIsInMouduleScope(),
-                               ChildInfo.getIsInFunctionScope());
+      analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
   }
 }
 
@@ -162,8 +238,11 @@ void CompileUnit::cleanupDataAfterClonning() {
   AbbreviationsSet.clear();
   ResolvedFullPaths.shrink_and_clear();
   ResolvedParentPaths.clear();
+  FileNames.shrink_and_clear();
   DieInfoArray = SmallVector<DIEInfo>();
   OutDieOffsetArray = SmallVector<uint64_t>();
+  TypeEntries = SmallVector<TypeEntry *>();
+  Dependencies.reset(nullptr);
   getOrigUnit().clear();
 }
 
@@ -184,7 +263,7 @@ static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
 /// Collect references to parseable Swift interfaces in imported
 /// DW_TAG_module blocks.
 void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
-  if (getLanguage() != dwarf::DW_LANG_Swift)
+  if (!Language || Language != dwarf::DW_LANG_Swift)
     return;
 
   if (!GlobalData.getOptions().ParseableSwiftInterfaces)
@@ -231,12 +310,43 @@ void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
   }
 }
 
+Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) {
+  if (!getUnitDIE().isValid())
+    return Error::success();
+
+  SyntheticTypeNameBuilder NameBuilder(TypePoolRef);
+  return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);
+}
+
+Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
+                                      SyntheticTypeNameBuilder &NameBuilder) {
+  OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);
+  for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
+       CurChild && CurChild->getAbbreviationDeclarationPtr();
+       CurChild = getSiblingEntry(CurChild)) {
+    CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
+    if (!ChildInfo.needToPlaceInTypeTable())
+      continue;
+
+    assert(ChildInfo.getODRAvailable());
+    if (Error Err = NameBuilder.assignName(
+            {this, CurChild},
+            ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
+      return Err;
+
+    if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
+      return Err;
+  }
+
+  return Error::success();
+}
+
 void CompileUnit::updateDieRefPatchesWithClonedOffsets() {
   if (std::optional<SectionDescriptor *> DebugInfoSection =
           tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) {
 
     (*DebugInfoSection)
-        ->ListDebugDieRefPatch.forEach([](DebugDieRefPatch &Patch) {
+        ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
           /// Replace stored DIE indexes with DIE output offsets.
           Patch.RefDieIdxOrClonedOffset =
               Patch.RefCU.getPointer()->getDieOutOffset(
@@ -245,7 +355,7 @@ void CompileUnit::updateDieRefPatchesWithClonedOffsets() {
 
     (*DebugInfoSection)
         ->ListDebugULEB128DieRefPatch.forEach(
-            [](DebugULEB128DieRefPatch &Patch) {
+            [&](DebugULEB128DieRefPatch &Patch) {
               /// Replace stored DIE indexes with DIE output offsets.
               Patch.RefDieIdxOrClonedOffset =
                   Patch.RefCU.getPointer()->getDieOutOffset(
@@ -278,45 +388,53 @@ void CompileUnit::updateDieRefPatchesWithClonedOffsets() {
   }
 }
 
-std::optional<std::pair<CompileUnit *, uint32_t>>
-CompileUnit::resolveDIEReference(
+std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
     const DWARFFormValue &RefValue,
     ResolveInterCUReferencesMode CanResolveInterCUReferences) {
   if (std::optional<DWARFFormValue::UnitOffset> Ref =
           *RefValue.getAsRelativeReference()) {
-    if (Ref->Unit != nullptr) {
+    if (Ref->Unit == OrigUnit) {
       // Referenced DIE is in current compile unit.
-
       if (std::optional<uint32_t> RefDieIdx =
-              getDIEIndexForOffset(Ref->Unit->getOffset() + Ref->Offset))
-        return std::make_pair(this, *RefDieIdx);
+              getDIEIndexForOffset(OrigUnit->getOffset() + Ref->Offset))
+        return UnitEntryPairTy{this, OrigUnit->getDebugInfoEntry(*RefDieIdx)};
     }
-
-    if (CompileUnit *RefCU = getUnitFromOffset(Ref->Offset)) {
-      if (RefCU->getUniqueID() == getUniqueID()) {
+    uint64_t RefDIEOffset =
+        Ref->Unit ? Ref->Unit->getOffset() + Ref->Offset : Ref->Offset;
+    if (CompileUnit *RefCU = getUnitFromOffset(RefDIEOffset)) {
+      if (RefCU == this) {
         // Referenced DIE is in current compile unit.
         if (std::optional<uint32_t> RefDieIdx =
-                getDIEIndexForOffset(Ref->Offset))
-          return std::make_pair(this, *RefDieIdx);
+                getDIEIndexForOffset(RefDIEOffset))
+          return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};
       } else if (CanResolveInterCUReferences) {
         // Referenced DIE is in other compile unit.
 
         // Check whether DIEs are loaded for that compile unit.
         enum Stage ReferredCUStage = RefCU->getStage();
         if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
-          return std::make_pair(RefCU, 0);
+          return UnitEntryPairTy{RefCU, nullptr};
 
         if (std::optional<uint32_t> RefDieIdx =
-                RefCU->getDIEIndexForOffset(Ref->Offset))
-          return std::make_pair(RefCU, *RefDieIdx);
+                RefCU->getDIEIndexForOffset(RefDIEOffset))
+          return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};
       } else
-        return std::make_pair(RefCU, 0);
+        return UnitEntryPairTy{RefCU, nullptr};
     }
   }
 
   return std::nullopt;
 }
 
+std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
+    const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,
+    ResolveInterCUReferencesMode CanResolveInterCUReferences) {
+  if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))
+    return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);
+
+  return std::nullopt;
+}
+
 void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
                                    int64_t PcOffset) {
   std::lock_guard<std::mutex> Guard(RangesMutex);
@@ -565,48 +683,6 @@ Error CompileUnit::emitDebugAddrSection() {
   return Error::success();
 }
 
-Error CompileUnit::emitDebugStringOffsetSection() {
-  if (getVersion() < 5)
-    return Error::success();
-
-  if (DebugStringIndexMap.empty())
-    return Error::success();
-
-  SectionDescriptor &OutDebugStrOffsetsSection =
-      getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
-
-  // Emit section header.
-
-  //   Emit length.
-  OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);
-  uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
-
-  //   Emit version.
-  OutDebugStrOffsetsSection.emitIntVal(5, 2);
-
-  //   Emit padding.
-  OutDebugStrOffsetsSection.emitIntVal(0, 2);
-
-  //   Emit index to offset map.
-  for (const StringEntry *String : DebugStringIndexMap.getValues()) {
-    // Note patch for string offset value.
-    OutDebugStrOffsetsSection.notePatch(
-        DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});
-
-    // Emit placeholder for offset value.
-    OutDebugStrOffsetsSection.emitOffset(0xBADDEF);
-  }
-
-  // Patch section length.
-  OutDebugStrOffsetsSection.apply(
-      OffsetAfterSectionLength -
-          OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
-      dwarf::DW_FORM_sec_offset,
-      OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
-
-  return Error::success();
-}
-
 Error CompileUnit::cloneAndEmitRanges() {
   if (getGlobalData().getOptions().UpdateIndexTablesOnly)
     return Error::success();
@@ -1165,20 +1241,25 @@ void CompileUnit::cloneDieAttrExpression(
   }
 }
 
-Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple) {
+Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple,
+                                TypeUnit *ArtificialTypeUnit) {
   BumpPtrAllocator Allocator;
 
   DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();
   if (!OrigUnitDIE.isValid())
     return Error::success();
 
+  TypeEntry *RootEntry = nullptr;
+  if (ArtificialTypeUnit)
+    RootEntry = ArtificialTypeUnit->getTypePool().getRoot();
+
   // Clone input DIE entry recursively.
-  DIE *OutCUDie =
-      cloneDIE(OrigUnitDIE.getDebugInfoEntry(), getDebugInfoHeaderSize(),
-               std::nullopt, std::nullopt, Allocator);
-  setOutUnitDIE(OutCUDie);
+  std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
+      OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),
+      std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
+  setOutUnitDIE(OutCUDie.first);
 
-  if (getGlobalData().getOptions().NoOutput || (OutCUDie == nullptr))
+  if (getGlobalData().getOptions().NoOutput || (OutCUDie.first == nullptr))
     return Error::success();
 
   assert(TargetTriple.has_value());
@@ -1188,6 +1269,7 @@ Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple) {
   if (Error Err = cloneAndEmitDebugMacro())
     return Err;
 
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
   if (Error Err = emitDebugInfo(*TargetTriple))
     return Err;
 
@@ -1215,27 +1297,103 @@ Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple) {
   return emitAbbreviations();
 }
 
-bool needToClone(CompileUnit::DIEInfo &Info) {
-  return Info.getKeep() || Info.getKeepChildren();
-}
-
-DIE *CompileUnit::cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
-                           uint64_t OutOffset,
-                           std::optional<int64_t> FuncAddressAdjustment,
-                           std::optional<int64_t> VarAddressAdjustment,
-                           BumpPtrAllocator &Allocator) {
+std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(
+    const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,
+    uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
+    std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
+    TypeUnit *ArtificialTypeUnit) {
   uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
   CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
 
-  if (!needToClone(Info))
-    return nullptr;
+  bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
+  bool NeedToCloneTypeDIE =
+      (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
+      Info.needToPlaceInTypeTable();
+  std::pair<DIE *, TypeEntry *> ClonedDIE;
+
+  DIEGenerator PlainDIEGenerator(Allocator, *this);
+
+  if (NeedToClonePlainDIE)
+    // Create a cloned DIE which would be placed into the cloned version
+    // of input compile unit.
+    ClonedDIE.first = createPlainDIEandCloneAttributes(
+        InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
+        VarAddressAdjustment);
+  if (NeedToCloneTypeDIE) {
+    // Create a cloned DIE which would be placed into the artificial type
+    // unit.
+    assert(ArtificialTypeUnit != nullptr);
+    DIEGenerator TypeDIEGenerator(
+        ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);
+
+    ClonedDIE.second = createTypeDIEandCloneAttributes(
+        InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
+        ArtificialTypeUnit);
+  }
+  TypeEntry *TypeParentForChild =
+      ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;
+
+  bool HasPlainChildrenToClone =
+      (ClonedDIE.first && Info.getKeepPlainChildren());
+
+  bool HasTypeChildrenToClone =
+      ((ClonedDIE.second ||
+        InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
+       Info.getKeepTypeChildren());
+
+  // Recursively clone children.
+  if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
+    for (const DWARFDebugInfoEntry *CurChild =
+             getFirstChildEntry(InputDieEntry);
+         CurChild && CurChild->getAbbreviationDeclarationPtr();
+         CurChild = getSiblingEntry(CurChild)) {
+      std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
+          CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
+          VarAddressAdjustment, Allocator, ArtificialTypeUnit);
+
+      if (ClonedChild.first) {
+        OutOffset =
+            ClonedChild.first->getOffset() + ClonedChild.first->getSize();
+        PlainDIEGenerator.addChild(ClonedChild.first);
+      }
+    }
+    assert(ClonedDIE.first == nullptr ||
+           HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
+
+    // Account for the end of children marker.
+    if (HasPlainChildrenToClone)
+      OutOffset += sizeof(int8_t);
+  }
+
+  // Update our size.
+  if (ClonedDIE.first != nullptr)
+    ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
 
+  return ClonedDIE;
+}
+
+DIE *CompileUnit::createPlainDIEandCloneAttributes(
+    const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
+    uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
+    std::optional<int64_t> &VarAddressAdjustment) {
+  uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
+  CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
+  DIE *ClonedDIE = nullptr;
   bool HasLocationExpressionAddress = false;
   if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
     // Get relocation adjustment value for the current function.
     FuncAddressAdjustment =
         getContaingFile().Addresses->getSubprogramRelocAdjustment(
             getDIE(InputDieEntry));
+  } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
+    // Get relocation adjustment value for the current label.
+    std::optional<uint64_t> lowPC =
+        dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));
+    if (lowPC) {
+      LabelMapTy::iterator It = Labels.find(*lowPC);
+      if (It != Labels.end())
+        FuncAddressAdjustment = It->second;
+    }
   } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
     // Get relocation adjustment value for the current variable.
     std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
@@ -1248,51 +1406,132 @@ DIE *CompileUnit::cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
       VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
   }
 
-  DIEGenerator DIEGenerator(Allocator, *this);
-  DIE *ClonedDIE = DIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
+  ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
+
+  // Offset to the DIE would be used after output DIE tree is deleted.
+  // Thus we need to remember DIE offset separately.
   rememberDieOutOffset(InputDieIdx, OutOffset);
 
   // Clone Attributes.
-  DIEAttributeCloner AttributesCloner(
-      ClonedDIE, *this, InputDieEntry, DIEGenerator, FuncAddressAdjustment,
-      VarAddressAdjustment, HasLocationExpressionAddress);
+  DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
+                                      PlainDIEGenerator, FuncAddressAdjustment,
+                                      VarAddressAdjustment,
+                                      HasLocationExpressionAddress);
   AttributesCloner.clone();
 
   // Remember accelerator info.
-  rememberAcceleratorEntries(InputDieEntry, OutOffset,
-                             AttributesCloner.AttrInfo);
+  AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);
+  AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
+                         nullptr);
 
-  bool HasChildrenToClone = Info.getKeepChildren();
-  OutOffset = AttributesCloner.finalizeAbbreviations(HasChildrenToClone);
+  OutOffset =
+      AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());
 
-  if (HasChildrenToClone) {
-    // Recursively clone children.
-    for (const DWARFDebugInfoEntry *CurChild =
-             getFirstChildEntry(InputDieEntry);
-         CurChild && CurChild->getAbbreviationDeclarationPtr();
-         CurChild = getSiblingEntry(CurChild)) {
-      if (DIE *ClonedChild =
-              cloneDIE(CurChild, OutOffset, FuncAddressAdjustment,
-                       VarAddressAdjustment, Allocator)) {
-        OutOffset = ClonedChild->getOffset() + ClonedChild->getSize();
-        DIEGenerator.addChild(ClonedChild);
-      }
+  return ClonedDIE;
+}
+
+/// Allocates output DIE for the specified \p TypeDescriptor.
+DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
+                                  DIEGenerator &TypeDIEGenerator,
+                                  dwarf::Tag DieTag, bool IsDeclaration,
+                                  bool IsParentDeclaration) {
+  DIE *DefinitionDie = TypeDescriptor->Die;
+  // Do not allocate any new DIE if definition DIE is already met.
+  if (DefinitionDie)
+    return nullptr;
+
+  DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
+  bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;
+
+  if (IsDeclaration && !DeclarationDie) {
+    // Alocate declaration DIE.
+    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
+    if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
+                                                             NewDie))
+      return NewDie;
+  } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
+    // Overwrite existing declaration DIE if it's parent is also an declaration
+    // while parent of current declaration DIE is a definition.
+    if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(
+            OldParentIsDeclaration, false)) {
+      DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
+      TypeDescriptor->DeclarationDie = NewDie;
+      return NewDie;
+    }
+  } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
+    // Alocate declaration DIE since parent of current DIE is marked as
+    // declaration.
+    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
+    if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
+                                                             NewDie))
+      return NewDie;
+  } else if (!IsDeclaration && !IsParentDeclaration) {
+    // Allocate definition DIE.
+    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
+    if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
+      TypeDescriptor->ParentIsDeclaration = false;
+      return NewDie;
     }
+  }
 
-    // Account for the end of children marker.
-    OutOffset += sizeof(int8_t);
+  return nullptr;
+}
+
+TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
+    const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
+    TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {
+  assert(ArtificialTypeUnit != nullptr);
+  uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
+
+  TypeEntry *Entry = getDieTypeEntry(InputDieIdx);
+  assert(Entry != nullptr);
+  assert(ClonedParentTypeDIE != nullptr);
+  TypeEntryBody *EntryBody =
+      ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(
+          Entry, ClonedParentTypeDIE);
+  assert(EntryBody);
+
+  bool IsDeclaration =
+      dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);
+
+  bool ParentIsDeclaration = false;
+  if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
+    ParentIsDeclaration =
+        dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);
+
+  DIE *OutDIE =
+      allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
+                      IsDeclaration, ParentIsDeclaration);
+
+  if (OutDIE != nullptr) {
+    assert(ArtificialTypeUnit != nullptr);
+    ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo);
+
+    DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
+                                        InputDieEntry, TypeDIEGenerator,
+                                        std::nullopt, std::nullopt, false);
+    AttributesCloner.clone();
+
+    // Remember accelerator info.
+    AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,
+                                              ArtificialTypeUnit);
+    AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
+                           Entry);
+
+    // if AttributesCloner.getOutOffset() == 0 then we need to add
+    // 1 to avoid assertion for zero size. We will subtract it back later.
+    OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
   }
 
-  // Update our size.
-  ClonedDIE->setSize(OutOffset - ClonedDIE->getOffset());
-  return ClonedDIE;
+  return Entry;
 }
 
 Error CompileUnit::cloneAndEmitLineTable(Triple &TargetTriple) {
   const DWARFDebugLine::LineTable *InputLineTable =
       getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());
   if (InputLineTable == nullptr) {
-    warn("cann't load line table.");
+    if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))
+      warn("cann't load line table.");
     return Error::success();
   }
 
@@ -1413,230 +1652,228 @@ void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
-  llvm::errs() << "{\n";
+  llvm::errs() << "{";
   llvm::errs() << "  Placement: ";
   switch (getPlacement()) {
   case NotSet:
-    llvm::errs() << "NotSet\n";
+    llvm::errs() << "NotSet";
     break;
   case TypeTable:
-    llvm::errs() << "TypeTable\n";
+    llvm::errs() << "TypeTable";
     break;
   case PlainDwarf:
-    llvm::errs() << "PlainDwarf\n";
+    llvm::errs() << "PlainDwarf";
     break;
   case Both:
-    llvm::errs() << "Both\n";
-    break;
-  case Parent:
-    llvm::errs() << "Parent\n";
+    llvm::errs() << "Both";
     break;
   }
 
   llvm::errs() << "  Keep: " << getKeep();
-  llvm::errs() << "  KeepChildren: " << getKeepChildren();
-  llvm::errs() << "  ReferrencedBy: " << getReferrencedBy();
+  llvm::errs() << "  KeepPlainChildren: " << getKeepPlainChildren();
+  llvm::errs() << "  KeepTypeChildren: " << getKeepTypeChildren();
   llvm::errs() << "  IsInMouduleScope: " << getIsInMouduleScope();
   llvm::errs() << "  IsInFunctionScope: " << getIsInFunctionScope();
+  llvm::errs() << "  IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
+  llvm::errs() << "  ODRAvailable: " << getODRAvailable();
+  llvm::errs() << "  TrackLiveness: " << getTrackLiveness();
   llvm::errs() << "}\n";
 }
 #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 
-static uint32_t hashFullyQualifiedName(CompileUnit *InputCU, DWARFDie &InputDIE,
-                                       int ChildRecurseDepth = 0) {
-  const char *Name = nullptr;
-  CompileUnit *CU = InputCU;
-  std::optional<DWARFFormValue> RefVal;
+std::optional<std::pair<StringRef, StringRef>>
+CompileUnit::getDirAndFilenameFromLineTable(
+    const DWARFFormValue &FileIdxValue) {
+  uint64_t FileIdx;
+  if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())
+    FileIdx = *Val;
+  else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
+    FileIdx = *Val;
+  else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
+    FileIdx = *Val;
+  else
+    return std::nullopt;
 
-  // Usually name`s depth does not exceed 3. Set maximal depth
-  // to 1000 here, to avoid infinite loop in case incorrect input
-  // DWARF.
-  size_t MaxNameDepth = 1000;
-  size_t CurNameDepth = 0;
+  return getDirAndFilenameFromLineTable(FileIdx);
+}
 
-  while (CurNameDepth++ < MaxNameDepth) {
-    if (const char *CurrentName = InputDIE.getName(DINameKind::ShortName))
-      Name = CurrentName;
+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);
+}
 
-    if (!(RefVal = InputDIE.find(dwarf::DW_AT_specification)) &&
-        !(RefVal = InputDIE.find(dwarf::DW_AT_abstract_origin)))
-      break;
+std::optional<std::pair<StringRef, StringRef>>
+CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
+  FileNamesCache::iterator FileData = FileNames.find(FileIdx);
+  if (FileData != FileNames.end())
+    return std::make_pair(StringRef(FileData->second.first),
+                          StringRef(FileData->second.second));
 
-    if (!RefVal->isFormClass(DWARFFormValue::FC_Reference))
-      break;
+  if (const DWARFDebugLine::LineTable *LineTable =
+          getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {
+    if (LineTable->hasFileAtIndex(FileIdx)) {
 
-    std::optional<std::pair<CompileUnit *, uint32_t>> RefDie =
-        CU->resolveDIEReference(*RefVal, ResolveInterCUReferencesMode::Resolve);
-    if (!RefDie)
-      break;
+      const llvm::DWARFDebugLine::FileNameEntry &Entry =
+          LineTable->Prologue.getFileNameEntry(FileIdx);
+
+      Expected<const char *> Name = Entry.Name.getAsCString();
+      if (!Name) {
+        warn(Name.takeError());
+        return std::nullopt;
+      }
+
+      std::string FileName = *Name;
+      if (isPathAbsoluteOnWindowsOrPosix(FileName)) {
+        FileNamesCache::iterator FileData =
+            FileNames
+                .insert(std::make_pair(
+                    FileIdx,
+                    std::make_pair(std::string(""), std::move(FileName))))
+                .first;
+        return std::make_pair(StringRef(FileData->second.first),
+                              StringRef(FileData->second.second));
+      }
+
+      SmallString<256> FilePath;
+      StringRef IncludeDir;
+      // Be defensive about the contents of Entry.
+      if (getVersion() >= 5) {
+        // DirIdx 0 is the compilation directory, so don't include it for
+        // relative names.
+        if ((Entry.DirIdx != 0) &&
+            Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
+          Expected<const char *> DirName =
+              LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
+                  .getAsCString();
+          if (DirName)
+            IncludeDir = *DirName;
+          else {
+            warn(DirName.takeError());
+            return std::nullopt;
+          }
+        }
+      } else {
+        if (0 < Entry.DirIdx &&
+            Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
+          Expected<const char *> DirName =
+              LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
+                  .getAsCString();
+          if (DirName)
+            IncludeDir = *DirName;
+          else {
+            warn(DirName.takeError());
+            return std::nullopt;
+          }
+        }
+      }
+
+      StringRef CompDir = getOrigUnit().getCompilationDir();
+
+      if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {
+        sys::path::append(FilePath, sys::path::Style::native, CompDir);
+      }
 
-    assert(RefDie->second != 0);
+      sys::path::append(FilePath, sys::path::Style::native, IncludeDir);
 
-    CU = RefDie->first;
-    InputDIE = RefDie->first->getDIEAtIndex(RefDie->second);
+      FileNamesCache::iterator FileData =
+          FileNames
+              .insert(
+                  std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
+                                                         std::move(FileName))))
+              .first;
+      return std::make_pair(StringRef(FileData->second.first),
+                            StringRef(FileData->second.second));
+    }
   }
 
-  if (!Name && InputDIE.getTag() == dwarf::DW_TAG_namespace)
-    Name = "(anonymous namespace)";
+  return std::nullopt;
+}
+
+#define MAX_REFERENCIES_DEPTH 1000
+UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() {
+  UnitEntryPairTy CUDiePair(*this);
+  std::optional<UnitEntryPairTy> RefDiePair;
+  int refDepth = 0;
+  do {
+    RefDiePair = CUDiePair.CU->resolveDIEReference(
+        CUDiePair.DieEntry, dwarf::DW_AT_extension,
+        ResolveInterCUReferencesMode::Resolve);
+    if (!RefDiePair || !RefDiePair->DieEntry)
+      return CUDiePair;
+
+    CUDiePair = *RefDiePair;
+  } while (refDepth++ < MAX_REFERENCIES_DEPTH);
+
+  return CUDiePair;
+}
 
-  DWARFDie ParentDie = InputDIE.getParent();
-  if (!ParentDie.isValid() || ParentDie.getTag() == dwarf::DW_TAG_compile_unit)
-    return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
+std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {
+  if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
+    return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};
 
-  return djbHash(
-      (Name ? Name : ""),
-      djbHash((Name ? "::" : ""),
-              hashFullyQualifiedName(CU, ParentDie, ++ChildRecurseDepth)));
+  return std::nullopt;
 }
 
-void CompileUnit::rememberAcceleratorEntries(
-    const DWARFDebugInfoEntry *InputDieEntry, uint64_t OutOffset,
-    AttributesInfo &AttrInfo) {
-  if (GlobalData.getOptions().AccelTables.empty())
-    return;
+CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)
+    : Ptr(U) {
+  assert(U != nullptr);
+}
 
-  DWARFDie InputDIE = getDIE(InputDieEntry);
-
-  // Look for short name recursively if short name is not known yet.
-  if (AttrInfo.Name == nullptr)
-    if (const char *ShortName = InputDIE.getShortName())
-      AttrInfo.Name = getGlobalData().getStringPool().insert(ShortName).first;
-
-  switch (InputDieEntry->getTag()) {
-  case dwarf::DW_TAG_array_type:
-  case dwarf::DW_TAG_class_type:
-  case dwarf::DW_TAG_enumeration_type:
-  case dwarf::DW_TAG_pointer_type:
-  case dwarf::DW_TAG_reference_type:
-  case dwarf::DW_TAG_string_type:
-  case dwarf::DW_TAG_structure_type:
-  case dwarf::DW_TAG_subroutine_type:
-  case dwarf::DW_TAG_typedef:
-  case dwarf::DW_TAG_union_type:
-  case dwarf::DW_TAG_ptr_to_member_type:
-  case dwarf::DW_TAG_set_type:
-  case dwarf::DW_TAG_subrange_type:
-  case dwarf::DW_TAG_base_type:
-  case dwarf::DW_TAG_const_type:
-  case dwarf::DW_TAG_constant:
-  case dwarf::DW_TAG_file_type:
-  case dwarf::DW_TAG_namelist:
-  case dwarf::DW_TAG_packed_type:
-  case dwarf::DW_TAG_volatile_type:
-  case dwarf::DW_TAG_restrict_type:
-  case dwarf::DW_TAG_atomic_type:
-  case dwarf::DW_TAG_interface_type:
-  case dwarf::DW_TAG_unspecified_type:
-  case dwarf::DW_TAG_shared_type:
-  case dwarf::DW_TAG_immutable_type:
-  case dwarf::DW_TAG_rvalue_reference_type: {
-    if (!AttrInfo.IsDeclaration && AttrInfo.Name != nullptr &&
-        !AttrInfo.Name->getKey().empty()) {
-      uint32_t Hash = hashFullyQualifiedName(this, InputDIE);
-
-      uint64_t RuntimeLang =
-          dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
-              .value_or(0);
-
-      bool ObjCClassIsImplementation =
-          (RuntimeLang == dwarf::DW_LANG_ObjC ||
-           RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
-          dwarf::toUnsigned(
-              InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
-              .value_or(0);
-
-      rememberTypeForAccelerators(AttrInfo.Name, OutOffset,
-                                  InputDieEntry->getTag(), Hash,
-                                  ObjCClassIsImplementation);
-    }
-  } break;
-  case dwarf::DW_TAG_namespace: {
-    if (AttrInfo.Name == nullptr)
-      AttrInfo.Name =
-          getGlobalData().getStringPool().insert("(anonymous namespace)").first;
-
-    rememberNamespaceForAccelerators(AttrInfo.Name, OutOffset,
-                                     InputDieEntry->getTag());
-  } break;
-  case dwarf::DW_TAG_imported_declaration: {
-    if (AttrInfo.Name != nullptr)
-      rememberNamespaceForAccelerators(AttrInfo.Name, OutOffset,
-                                       InputDieEntry->getTag());
-  } break;
-  case dwarf::DW_TAG_compile_unit:
-  case dwarf::DW_TAG_lexical_block: {
-    // Nothing to do.
-  } break;
-  default:
-    if (AttrInfo.HasLiveAddress || AttrInfo.HasRanges) {
-      if (AttrInfo.Name != nullptr)
-        rememberNameForAccelerators(
-            AttrInfo.Name, OutOffset, InputDieEntry->getTag(),
-            InputDieEntry->getTag() == dwarf::DW_TAG_inlined_subroutine);
-
-      // Look for mangled name recursively if mangled name is not known yet.
-      if (AttrInfo.MangledName == nullptr)
-        if (const char *LinkageName = InputDIE.getLinkageName())
-          AttrInfo.MangledName =
-              getGlobalData().getStringPool().insert(LinkageName).first;
-
-      if (AttrInfo.MangledName != nullptr &&
-          AttrInfo.MangledName != AttrInfo.Name)
-        rememberNameForAccelerators(
-            AttrInfo.MangledName, OutOffset, InputDieEntry->getTag(),
-            InputDieEntry->getTag() == dwarf::DW_TAG_inlined_subroutine);
-
-      // Strip template parameters from the short name.
-      if (AttrInfo.Name != nullptr && AttrInfo.MangledName != AttrInfo.Name &&
-          (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
-        if (std::optional<StringRef> Name =
-                StripTemplateParameters(AttrInfo.Name->getKey())) {
-          StringEntry *NameWithoutTemplateParams =
-              getGlobalData().getStringPool().insert(*Name).first;
-
-          rememberNameForAccelerators(NameWithoutTemplateParams, OutOffset,
-                                      InputDieEntry->getTag(), true);
-        }
-      }
+CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {
+  assert(U != nullptr);
+}
 
-      if (AttrInfo.Name)
-        rememberObjCAccelerator(InputDieEntry, OutOffset, AttrInfo);
-    }
-    break;
-  }
+DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() {
+  if (isCompileUnit())
+    return getAsCompileUnit();
+  else
+    return getAsTypeUnit();
 }
 
-void CompileUnit::rememberObjCAccelerator(
-    const DWARFDebugInfoEntry *InputDieEntry, uint64_t OutOffset,
-    AttributesInfo &AttrInfo) {
-  std::optional<ObjCSelectorNames> Names =
-      getObjCNamesIfSelector(AttrInfo.Name->getKey());
-  if (!Names)
-    return;
+bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {
+  return Ptr.is<CompileUnit *>();
+}
 
-  StringEntry *Selector =
-      getGlobalData().getStringPool().insert(Names->Selector).first;
-  rememberNameForAccelerators(Selector, OutOffset, InputDieEntry->getTag(),
-                              true);
-  StringEntry *ClassName =
-      getGlobalData().getStringPool().insert(Names->ClassName).first;
-  rememberObjCNameForAccelerators(ClassName, OutOffset,
-                                  InputDieEntry->getTag());
-  if (Names->ClassNameNoCategory) {
-    StringEntry *ClassNameNoCategory = getGlobalData()
-                                           .getStringPool()
-                                           .insert(*Names->ClassNameNoCategory)
-                                           .first;
-    rememberObjCNameForAccelerators(ClassNameNoCategory, OutOffset,
-                                    InputDieEntry->getTag());
-  }
-  if (Names->MethodNameNoCategory) {
-    StringEntry *MethodNameNoCategory =
-        getGlobalData()
-            .getStringPool()
-            .insert(*Names->MethodNameNoCategory)
-            .first;
-    rememberNameForAccelerators(MethodNameNoCategory, OutOffset,
-                                InputDieEntry->getTag(), true);
-  }
+bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {
+  return Ptr.is<TypeUnit *>();
+}
+
+CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {
+  return Ptr.get<CompileUnit *>();
+}
+
+TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {
+  return Ptr.get<TypeUnit *>();
+}
+
+bool CompileUnit::resolveDependenciesAndMarkLiveness(
+    bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
+  if (!Dependencies.get())
+    Dependencies.reset(new DependencyTracker(*this));
+
+  return Dependencies->resolveDependenciesAndMarkLiveness(
+      InterCUProcessingStarted, HasNewInterconnectedCUs);
+}
+
+bool CompileUnit::updateDependenciesCompleteness() {
+  assert(Dependencies.get());
+
+  return Dependencies.get()->updateDependenciesCompleteness();
+}
+
+void CompileUnit::verifyDependencies() {
+  assert(Dependencies.get());
+
+  Dependencies.get()->verifyKeepChain();
+}
+
+ArrayRef<dwarf::Attribute> llvm::dwarflinker_parallel::getODRAttributes() {
+  static dwarf::Attribute ODRAttributes[] = {
+      dwarf::DW_AT_type, dwarf::DW_AT_specification,
+      dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
+
+  return ODRAttributes;
 }
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h
index 54666f684f3a3b0..39e010fd632393d 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h
@@ -10,7 +10,6 @@
 #define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERCOMPILEUNIT_H
 
 #include "DWARFLinkerUnit.h"
-#include "IndexedValuesMap.h"
 #include "llvm/DWARFLinkerParallel/DWARFFile.h"
 #include <optional>
 
@@ -20,6 +19,26 @@ namespace dwarflinker_parallel {
 using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
 
 struct AttributesInfo;
+class SyntheticTypeNameBuilder;
+class DIEGenerator;
+class TypeUnit;
+class DependencyTracker;
+
+class CompileUnit;
+
+/// This is a helper structure which keeps a debug info entry
+/// with it's containing compilation unit.
+struct UnitEntryPairTy {
+  UnitEntryPairTy() = default;
+  UnitEntryPairTy(CompileUnit *CU, const DWARFDebugInfoEntry *DieEntry)
+      : CU(CU), DieEntry(DieEntry) {}
+
+  CompileUnit *CU = nullptr;
+  const DWARFDebugInfoEntry *DieEntry = nullptr;
+
+  UnitEntryPairTy getNamespaceOrigin();
+  std::optional<UnitEntryPairTy> getParent();
+};
 
 enum ResolveInterCUReferencesMode : bool {
   Resolve = true,
@@ -42,6 +61,13 @@ class CompileUnit : public DwarfUnit {
     /// discovered, type names are assigned if ODR is requested).
     LivenessAnalysisDone,
 
+    /// Check if dependencies have incompatible placement.
+    /// If that is the case modify placement to be compatible.
+    UpdateDependenciesCompleteness,
+
+    /// Type names assigned to DIEs.
+    TypeNamesAssigned,
+
     /// Output DWARF is generated.
     Cloned,
 
@@ -50,38 +76,20 @@ class CompileUnit : public DwarfUnit {
 
     /// Resources(Input DWARF, Output DWARF tree) are released.
     Cleaned,
+
+    /// Compile Unit should be skipped
+    Skipped
   };
 
   CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
               StringRef ClangModuleName, DWARFFile &File,
               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
-              llvm::endianness Endianess)
-      : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
-        getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded) {
-    UnitName = File.FileName;
-    setOutputFormat(Format, Endianess);
-  }
+              llvm::endianness Endianess);
 
   CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, unsigned ID,
               StringRef ClangModuleName, DWARFFile &File,
               OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format,
-              llvm::endianness Endianess)
-      : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
-        OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
-        Stage(Stage::CreatedNotLoaded) {
-    DWARFDie CUDie = OrigUnit.getUnitDIE();
-    if (!CUDie)
-      return;
-
-    setOutputFormat(Format, Endianess);
-
-    Language = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language), 0);
-    if (const char *CUName = CUDie.getName(DINameKind::ShortName))
-      UnitName = CUName;
-    else
-      UnitName = File.FileName;
-    SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();
-  }
+              llvm::endianness Endianess);
 
   /// Returns stage of overall processing.
   Stage getStage() const { return Stage; }
@@ -114,7 +122,7 @@ class CompileUnit : public DwarfUnit {
 
   /// Navigate DWARF tree and set die properties.
   void analyzeDWARFStructure() {
-    analyzeDWARFStructureRec(getUnitDIE().getDebugInfoEntry(), false, false);
+    analyzeDWARFStructureRec(getUnitDIE().getDebugInfoEntry(), false);
   }
 
   /// Cleanup unneeded resources after compile unit is cloned.
@@ -124,25 +132,34 @@ class CompileUnit : public DwarfUnit {
   /// This method copies output offsets for referenced DIEs into DIEs patches.
   void updateDieRefPatchesWithClonedOffsets();
 
+  /// Search for subprograms and variables referencing live code and discover
+  /// dependend DIEs. Mark live DIEs, set placement for DIEs.
+  bool resolveDependenciesAndMarkLiveness(
+      bool InterCUProcessingStarted,
+      std::atomic<bool> &HasNewInterconnectedCUs);
+
+  /// Check dependend DIEs for incompatible placement.
+  /// Make placement to be consistent.
+  bool updateDependenciesCompleteness();
+
+  /// Check DIEs to have a consistent marking(keep marking, placement marking).
+  void verifyDependencies();
+
+  /// Search for type entries and assign names.
+  Error assignTypeNames(TypePool &TypePoolRef);
+
   /// Kinds of placement for the output die.
   enum DieOutputPlacement : uint8_t {
     NotSet = 0,
 
     /// Corresponding DIE goes to the type table only.
-    /// NOTE: Not used yet.
     TypeTable = 1,
 
     /// Corresponding DIE goes to the plain dwarf only.
     PlainDwarf = 2,
 
     /// Corresponding DIE goes to type table and to plain dwarf.
-    /// NOTE: Not used yet.
     Both = 3,
-
-    /// Corresponding DIE needs to examine parent to determine
-    /// the point of placement.
-    /// NOTE: Not used yet.
-    Parent = 4
   };
 
   /// Information gathered about source DIEs.
@@ -204,10 +221,10 @@ class CompileUnit : public DwarfUnit {
     SINGLE_FLAG_METHODS_SET(Keep, 0x08)
 
     /// DIE has children which are part of the linked output.
-    SINGLE_FLAG_METHODS_SET(KeepChildren, 0x10)
+    SINGLE_FLAG_METHODS_SET(KeepPlainChildren, 0x10)
 
-    /// DIE is referenced by other DIE.
-    SINGLE_FLAG_METHODS_SET(ReferrencedBy, 0x20)
+    /// DIE has children which are part of the type table.
+    SINGLE_FLAG_METHODS_SET(KeepTypeChildren, 0x20)
 
     /// DIE is in module scope.
     SINGLE_FLAG_METHODS_SET(IsInMouduleScope, 0x40)
@@ -215,6 +232,18 @@ class CompileUnit : public DwarfUnit {
     /// DIE is in function scope.
     SINGLE_FLAG_METHODS_SET(IsInFunctionScope, 0x80)
 
+    /// DIE is in anonymous namespace scope.
+    SINGLE_FLAG_METHODS_SET(IsInAnonNamespaceScope, 0x100)
+
+    /// DIE is available for ODR type deduplication.
+    SINGLE_FLAG_METHODS_SET(ODRAvailable, 0x200)
+
+    /// Track liveness for the DIE.
+    SINGLE_FLAG_METHODS_SET(TrackLiveness, 0x400)
+
+    /// Track liveness for the DIE.
+    SINGLE_FLAG_METHODS_SET(HasAnAddress, 0x800)
+
     void unsetFlagsWhichSetDuringLiveAnalysis() {
       auto InputData = Flags.load();
       while (!Flags.compare_exchange_weak(
@@ -228,6 +257,18 @@ class CompileUnit : public DwarfUnit {
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     LLVM_DUMP_METHOD void dump();
 #endif
+
+    bool needToPlaceInTypeTable() const {
+      return (getKeep() && (getPlacement() == CompileUnit::TypeTable ||
+                            getPlacement() == CompileUnit::Both)) ||
+             getKeepTypeChildren();
+    }
+
+    bool needToKeepInPlainDwarf() const {
+      return (getKeep() && (getPlacement() == CompileUnit::PlainDwarf ||
+                            getPlacement() == CompileUnit::Both)) ||
+             getKeepPlainChildren();
+    }
   };
 
   /// \defgroup Group of functions returning DIE info.
@@ -273,6 +314,29 @@ class CompileUnit : public DwarfUnit {
         ->load();
   }
 
+  /// \p Idx index of the DIE.
+  /// \returns type entry.
+  TypeEntry *getDieTypeEntry(uint32_t Idx) {
+    return reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
+        ->load();
+  }
+
+  /// \p InputDieEntry debug info entry.
+  /// \returns DieInfo descriptor.
+  uint64_t getDieOutOffset(const DWARFDebugInfoEntry *InputDieEntry) {
+    return reinterpret_cast<std::atomic<uint64_t> *>(
+               &OutDieOffsetArray[getOrigUnit().getDIEIndex(InputDieEntry)])
+        ->load();
+  }
+
+  /// \p InputDieEntry debug info entry.
+  /// \returns type entry.
+  TypeEntry *getDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry) {
+    return reinterpret_cast<std::atomic<TypeEntry *> *>(
+               &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
+        ->load();
+  }
+
   /// \p Idx index of the DIE.
   /// \returns DieInfo descriptor.
   void rememberDieOutOffset(uint32_t Idx, uint64_t Offset) {
@@ -280,6 +344,22 @@ class CompileUnit : public DwarfUnit {
         ->store(Offset);
   }
 
+  /// \p Idx index of the DIE.
+  /// \p Type entry.
+  void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry) {
+    reinterpret_cast<std::atomic<TypeEntry *> *>(&TypeEntries[Idx])
+        ->store(Entry);
+  }
+
+  /// \p InputDieEntry debug info entry.
+  /// \p Type entry.
+  void setDieTypeEntry(const DWARFDebugInfoEntry *InputDieEntry,
+                       TypeEntry *Entry) {
+    reinterpret_cast<std::atomic<TypeEntry *> *>(
+        &TypeEntries[getOrigUnit().getDIEIndex(InputDieEntry)])
+        ->store(Entry);
+  }
+
   /// @}
 
   /// Returns value of DW_AT_low_pc attribute.
@@ -299,9 +379,15 @@ class CompileUnit : public DwarfUnit {
   /// RefValue. The resulting DIE might be in another CompileUnit.
   /// \returns referenced die and corresponding compilation unit.
   ///          compilation unit is null if reference could not be resolved.
-  std::optional<std::pair<CompileUnit *, uint32_t>>
+  std::optional<UnitEntryPairTy>
   resolveDIEReference(const DWARFFormValue &RefValue,
                       ResolveInterCUReferencesMode CanResolveInterCUReferences);
+
+  std::optional<UnitEntryPairTy>
+  resolveDIEReference(const DWARFDebugInfoEntry *DieEntry,
+                      dwarf::Attribute Attr,
+                      ResolveInterCUReferencesMode CanResolveInterCUReferences);
+
   /// @}
 
   /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
@@ -312,7 +398,8 @@ class CompileUnit : public DwarfUnit {
   const RangesTy &getFunctionRanges() const { return Ranges; }
 
   /// Clone and emit this compilation unit.
-  Error cloneAndEmit(std::optional<Triple> TargetTriple);
+  Error cloneAndEmit(std::optional<Triple> TargetTriple,
+                     TypeUnit *ArtificialTypeUnit);
 
   /// Clone and emit debug locations(.debug_loc/.debug_loclists).
   Error cloneAndEmitDebugLocations();
@@ -324,10 +411,12 @@ class CompileUnit : public DwarfUnit {
   Error cloneAndEmitDebugMacro();
 
   // Clone input DIE entry.
-  DIE *cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, uint64_t OutOffset,
-                std::optional<int64_t> FuncAddressAdjustment,
-                std::optional<int64_t> VarAddressAdjustment,
-                BumpPtrAllocator &Allocator);
+  std::pair<DIE *, TypeEntry *>
+  cloneDIE(const DWARFDebugInfoEntry *InputDieEntry,
+           TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset,
+           std::optional<int64_t> FuncAddressAdjustment,
+           std::optional<int64_t> VarAddressAdjustment,
+           BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
 
   // Clone and emit line table.
   Error cloneAndEmitLineTable(Triple &TargetTriple);
@@ -344,10 +433,13 @@ class CompileUnit : public DwarfUnit {
     return DebugAddrIndexMap.getValueIndex(Addr);
   }
 
-  /// Returns index(inside .debug_str_offsets) of specified string.
-  uint64_t getDebugStrIndex(const StringEntry *String) {
-    return DebugStringIndexMap.getValueIndex(String);
-  }
+  /// Returns directory and file from the line table by index.
+  std::optional<std::pair<StringRef, StringRef>>
+  getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue);
+
+  /// Returns directory and file from the line table by index.
+  std::optional<std::pair<StringRef, StringRef>>
+  getDirAndFilenameFromLineTable(uint64_t FileIdx);
 
   /// \defgroup Helper methods to access OrigUnit.
   ///
@@ -469,10 +561,44 @@ class CompileUnit : public DwarfUnit {
 
   /// @}
 
+  /// Save specified accelerator info \p Info.
+  void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info) {
+    AcceleratorRecords.add(Info);
+  }
+
+  /// Enumerates all units accelerator records.
+  void
+  forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
+    AcceleratorRecords.forEach(Handler);
+  }
+
+  /// Output unit selector.
+  class OutputUnitVariantPtr {
+  public:
+    OutputUnitVariantPtr(CompileUnit *U);
+    OutputUnitVariantPtr(TypeUnit *U);
+
+    /// Accessor for common functionality.
+    DwarfUnit *operator->();
+
+    bool isCompileUnit();
+
+    bool isTypeUnit();
+
+    /// Returns CompileUnit if applicable.
+    CompileUnit *getAsCompileUnit();
+
+    /// Returns TypeUnit if applicable.
+    TypeUnit *getAsTypeUnit();
+
+  protected:
+    PointerUnion<CompileUnit *, TypeUnit *> Ptr;
+  };
+
 private:
   /// Navigate DWARF tree recursively and set die properties.
   void analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
-                                bool IsInModule, bool IsInFunction);
+                                bool IsODRUnavailableFunctionScope);
 
   struct LinkedLocationExpressionsWithOffsetPatches {
     DWARFLocationExpression Expression;
@@ -495,9 +621,6 @@ class CompileUnit : public DwarfUnit {
   /// Emit the .debug_addr section fragment for current unit.
   Error emitDebugAddrSection();
 
-  /// Emit the .debug_str_offsets section for current unit.
-  Error emitDebugStringOffsetSection();
-
   /// Emit .debug_aranges.
   void emitAranges(AddressRanges &LinkedFunctionRanges);
 
@@ -521,13 +644,25 @@ class CompileUnit : public DwarfUnit {
   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
                           uint64_t OffsetToMacroTable, bool hasDWARFv5Header);
 
-  /// Store accelerator information for the \p InputDieEntry.
-  void rememberAcceleratorEntries(const DWARFDebugInfoEntry *InputDieEntry,
-                                  uint64_t OutOffset, AttributesInfo &AttrInfo);
+  /// Creates DIE which would be placed into the "Plain" compile unit.
+  DIE *createPlainDIEandCloneAttributes(
+      const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
+      uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
+      std::optional<int64_t> &VarAddressAdjustment);
+
+  /// Creates DIE which would be placed into the "Type" compile unit.
+  TypeEntry *createTypeDIEandCloneAttributes(
+      const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
+      TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit);
+
+  /// Create output DIE inside specified \p TypeDescriptor.
+  DIE *allocateTypeDie(TypeEntryBody *TypeDescriptor,
+                       DIEGenerator &TypeDIEGenerator, dwarf::Tag DieTag,
+                       bool IsDeclaration, bool IsParentDeclaration);
 
-  /// Store ObjC accelerator information for the \p InputDieEntry.
-  void rememberObjCAccelerator(const DWARFDebugInfoEntry *InputDieEntry,
-                               uint64_t OutOffset, AttributesInfo &AttrInfo);
+  /// Enumerate \p DieEntry children and assign names for them.
+  Error assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
+                           SyntheticTypeNameBuilder &NameBuilder);
 
   /// DWARFFile containing this compile unit.
   DWARFFile &File;
@@ -535,6 +670,9 @@ class CompileUnit : public DwarfUnit {
   /// Pointer to the paired compile unit from the input DWARF.
   DWARFUnit *OrigUnit = nullptr;
 
+  /// The DW_AT_language of this unit.
+  std::optional<uint16_t> Language;
+
   /// Line table for this unit.
   const DWARFDebugLine::LineTable *LineTablePtr = nullptr;
 
@@ -547,10 +685,9 @@ class CompileUnit : public DwarfUnit {
   /// Maps an address into the index inside .debug_addr section.
   IndexedValuesMap<uint64_t> DebugAddrIndexMap;
 
-  /// Maps a string into the index inside .debug_str_offsets section.
-  IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
+  std::unique_ptr<DependencyTracker> Dependencies;
 
-  /// \defgroup Data Members accessed asinchroniously.
+  /// \defgroup Data Members accessed asinchronously.
   ///
   /// @{
   OffsetToUnitTy getUnitFromOffset;
@@ -558,6 +695,9 @@ class CompileUnit : public DwarfUnit {
   std::optional<uint64_t> LowPc;
   uint64_t HighPc = 0;
 
+  /// Flag indicating whether type de-duplication is forbidden.
+  bool NoODR = true;
+
   /// The ranges in that map are the PC ranges for functions in this unit,
   /// associated with the PC offset to apply to the addresses to get
   /// the linked address.
@@ -565,7 +705,8 @@ class CompileUnit : public DwarfUnit {
   std::mutex RangesMutex;
 
   /// The DW_AT_low_pc of each DW_TAG_label.
-  SmallDenseMap<uint64_t, uint64_t, 1> Labels;
+  using LabelMapTy = SmallDenseMap<uint64_t, uint64_t, 1>;
+  LabelMapTy Labels;
   std::mutex LabelsMutex;
 
   /// This field keeps current stage of overall compile unit processing.
@@ -574,9 +715,19 @@ class CompileUnit : public DwarfUnit {
   /// DIE info indexed by DIE index.
   SmallVector<DIEInfo> DieInfoArray;
   SmallVector<uint64_t> OutDieOffsetArray;
+  SmallVector<TypeEntry *> TypeEntries;
+
+  /// The list of accelerator records for this unit.
+  ArrayList<AccelInfo> AcceleratorRecords;
   /// @}
 };
 
+/// \returns list of attributes referencing type DIEs which might be
+/// deduplicated.
+/// Note: it does not include DW_AT_containing_type attribute to avoid
+/// infinite recursion.
+ArrayRef<dwarf::Attribute> getODRAttributes();
+
 } // end of namespace dwarflinker_parallel
 } // end namespace llvm
 
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h
index 78d0b5468d0495e..220739a1214c690 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERGLOBALDATA_H
 #define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERGLOBALDATA_H
 
+#include "TypePool.h"
 #include "llvm/DWARFLinkerParallel/DWARFLinker.h"
 #include "llvm/DWARFLinkerParallel/StringPool.h"
 #include "llvm/Support/PerThreadBumpPtrAllocator.h"
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
index a755d540aef99e1..c49b9ef0cdf989d 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
@@ -9,6 +9,8 @@
 #include "DWARFLinkerImpl.h"
 #include "DIEGenerator.h"
 #include "DependencyTracker.h"
+#include "Utils.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/ThreadPool.h"
@@ -16,6 +18,50 @@
 namespace llvm {
 namespace dwarflinker_parallel {
 
+DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
+                                 MessageHandlerTy WarningHandler,
+                                 TranslatorFuncTy StringsTranslator)
+    : UniqueUnitID(0), DebugStrStrings(GlobalData),
+      DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
+  GlobalData.setTranslator(StringsTranslator);
+  GlobalData.setErrorHandler(ErrorHandler);
+  GlobalData.setWarningHandler(WarningHandler);
+}
+
+DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
+                                          DWARFFile &File,
+                                          StringMap<uint64_t> &ClangModules,
+                                          std::atomic<size_t> &UniqueUnitID,
+                                          std::optional<Triple> TargetTriple)
+    : OutputSections(GlobalData), InputDWARFFile(File),
+      ClangModules(ClangModules), TargetTriple(TargetTriple),
+      UniqueUnitID(UniqueUnitID) {
+
+  if (File.Dwarf) {
+    if (!File.Dwarf->compile_units().empty())
+      CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
+
+    // Set context format&endianness based on the input file.
+    Format.Version = File.Dwarf->getMaxVersion();
+    Format.AddrSize = File.Dwarf->getCUAddrSize();
+    Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
+                                              : llvm::endianness::big;
+  }
+}
+
+DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
+    DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
+    : File(File), Unit(std::move(Unit)) {}
+
+DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
+    LinkContext::RefModuleUnit &&Other)
+    : File(Other.File), Unit(std::move(Other.Unit)) {}
+
+void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
+    LinkContext::RefModuleUnit &&Unit) {
+  ModulesCompileUnits.emplace_back(std::move(Unit));
+}
+
 Error DWARFLinkerImpl::createEmitter(const Triple &TheTriple,
                                      OutputFileType FileType,
                                      raw_pwrite_stream &OutFile) {
@@ -55,6 +101,10 @@ void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
   }
 }
 
+void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
+  ObjectContexts.reserve(ObjFilesNum);
+}
+
 Error DWARFLinkerImpl::link() {
   // reset compile unit unique ID counter.
   UniqueUnitID = 0;
@@ -71,6 +121,7 @@ Error DWARFLinkerImpl::link() {
                            ? llvm::endianness::little
                            : llvm::endianness::big;
   }
+  std::optional<uint16_t> Language;
 
   for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
     if (Context->InputDWARFFile.Dwarf.get() == nullptr) {
@@ -101,6 +152,23 @@ Error DWARFLinkerImpl::link() {
         std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
 
     Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
+
+    // FIXME: move creation of CompileUnits into the addObjectFile.
+    // This would allow to not scan for context Language and Modules state
+    // twice. And then following handling might be removed.
+    for (const std::unique_ptr<DWARFUnit> &OrigCU :
+         Context->InputDWARFFile.Dwarf->compile_units()) {
+      DWARFDie UnitDie = OrigCU.get()->getUnitDIE();
+
+      if (!Language) {
+        if (std::optional<DWARFFormValue> Val =
+                UnitDie.find(dwarf::DW_AT_language)) {
+          uint16_t LangVal = dwarf::toUnsigned(Val, 0);
+          if (isODRLanguage(LangVal))
+            Language = LangVal;
+        }
+      }
+    }
   }
 
   if (GlobalFormat.AddrSize == 0) {
@@ -113,6 +181,14 @@ Error DWARFLinkerImpl::link() {
 
   CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
 
+  if (!GlobalData.Options.NoODR && Language.has_value()) {
+    parallel::TaskGroup TGroup;
+    TGroup.spawn([&]() {
+      ArtificialTypeUnit = std::make_unique<TypeUnit>(
+          GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
+    });
+  }
+
   // Set parallel options.
   if (GlobalData.getOptions().Threads == 0)
     parallel::strategy = optimal_concurrency(OverallNumberOfCU);
@@ -123,7 +199,7 @@ Error DWARFLinkerImpl::link() {
   if (GlobalData.getOptions().Threads == 1) {
     for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
       // Link object file.
-      if (Error Err = Context->link())
+      if (Error Err = Context->link(ArtificialTypeUnit.get()))
         GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
 
       Context->InputDWARFFile.unload();
@@ -133,7 +209,7 @@ Error DWARFLinkerImpl::link() {
     for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
       Pool.async([&]() {
         // Link object file.
-        if (Error Err = Context->link())
+        if (Error Err = Context->link(ArtificialTypeUnit.get()))
           GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
 
         Context->InputDWARFFile.unload();
@@ -142,6 +218,19 @@ Error DWARFLinkerImpl::link() {
     Pool.wait();
   }
 
+  if (ArtificialTypeUnit.get() != nullptr && !ArtificialTypeUnit->getTypePool()
+                                                  .getRoot()
+                                                  ->getValue()
+                                                  .load()
+                                                  ->Children.empty()) {
+    std::optional<Triple> OutTriple = TheDwarfEmitter.get() == nullptr
+                                          ? std::optional<Triple>(std::nullopt)
+                                          : TheDwarfEmitter->getTargetTriple();
+
+    if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(OutTriple))
+      return Err;
+  }
+
   // At this stage each compile units are cloned to their own set of debug
   // sections. Now, update patches, assign offsets and assemble final file
   // glueing debug tables from each compile unit.
@@ -175,6 +264,11 @@ Error DWARFLinkerImpl::validateAndUpdateOptions() {
         "set number of threads to 1 to make --verbose to work properly.", "");
   }
 
+  // Do not do types deduplication in case --update.
+  if (GlobalData.getOptions().UpdateIndexTablesOnly &&
+      !GlobalData.Options.NoODR)
+    GlobalData.Options.NoODR = true;
+
   return Error::success();
 }
 
@@ -369,7 +463,7 @@ Error DWARFLinkerImpl::LinkContext::loadClangModule(
   return Error::success();
 }
 
-Error DWARFLinkerImpl::LinkContext::link() {
+Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
   InterCUProcessingStarted = false;
   if (!InputDWARFFile.Dwarf)
     return Error::success();
@@ -380,7 +474,7 @@ Error DWARFLinkerImpl::LinkContext::link() {
 
   // Link modules compile units first.
   parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {
-    linkSingleCompileUnit(*RefModule.Unit);
+    linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit);
   });
 
   // Check for live relocations. If there is no any live relocation then we
@@ -420,43 +514,78 @@ Error DWARFLinkerImpl::LinkContext::link() {
     // Link self-sufficient compile units and discover inter-connected compile
     // units.
     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-      linkSingleCompileUnit(*CU);
+      linkSingleCompileUnit(*CU, ArtificialTypeUnit);
     });
 
     // Link all inter-connected units.
     if (HasNewInterconnectedCUs) {
       InterCUProcessingStarted = true;
 
-      do {
-        HasNewInterconnectedCUs = false;
-
-        // Load inter-connected units.
-        parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-          if (CU->isInterconnectedCU()) {
-            CU->maybeResetToLoadedStage();
-            linkSingleCompileUnit(*CU, CompileUnit::Stage::Loaded);
-          }
-        });
+      if (Error Err = finiteLoop([&]() -> Expected<bool> {
+            HasNewInterconnectedCUs = false;
+
+            // Load inter-connected units.
+            parallelForEach(
+                CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+                  if (CU->isInterconnectedCU()) {
+                    CU->maybeResetToLoadedStage();
+                    linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                                          CompileUnit::Stage::Loaded);
+                  }
+                });
+
+            // Do liveness analysis for inter-connected units.
+            parallelForEach(CompileUnits,
+                            [&](std::unique_ptr<CompileUnit> &CU) {
+                              linkSingleCompileUnit(
+                                  *CU, ArtificialTypeUnit,
+                                  CompileUnit::Stage::LivenessAnalysisDone);
+                            });
+
+            return HasNewInterconnectedCUs.load();
+          }))
+        return Err;
+
+      // Update dependencies.
+      if (Error Err = finiteLoop([&]() -> Expected<bool> {
+            HasNewGlobalDependency = false;
+            parallelForEach(
+                CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+                  linkSingleCompileUnit(
+                      *CU, ArtificialTypeUnit,
+                      CompileUnit::Stage::UpdateDependenciesCompleteness);
+                });
+            return HasNewGlobalDependency.load();
+          }))
+        return Err;
+      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+        if (CU->isInterconnectedCU() &&
+            CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
+          CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
+      });
 
-        // Do liveness analysis for inter-connected units.
-        parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-          linkSingleCompileUnit(*CU, CompileUnit::Stage::LivenessAnalysisDone);
-        });
-      } while (HasNewInterconnectedCUs);
+      // Assign type names.
+      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                              CompileUnit::Stage::TypeNamesAssigned);
+      });
 
       // Clone inter-connected units.
       parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, CompileUnit::Stage::Cloned);
+        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                              CompileUnit::Stage::Cloned);
       });
 
       // Update patches for inter-connected units.
       parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, CompileUnit::Stage::PatchesUpdated);
+        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                              CompileUnit::Stage::PatchesUpdated);
       });
 
       // Release data.
       parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, CompileUnit::Stage::Cleaned);
+        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                              CompileUnit::Stage::Cleaned);
       });
     }
 
@@ -483,78 +612,119 @@ Error DWARFLinkerImpl::LinkContext::link() {
 }
 
 void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
-    CompileUnit &CU, enum CompileUnit::Stage DoUntilStage) {
-  while (CU.getStage() < DoUntilStage) {
-    if (InterCUProcessingStarted != CU.isInterconnectedCU())
-      return;
+    CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
+    enum CompileUnit::Stage DoUntilStage) {
+  if (InterCUProcessingStarted != CU.isInterconnectedCU())
+    return;
 
-    switch (CU.getStage()) {
-    case CompileUnit::Stage::CreatedNotLoaded: {
-      // Load input compilation unit DIEs.
-      // Analyze properties of DIEs.
-      if (!CU.loadInputDIEs()) {
-        // We do not need to do liveness analysis for invalud compilation unit.
-        CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
-      } else {
-        CU.analyzeDWARFStructure();
-
-        // The registerModuleReference() condition effectively skips
-        // over fully resolved skeleton units. This second pass of
-        // registerModuleReferences doesn't do any new work, but it
-        // will collect top-level errors, which are suppressed. Module
-        // warnings were already displayed in the first iteration.
-        if (registerModuleReference(
-                CU.getOrigUnit().getUnitDIE(), nullptr,
-                [](const DWARFUnit &) {}, 0))
-          CU.setStage(CompileUnit::Stage::PatchesUpdated);
-        else
-          CU.setStage(CompileUnit::Stage::Loaded);
-      }
-    } break;
+  if (Error Err = finiteLoop([&]() -> Expected<bool> {
+        if (CU.getStage() >= DoUntilStage)
+          return false;
+
+        switch (CU.getStage()) {
+        case CompileUnit::Stage::CreatedNotLoaded: {
+          // Load input compilation unit DIEs.
+          // Analyze properties of DIEs.
+          if (!CU.loadInputDIEs()) {
+            // We do not need to do liveness analysis for invalid compilation
+            // unit.
+            CU.setStage(CompileUnit::Stage::Skipped);
+          } else {
+            CU.analyzeDWARFStructure();
+
+            // The registerModuleReference() condition effectively skips
+            // over fully resolved skeleton units. This second pass of
+            // registerModuleReferences doesn't do any new work, but it
+            // will collect top-level errors, which are suppressed. Module
+            // warnings were already displayed in the first iteration.
+            if (registerModuleReference(
+                    CU.getOrigUnit().getUnitDIE(), nullptr,
+                    [](const DWARFUnit &) {}, 0))
+              CU.setStage(CompileUnit::Stage::PatchesUpdated);
+            else
+              CU.setStage(CompileUnit::Stage::Loaded);
+          }
+        } break;
 
-    case CompileUnit::Stage::Loaded: {
-      // Mark all the DIEs that need to be present in the generated output.
-      // If ODR requested, build type names.
-      if (!DependencyTracker(*this).resolveDependenciesAndMarkLiveness(CU)) {
-        assert(HasNewInterconnectedCUs);
-        return;
-      }
+        case CompileUnit::Stage::Loaded: {
+          // Mark all the DIEs that need to be present in the generated output.
+          // If ODR requested, build type names.
+          if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
+                                                     HasNewInterconnectedCUs)) {
+            assert(HasNewInterconnectedCUs &&
+                   "Flag indicating new inter-connections is not set");
+            return false;
+          }
 
-      CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
-    } break;
+          CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
+        } break;
 
-    case CompileUnit::Stage::LivenessAnalysisDone:
+        case CompileUnit::Stage::LivenessAnalysisDone: {
+          if (InterCUProcessingStarted) {
+            if (CU.updateDependenciesCompleteness())
+              HasNewGlobalDependency = true;
+            return false;
+          } else {
+            if (Error Err = finiteLoop([&]() -> Expected<bool> {
+                  return CU.updateDependenciesCompleteness();
+                }))
+              return std::move(Err);
+
+            CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
+          }
+        } break;
 
+        case CompileUnit::Stage::UpdateDependenciesCompleteness:
 #ifndef NDEBUG
-      DependencyTracker::verifyKeepChain(CU);
+          CU.verifyDependencies();
 #endif
 
-      // Clone input compile unit.
-      if (CU.isClangModule() || GlobalData.getOptions().UpdateIndexTablesOnly ||
-          CU.getContaingFile().Addresses->hasValidRelocs()) {
-        if (Error Err = CU.cloneAndEmit(TargetTriple))
-          CU.error(std::move(Err));
-      }
+          if (ArtificialTypeUnit) {
+            if (Error Err =
+                    CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
+              return std::move(Err);
+          }
+          CU.setStage(CompileUnit::Stage::TypeNamesAssigned);
+          break;
+
+        case CompileUnit::Stage::TypeNamesAssigned:
+          // Clone input compile unit.
+          if (CU.isClangModule() ||
+              GlobalData.getOptions().UpdateIndexTablesOnly ||
+              CU.getContaingFile().Addresses->hasValidRelocs()) {
+            if (Error Err = CU.cloneAndEmit(TargetTriple, ArtificialTypeUnit))
+              return std::move(Err);
+          }
 
-      CU.setStage(CompileUnit::Stage::Cloned);
-      break;
+          CU.setStage(CompileUnit::Stage::Cloned);
+          break;
 
-    case CompileUnit::Stage::Cloned:
-      // Update DIEs referencies.
-      CU.updateDieRefPatchesWithClonedOffsets();
-      CU.setStage(CompileUnit::Stage::PatchesUpdated);
-      break;
+        case CompileUnit::Stage::Cloned:
+          // Update DIEs referencies.
+          CU.updateDieRefPatchesWithClonedOffsets();
+          CU.setStage(CompileUnit::Stage::PatchesUpdated);
+          break;
 
-    case CompileUnit::Stage::PatchesUpdated:
-      // Cleanup resources.
-      CU.cleanupDataAfterClonning();
-      CU.setStage(CompileUnit::Stage::Cleaned);
-      break;
+        case CompileUnit::Stage::PatchesUpdated:
+          // Cleanup resources.
+          CU.cleanupDataAfterClonning();
+          CU.setStage(CompileUnit::Stage::Cleaned);
+          break;
 
-    case CompileUnit::Stage::Cleaned:
-      assert(false);
-      break;
-    }
+        case CompileUnit::Stage::Cleaned:
+          assert(false);
+          break;
+
+        case CompileUnit::Stage::Skipped:
+          // Nothing to do.
+          break;
+        }
+
+        return true;
+      })) {
+    CU.error(std::move(Err));
+    CU.cleanupDataAfterClonning();
+    CU.setStage(CompileUnit::Stage::Skipped);
   }
 }
 
@@ -716,6 +886,9 @@ void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
   // units into the resulting file.
   emitCommonSectionsAndWriteCompileUnitsToTheOutput();
 
+  if (ArtificialTypeUnit.get() != nullptr)
+    ArtificialTypeUnit.reset();
+
   // Write common debug sections into the resulting file.
   writeCommonSectionsToTheOutput();
 
@@ -861,47 +1034,101 @@ void DWARFLinkerImpl::forEachOutputString(
       });
     });
 
-    CU->AcceleratorRecords.forEach([&](DwarfUnit::AccelInfo &Info) {
+    CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
       StringHandler(DebugStr, Info.String);
     });
   });
+
+  if (ArtificialTypeUnit.get() != nullptr) {
+    ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
+      OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
+        StringHandler(StringDestinationKind::DebugStr, Patch.String);
+      });
+
+      OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
+        StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
+      });
+
+      OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
+        if (Patch.Die == nullptr)
+          return;
+
+        StringHandler(StringDestinationKind::DebugStr, Patch.String);
+      });
+
+      OutSection.ListDebugTypeLineStrPatch.forEach(
+          [&](DebugTypeLineStrPatch &Patch) {
+            if (Patch.Die == nullptr)
+              return;
+
+            StringHandler(StringDestinationKind::DebugStr, Patch.String);
+          });
+    });
+  }
 }
 
 void DWARFLinkerImpl::forEachObjectSectionsSet(
     function_ref<void(OutputSections &)> SectionsSetHandler) {
-  // Handle all modules first(before regular compilation units).
+  // Handle artificial type unit first.
+  if (ArtificialTypeUnit.get() != nullptr)
+    SectionsSetHandler(*ArtificialTypeUnit);
+
+  // Then all modules(before regular compilation units).
   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
-      SectionsSetHandler(*ModuleUnit.Unit);
+      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
+        SectionsSetHandler(*ModuleUnit.Unit);
 
+  // Finally all compilation units.
   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
     // Handle object file common sections.
     SectionsSetHandler(*Context);
 
     // Handle compilation units.
     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
-      SectionsSetHandler(*CU);
+      if (CU->getStage() != CompileUnit::Stage::Skipped)
+        SectionsSetHandler(*CU);
   }
 }
 
+void DWARFLinkerImpl::forEachCompileAndTypeUnit(
+    function_ref<void(DwarfUnit *CU)> UnitHandler) {
+  if (ArtificialTypeUnit.get() != nullptr)
+    UnitHandler(ArtificialTypeUnit.get());
+
+  // Enumerate module units.
+  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
+    for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
+      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
+        UnitHandler(ModuleUnit.Unit.get());
+
+  // Enumerate compile units.
+  for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
+    for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
+      if (CU->getStage() != CompileUnit::Stage::Skipped)
+        UnitHandler(CU.get());
+}
+
 void DWARFLinkerImpl::forEachCompileUnit(
     function_ref<void(CompileUnit *CU)> UnitHandler) {
   // Enumerate module units.
   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
-      UnitHandler(ModuleUnit.Unit.get());
+      if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
+        UnitHandler(ModuleUnit.Unit.get());
 
   // Enumerate compile units.
   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
-      UnitHandler(CU.get());
+      if (CU->getStage() != CompileUnit::Stage::Skipped)
+        UnitHandler(CU.get());
 }
 
 void DWARFLinkerImpl::patchOffsetsAndSizes() {
   forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
     SectionsSet.forEach([&](SectionDescriptor &OutSection) {
-      SectionsSet.applyPatches(OutSection, DebugStrStrings,
-                               DebugLineStrStrings);
+      SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
+                               ArtificialTypeUnit.get());
     });
   });
 }
@@ -1005,8 +1232,9 @@ void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
   AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
   AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
 
-  forEachCompileUnit([&](CompileUnit *CU) {
-    CU->AcceleratorRecords.forEach([&](const DwarfUnit::AccelInfo &Info) {
+  forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
+    CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
+      uint64_t OutOffset = Info.OutOffset;
       switch (Info.Type) {
       case DwarfUnit::AccelType::None: {
         llvm_unreachable("Unknown accelerator record");
@@ -1015,25 +1243,25 @@ void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
         AppleNamespaces.addName(
             *DebugStrStrings.getExistingEntry(Info.String),
             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
-                Info.OutOffset);
+                OutOffset);
       } break;
       case DwarfUnit::AccelType::Name: {
         AppleNames.addName(
             *DebugStrStrings.getExistingEntry(Info.String),
             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
-                Info.OutOffset);
+                OutOffset);
       } break;
       case DwarfUnit::AccelType::ObjC: {
         AppleObjC.addName(
             *DebugStrStrings.getExistingEntry(Info.String),
             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
-                Info.OutOffset);
+                OutOffset);
       } break;
       case DwarfUnit::AccelType::Type: {
         AppleTypes.addName(
             *DebugStrStrings.getExistingEntry(Info.String),
             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
-                Info.OutOffset,
+                OutOffset,
             Info.Tag,
             Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
                                          : 0,
@@ -1136,16 +1364,13 @@ void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
 
   unsigned Id = 0;
 
-  forEachCompileUnit([&](CompileUnit *CU) {
-    CompUnits.push_back(
-        CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
-            .StartOffset);
-    CUidToIdx[CU->getUniqueID()] = Id++;
-
-    CU->AcceleratorRecords.forEach([&](const DwarfUnit::AccelInfo &Info) {
+  forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
+    bool HasRecords = false;
+    CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
       if (DebugNames.get() == nullptr)
         DebugNames = std::make_unique<DWARF5AccelTable>();
 
+      HasRecords = true;
       switch (Info.Type) {
       case DwarfUnit::AccelType::Name:
       case DwarfUnit::AccelType::Namespace:
@@ -1158,6 +1383,13 @@ void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
         break; // Nothing to do.
       };
     });
+
+    if (HasRecords) {
+      CompUnits.push_back(
+          CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
+              .StartOffset);
+      CUidToIdx[CU->getUniqueID()] = Id++;
+    }
   });
 
   if (DebugNames.get() != nullptr) {
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h
index 45dc506b9947ea1..60018eea121f204 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h
@@ -11,6 +11,7 @@
 
 #include "DWARFEmitterImpl.h"
 #include "DWARFLinkerCompileUnit.h"
+#include "DWARFLinkerTypeUnit.h"
 #include "StringEntryToDwarfStringPoolEntryMap.h"
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/CodeGen/AccelTable.h"
@@ -25,13 +26,7 @@ class DWARFLinkerImpl : public DWARFLinker {
 public:
   DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
                   MessageHandlerTy WarningHandler,
-                  TranslatorFuncTy StringsTranslator)
-      : UniqueUnitID(0), DebugStrStrings(GlobalData),
-        DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
-    GlobalData.setTranslator(StringsTranslator);
-    GlobalData.setErrorHandler(ErrorHandler);
-    GlobalData.setWarningHandler(WarningHandler);
-  }
+                  TranslatorFuncTy StringsTranslator);
 
   /// Create debug info emitter.
   Error createEmitter(const Triple &TheTriple, OutputFileType FileType,
@@ -74,11 +69,7 @@ class DWARFLinkerImpl : public DWARFLinker {
   }
 
   /// Do not unique types according to ODR.
-  void setNoODR(bool) override {
-    // FIXME: set option when ODR mode will be supported.
-    // getOptions().NoODR = NoODR;
-    GlobalData.Options.NoODR = true;
-  }
+  void setNoODR(bool NoODR) override { GlobalData.Options.NoODR = NoODR; }
 
   /// Update index tables only(do not modify rest of DWARF).
   void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) override {
@@ -114,9 +105,7 @@ class DWARFLinkerImpl : public DWARFLinker {
   }
 
   /// Set estimated objects files amount, for preliminary data allocation.
-  void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override {
-    ObjectContexts.reserve(ObjFilesNum);
-  }
+  void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override;
 
   /// Set verification handler which would be used to report verification
   /// errors.
@@ -173,10 +162,8 @@ class DWARFLinkerImpl : public DWARFLinker {
     /// Keep information for referenced clang module: already loaded DWARF info
     /// of the clang module and a CompileUnit of the module.
     struct RefModuleUnit {
-      RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
-          : File(File), Unit(std::move(Unit)) {}
-      RefModuleUnit(RefModuleUnit &&Other)
-          : File(Other.File), Unit(std::move(Other.Unit)) {}
+      RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit);
+      RefModuleUnit(RefModuleUnit &&Other);
       RefModuleUnit(const RefModuleUnit &) = delete;
 
       DWARFFile &File;
@@ -209,28 +196,15 @@ class DWARFLinkerImpl : public DWARFLinker {
     /// if new inter-connected units were found.
     std::atomic<bool> HasNewInterconnectedCUs = {false};
 
+    std::atomic<bool> HasNewGlobalDependency = {false};
+
     /// Counter for compile units ID.
     std::atomic<size_t> &UniqueUnitID;
 
     LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,
                 StringMap<uint64_t> &ClangModules,
                 std::atomic<size_t> &UniqueUnitID,
-                std::optional<Triple> TargetTriple)
-        : OutputSections(GlobalData), InputDWARFFile(File),
-          ClangModules(ClangModules), TargetTriple(TargetTriple),
-          UniqueUnitID(UniqueUnitID) {
-
-      if (File.Dwarf) {
-        if (!File.Dwarf->compile_units().empty())
-          CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
-
-        // Set context format&endianness based on the input file.
-        Format.Version = File.Dwarf->getMaxVersion();
-        Format.AddrSize = File.Dwarf->getCUAddrSize();
-        Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
-                                                  : llvm::endianness::big;
-      }
-    }
+                std::optional<Triple> TargetTriple);
 
     /// Check whether specified \p CUDie is a Clang module reference.
     /// if \p Quiet is false then display error messages.
@@ -259,9 +233,7 @@ class DWARFLinkerImpl : public DWARFLinker {
                           unsigned Indent = 0);
 
     /// Add Compile Unit corresponding to the module.
-    void addModulesCompileUnit(RefModuleUnit &&Unit) {
-      ModulesCompileUnits.emplace_back(std::move(Unit));
-    }
+    void addModulesCompileUnit(RefModuleUnit &&Unit);
 
     /// Computes the total size of the debug info.
     uint64_t getInputDebugInfoSize() const {
@@ -277,11 +249,11 @@ class DWARFLinkerImpl : public DWARFLinker {
     }
 
     /// Link compile units for this context.
-    Error link();
+    Error link(TypeUnit *ArtificialTypeUnit);
 
     /// Link specified compile unit until specified stage.
     void linkSingleCompileUnit(
-        CompileUnit &CU,
+        CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
         enum CompileUnit::Stage DoUntilStage = CompileUnit::Stage::Cleaned);
 
     /// Emit invariant sections.
@@ -331,6 +303,9 @@ class DWARFLinkerImpl : public DWARFLinker {
   void forEachObjectSectionsSet(
       function_ref<void(OutputSections &SectionsSet)> SectionsSetHandler);
 
+  /// Enumerates all compile and type units.
+  void forEachCompileAndTypeUnit(function_ref<void(DwarfUnit *CU)> UnitHandler);
+
   /// Enumerates all comple units.
   void forEachCompileUnit(function_ref<void(CompileUnit *CU)> UnitHandler);
 
@@ -368,6 +343,9 @@ class DWARFLinkerImpl : public DWARFLinker {
   /// Mapping the PCM filename to the DwoId.
   StringMap<uint64_t> ClangModules;
   std::mutex ClangModulesMutex;
+
+  /// Type unit.
+  std::unique_ptr<TypeUnit> ArtificialTypeUnit;
   /// @}
 
   /// \defgroup Data members accessed sequentially.
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp
new file mode 100644
index 000000000000000..9d5c213085c2935
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp
@@ -0,0 +1,391 @@
+//===- DWARFLinkerTypeUnit.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLinkerTypeUnit.h"
+#include "DIEGenerator.h"
+#include "DWARFEmitterImpl.h"
+#include "llvm/Support/LEB128.h"
+
+using namespace llvm;
+using namespace llvm::dwarflinker_parallel;
+
+TypeUnit::TypeUnit(LinkingGlobalData &GlobalData, unsigned ID,
+                   std::optional<uint16_t> Language, dwarf::FormParams Format,
+                   endianness Endianess)
+    : DwarfUnit(GlobalData, ID, ""), Language(Language),
+      AcceleratorRecords(&GlobalData.getAllocator()) {
+
+  UnitName = "__artificial_type_unit";
+
+  setOutputFormat(Format, Endianess);
+
+  // Create line table prologue.
+  LineTable.Prologue.FormParams = getFormParams();
+  LineTable.Prologue.MinInstLength = 1;
+  LineTable.Prologue.MaxOpsPerInst = 1;
+  LineTable.Prologue.DefaultIsStmt = 1;
+  LineTable.Prologue.LineBase = -5;
+  LineTable.Prologue.LineRange = 14;
+  LineTable.Prologue.OpcodeBase = 13;
+  LineTable.Prologue.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0,
+                                              0, 0, 1, 0, 0, 1};
+
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+}
+
+void TypeUnit::createDIETree(BumpPtrAllocator &Allocator) {
+  prepareDataForTreeCreation();
+
+  // TaskGroup is created here as internal code has calls to
+  // PerThreadBumpPtrAllocator which should be called from the task group task.
+  parallel::TaskGroup TG;
+  TG.spawn([&]() {
+    SectionDescriptor &DebugInfoSection =
+        getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+    SectionDescriptor &DebugLineSection =
+        getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);
+
+    DIEGenerator DIETreeGenerator(Allocator, *this);
+    OffsetsPtrVector PatchesOffsets;
+
+    // Create a Die for artificial compilation unit for types.
+    DIE *UnitDIE = DIETreeGenerator.createDIE(dwarf::DW_TAG_compile_unit, 0);
+    uint64_t OutOffset = getDebugInfoHeaderSize();
+    UnitDIE->setOffset(OutOffset);
+
+    SmallString<200> ProducerString;
+    ProducerString += "llvm DWARFLinkerParallel library version ";
+    DebugInfoSection.notePatchWithOffsetUpdate(
+        DebugStrPatch{
+            {OutOffset},
+            GlobalData.getStringPool().insert(ProducerString.str()).first},
+        PatchesOffsets);
+    OutOffset += DIETreeGenerator
+                     .addStringPlaceholderAttribute(dwarf::DW_AT_producer,
+                                                    dwarf::DW_FORM_strp)
+                     .second;
+
+    if (Language) {
+      OutOffset += DIETreeGenerator
+                       .addScalarAttribute(dwarf::DW_AT_language,
+                                           dwarf::DW_FORM_data2, *Language)
+                       .second;
+    }
+
+    DebugInfoSection.notePatchWithOffsetUpdate(
+        DebugStrPatch{{OutOffset},
+                      GlobalData.getStringPool().insert(getUnitName()).first},
+        PatchesOffsets);
+    OutOffset += DIETreeGenerator
+                     .addStringPlaceholderAttribute(dwarf::DW_AT_name,
+                                                    dwarf::DW_FORM_strp)
+                     .second;
+
+    if (!LineTable.Prologue.FileNames.empty()) {
+      DebugInfoSection.notePatchWithOffsetUpdate(
+          DebugOffsetPatch{OutOffset, &DebugLineSection}, PatchesOffsets);
+
+      OutOffset += DIETreeGenerator
+                       .addScalarAttribute(dwarf::DW_AT_stmt_list,
+                                           dwarf::DW_FORM_sec_offset, 0xbaddef)
+                       .second;
+    }
+
+    DebugInfoSection.notePatchWithOffsetUpdate(
+        DebugStrPatch{{OutOffset}, GlobalData.getStringPool().insert("").first},
+        PatchesOffsets);
+    OutOffset += DIETreeGenerator
+                     .addStringPlaceholderAttribute(dwarf::DW_AT_comp_dir,
+                                                    dwarf::DW_FORM_strp)
+                     .second;
+
+    if (!DebugStringIndexMap.empty()) {
+      // Type unit is assumed to be emitted first. Thus we can use direct value
+      // for DW_AT_str_offsets_base attribute(No need to fix it up with unit
+      // offset value).
+      OutOffset += DIETreeGenerator
+                       .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
+                                           dwarf::DW_FORM_sec_offset,
+                                           getDebugStrOffsetsHeaderSize())
+                       .second;
+    }
+
+    UnitDIE->setSize(OutOffset - UnitDIE->getOffset() + 1);
+    OutOffset =
+        finalizeTypeEntryRec(UnitDIE->getOffset(), UnitDIE, Types.getRoot());
+
+    // Update patch offsets.
+    for (uint64_t *OffsetPtr : PatchesOffsets)
+      *OffsetPtr += getULEB128Size(UnitDIE->getAbbrevNumber());
+
+    setOutUnitDIE(UnitDIE);
+  });
+}
+
+void TypeUnit::prepareDataForTreeCreation() {
+  SectionDescriptor &DebugInfoSection =
+      getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+
+  // Type unit data created parallelly. So the order of data is not
+  // deterministic. Order data here if we need deterministic output.
+
+  parallel::TaskGroup TG;
+
+  if (!GlobalData.getOptions().AllowNonDeterministicOutput) {
+    TG.spawn([&]() {
+      // Sort types to have a deterministic output.
+      Types.sortTypes();
+    });
+  }
+
+  TG.spawn([&]() {
+    if (!GlobalData.getOptions().AllowNonDeterministicOutput) {
+      // Sort decl type patches to have a deterministic output.
+      std::function<bool(const DebugTypeDeclFilePatch &LHS,
+                         const DebugTypeDeclFilePatch &RHS)>
+          PatchesComparator = [&](const DebugTypeDeclFilePatch &LHS,
+                                  const DebugTypeDeclFilePatch &RHS) {
+            return LHS.Directory->first() < RHS.Directory->first() ||
+                   (!(RHS.Directory->first() < LHS.Directory->first()) &&
+                    LHS.FilePath->first() < RHS.FilePath->first());
+          };
+      // Sort patches to have a deterministic output.
+      DebugInfoSection.ListDebugTypeDeclFilePatch.sort(PatchesComparator);
+    }
+
+    // Update DW_AT_decl_file attribute
+    dwarf::Form DeclFileForm =
+        getScalarFormForValue(
+            DebugInfoSection.ListDebugTypeDeclFilePatch.size())
+            .first;
+
+    DebugInfoSection.ListDebugTypeDeclFilePatch.forEach(
+        [&](DebugTypeDeclFilePatch &Patch) {
+          TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
+          assert(TypeEntry &&
+                 formatv("No data for type {0}", Patch.TypeName->getKey())
+                     .str()
+                     .c_str());
+          if (&TypeEntry->getFinalDie() != Patch.Die)
+            return;
+
+          uint32_t FileIdx =
+              addFileNameIntoLinetable(Patch.Directory, Patch.FilePath);
+
+          unsigned DIESize = Patch.Die->getSize();
+          DIEGenerator DIEGen(Patch.Die, Types.getThreadLocalAllocator(),
+                              *this);
+
+          DIESize += DIEGen
+                         .addScalarAttribute(dwarf::DW_AT_decl_file,
+                                             DeclFileForm, FileIdx)
+                         .second;
+          Patch.Die->setSize(DIESize);
+        });
+  });
+
+  if (!GlobalData.getOptions().AllowNonDeterministicOutput) {
+    // Sort patches to have a deterministic output.
+    TG.spawn([&]() {
+      forEach([&](SectionDescriptor &OutSection) {
+        std::function<bool(const DebugStrPatch &LHS, const DebugStrPatch &RHS)>
+            StrPatchesComparator =
+                [&](const DebugStrPatch &LHS, const DebugStrPatch &RHS) {
+                  return LHS.String->getKey() < RHS.String->getKey();
+                };
+        OutSection.ListDebugStrPatch.sort(StrPatchesComparator);
+
+        std::function<bool(const DebugTypeStrPatch &LHS,
+                           const DebugTypeStrPatch &RHS)>
+            TypeStrPatchesComparator = [&](const DebugTypeStrPatch &LHS,
+                                           const DebugTypeStrPatch &RHS) {
+              return LHS.String->getKey() < RHS.String->getKey();
+            };
+        OutSection.ListDebugTypeStrPatch.sort(TypeStrPatchesComparator);
+      });
+    });
+  }
+
+  if (!GlobalData.getOptions().AllowNonDeterministicOutput) {
+    // Sort patches to have a deterministic output.
+    TG.spawn([&]() {
+      forEach([&](SectionDescriptor &OutSection) {
+        std::function<bool(const DebugLineStrPatch &LHS,
+                           const DebugLineStrPatch &RHS)>
+            LineStrPatchesComparator = [&](const DebugLineStrPatch &LHS,
+                                           const DebugLineStrPatch &RHS) {
+              return LHS.String->getKey() < RHS.String->getKey();
+            };
+        OutSection.ListDebugLineStrPatch.sort(LineStrPatchesComparator);
+
+        std::function<bool(const DebugTypeLineStrPatch &LHS,
+                           const DebugTypeLineStrPatch &RHS)>
+            TypeLineStrPatchesComparator =
+                [&](const DebugTypeLineStrPatch &LHS,
+                    const DebugTypeLineStrPatch &RHS) {
+                  return LHS.String->getKey() < RHS.String->getKey();
+                };
+        OutSection.ListDebugTypeLineStrPatch.sort(TypeLineStrPatchesComparator);
+      });
+    });
+  }
+}
+
+uint64_t TypeUnit::finalizeTypeEntryRec(uint64_t OutOffset, DIE *OutDIE,
+                                        TypeEntry *Entry) {
+  bool HasChildren = !Entry->getValue().load()->Children.empty();
+  DIEGenerator DIEGen(OutDIE, Types.getThreadLocalAllocator(), *this);
+  OutOffset += DIEGen.finalizeAbbreviations(HasChildren, nullptr);
+  OutOffset += OutDIE->getSize() - 1;
+
+  if (HasChildren) {
+    Entry->getValue().load()->Children.forEach([&](TypeEntry *ChildEntry) {
+      DIE *ChildDIE = &ChildEntry->getValue().load()->getFinalDie();
+      DIEGen.addChild(ChildDIE);
+
+      ChildDIE->setOffset(OutOffset);
+
+      OutOffset = finalizeTypeEntryRec(OutOffset, ChildDIE, ChildEntry);
+    });
+
+    // End of children marker.
+    OutOffset += sizeof(int8_t);
+  }
+
+  OutDIE->setSize(OutOffset - OutDIE->getOffset());
+  return OutOffset;
+}
+
+uint32_t TypeUnit::addFileNameIntoLinetable(StringEntry *Dir,
+                                            StringEntry *FileName) {
+  uint32_t DirIdx = 0;
+
+  if (Dir->first() == "") {
+    DirIdx = 0;
+  } else {
+    DirectoriesMapTy::iterator DirEntry = DirectoriesMap.find(Dir);
+    if (DirEntry == DirectoriesMap.end()) {
+      // We currently do not support more than UINT32_MAX directories.
+      assert(LineTable.Prologue.IncludeDirectories.size() < UINT32_MAX);
+      DirIdx = LineTable.Prologue.IncludeDirectories.size();
+      DirectoriesMap.insert({Dir, DirIdx});
+      LineTable.Prologue.IncludeDirectories.push_back(
+          DWARFFormValue::createFromPValue(dwarf::DW_FORM_string,
+                                           Dir->getKeyData()));
+    } else {
+      DirIdx = DirEntry->second;
+    }
+
+    if (getVersion() < 5)
+      DirIdx++;
+  }
+
+  uint32_t FileIdx = 0;
+  FilenamesMapTy::iterator FileEntry = FileNamesMap.find({FileName, DirIdx});
+  if (FileEntry == FileNamesMap.end()) {
+    // We currently do not support more than UINT32_MAX files.
+    assert(LineTable.Prologue.FileNames.size() < UINT32_MAX);
+    FileIdx = LineTable.Prologue.FileNames.size();
+    FileNamesMap.insert({{FileName, DirIdx}, FileIdx});
+    LineTable.Prologue.FileNames.push_back(DWARFDebugLine::FileNameEntry());
+    LineTable.Prologue.FileNames.back().Name = DWARFFormValue::createFromPValue(
+        dwarf::DW_FORM_string, FileName->getKeyData());
+    LineTable.Prologue.FileNames.back().DirIdx = DirIdx;
+  } else {
+    FileIdx = FileEntry->second;
+  }
+
+  return getVersion() < 5 ? FileIdx + 1 : FileIdx;
+}
+
+std::pair<dwarf::Form, uint8_t>
+TypeUnit::getScalarFormForValue(uint64_t Value) const {
+  if (Value > 0xFFFFFFFF)
+    return std::make_pair(dwarf::DW_FORM_data8, 8);
+
+  if (Value > 0xFFFF)
+    return std::make_pair(dwarf::DW_FORM_data4, 4);
+
+  if (Value > 0xFF)
+    return std::make_pair(dwarf::DW_FORM_data2, 2);
+
+  return std::make_pair(dwarf::DW_FORM_data1, 1);
+}
+
+uint8_t TypeUnit::getSizeByAttrForm(dwarf::Form Form) const {
+  if (Form == dwarf::DW_FORM_data1)
+    return 1;
+
+  if (Form == dwarf::DW_FORM_data2)
+    return 2;
+
+  if (Form == dwarf::DW_FORM_data4)
+    return 4;
+
+  if (Form == dwarf::DW_FORM_data8)
+    return 8;
+
+  if (Form == dwarf::DW_FORM_data16)
+    return 16;
+
+  llvm_unreachable("Unsupported Attr Form");
+}
+
+Error TypeUnit::finishCloningAndEmit(std::optional<Triple> TargetTriple) {
+  BumpPtrAllocator Allocator;
+  createDIETree(Allocator);
+
+  if (getGlobalData().getOptions().NoOutput || (getOutUnitDIE() == nullptr))
+    return Error::success();
+
+  // Create sections ahead so that they should not be created asynchronously
+  // later.
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
+  getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);
+  if (llvm::is_contained(GlobalData.getOptions().AccelTables,
+                         DWARFLinker::AccelTableKind::Pub)) {
+    getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);
+    getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);
+  }
+
+  SmallVector<std::function<Error(void)>> Tasks;
+
+  // Add task for emitting .debug_line section.
+  if (!LineTable.Prologue.FileNames.empty()) {
+    Tasks.push_back([&]() -> Error {
+      assert(TargetTriple.has_value());
+      return emitDebugLine(*TargetTriple, LineTable);
+    });
+  }
+
+  // Add task for emitting .debug_info section.
+  Tasks.push_back([&]() -> Error { return emitDebugInfo(*TargetTriple); });
+
+  // Add task for emitting Pub accelerator sections.
+  if (llvm::is_contained(GlobalData.getOptions().AccelTables,
+                         DWARFLinker::AccelTableKind::Pub)) {
+    Tasks.push_back([&]() -> Error {
+      emitPubAccelerators();
+      return Error::success();
+    });
+  }
+
+  // Add task for emitting .debug_str_offsets section.
+  Tasks.push_back([&]() -> Error { return emitDebugStringOffsetSection(); });
+
+  // Add task for emitting .debug_abbr section.
+  Tasks.push_back([&]() -> Error { return emitAbbreviations(); });
+
+  if (auto Err = parallelForEachError(
+          Tasks, [&](std::function<Error(void)> F) { return F(); }))
+    return Err;
+
+  return Error::success();
+}
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h
new file mode 100644
index 000000000000000..97e620eee0c4245
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h
@@ -0,0 +1,138 @@
+//===- DWARFLinkerTypeUnit.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
+#define LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
+
+#include "DWARFLinkerUnit.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+/// Type Unit is used to represent an artificial compilation unit
+/// which keeps all type information. This type information is referenced
+/// from other compilation units.
+class TypeUnit : public DwarfUnit {
+public:
+  TypeUnit(LinkingGlobalData &GlobalData, unsigned ID,
+           std::optional<uint16_t> Language, dwarf::FormParams Format,
+           llvm::endianness Endianess);
+
+  /// Generates DIE tree based on information from TypesMap.
+  void createDIETree(BumpPtrAllocator &Allocator);
+
+  /// Emits resulting dwarf based on information from DIE tree.
+  Error finishCloningAndEmit(std::optional<Triple> TargetTriple);
+
+  /// Returns global type pool.
+  TypePool &getTypePool() { return Types; }
+
+  /// TypeUnitAccelInfo extends AccelInfo structure with type specific fileds.
+  /// We need these additional fields to decide whether OutDIE should have an
+  /// accelerator record or not. The TypeEntryBodyPtr can refer to the
+  /// declaration DIE and definition DIE corresponding to the type entry.
+  /// Only one of them would be used in final output. So if TypeUnitAccelInfo
+  /// refers OutDIE which does not match with TypeEntryBodyPtr->getFinalDie()
+  /// then such record should be skipped.
+  struct TypeUnitAccelInfo : public AccelInfo {
+    /// Pointer to the output DIE which owns this accelerator record.
+    DIE *OutDIE = nullptr;
+
+    /// Pointer to the type entry body.
+    TypeEntryBody *TypeEntryBodyPtr = nullptr;
+  };
+
+  /// Enumerates all accelerator records and call \p Handler for each.
+  void
+  forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) override {
+    AcceleratorRecords.forEach([&](TypeUnitAccelInfo &Info) {
+      // Check whether current record is for the final DIE.
+      assert(Info.TypeEntryBodyPtr != nullptr);
+
+      if (&Info.TypeEntryBodyPtr->getFinalDie() != Info.OutDIE)
+        return;
+
+      Info.OutOffset = Info.OutDIE->getOffset();
+      Handler(Info);
+    });
+  }
+
+  /// Returns index for the specified \p String inside .debug_str_offsets.
+  uint64_t getDebugStrIndex(const StringEntry *String) override {
+    std::unique_lock<std::mutex> LockGuard(DebugStringIndexMapMutex);
+    return DebugStringIndexMap.getValueIndex(String);
+  }
+
+  /// Adds \p Info to the unit's accelerator records.
+  void saveAcceleratorInfo(const TypeUnitAccelInfo &Info) {
+    AcceleratorRecords.add(Info);
+  }
+
+private:
+  /// Type DIEs are partially created at clonning stage. They are organised
+  /// as a tree using type entries. This function links DIEs(corresponding
+  /// to the type entries) into the tree structure.
+  uint64_t finalizeTypeEntryRec(uint64_t OutOffset, DIE *OutDIE,
+                                TypeEntry *Entry);
+
+  /// Prepares DIEs to be linked into the tree.
+  void prepareDataForTreeCreation();
+
+  /// Add specified \p Dir and \p Filename into the line table
+  /// of this type unit.
+  uint32_t addFileNameIntoLinetable(StringEntry *Dir, StringEntry *FileName);
+
+  std::pair<dwarf::Form, uint8_t> getScalarFormForValue(uint64_t Value) const;
+
+  uint8_t getSizeByAttrForm(dwarf::Form Form) const;
+
+  struct CmpStringEntryRef {
+    bool operator()(const StringEntry *LHS, const StringEntry *RHS) const {
+      return LHS->first() < RHS->first();
+    }
+  };
+  struct CmpDirIDStringEntryRef {
+    bool operator()(const std::pair<StringEntry *, uint64_t> &LHS,
+                    const std::pair<StringEntry *, uint64_t> &RHS) const {
+      return LHS.second < RHS.second ||
+             (!(RHS.second < LHS.second) &&
+              LHS.first->first() < RHS.first->first());
+    }
+  };
+
+  /// The DW_AT_language of this unit.
+  std::optional<uint16_t> Language;
+
+  /// This unit line table.
+  DWARFDebugLine::LineTable LineTable;
+
+  /// Data members keeping file names for line table.
+  using DirectoriesMapTy = std::map<StringEntry *, size_t, CmpStringEntryRef>;
+  using FilenamesMapTy = std::map<std::pair<StringEntry *, uint64_t>, size_t,
+                                  CmpDirIDStringEntryRef>;
+
+  DirectoriesMapTy DirectoriesMap;
+  FilenamesMapTy FileNamesMap;
+
+  /// Type DIEs tree.
+  TypePool Types;
+
+  /// List of accelerator entries for this unit.
+  ArrayList<TypeUnitAccelInfo> AcceleratorRecords;
+
+  /// Guard for DebugStringIndexMap.
+  std::mutex DebugStringIndexMapMutex;
+};
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
index 1503015f015575b..b1da1900d65ef70 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
@@ -88,7 +88,7 @@ void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
   encodeULEB128(0, AbbrevSection.OS);
 }
 
-Error DwarfUnit::emitDebugInfo(Triple &TargetTriple) {
+Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
   DIE *OutUnitDIE = getOutUnitDIE();
   if (OutUnitDIE == nullptr)
     return Error::success();
@@ -119,18 +119,60 @@ Error DwarfUnit::emitDebugInfo(Triple &TargetTriple) {
   return Error::success();
 }
 
-Error DwarfUnit::emitDebugLine(Triple &TargetTriple,
+Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,
                                const DWARFDebugLine::LineTable &OutLineTable) {
   DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
 
   return DebugLineEmitter.emit(OutLineTable);
 }
 
+Error DwarfUnit::emitDebugStringOffsetSection() {
+  if (getVersion() < 5)
+    return Error::success();
+
+  if (DebugStringIndexMap.empty())
+    return Error::success();
+
+  SectionDescriptor &OutDebugStrOffsetsSection =
+      getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets);
+
+  // Emit section header.
+
+  //   Emit length.
+  OutDebugStrOffsetsSection.emitUnitLength(0xBADDEF);
+  uint64_t OffsetAfterSectionLength = OutDebugStrOffsetsSection.OS.tell();
+
+  //   Emit version.
+  OutDebugStrOffsetsSection.emitIntVal(5, 2);
+
+  //   Emit padding.
+  OutDebugStrOffsetsSection.emitIntVal(0, 2);
+
+  //   Emit index to offset map.
+  for (const StringEntry *String : DebugStringIndexMap.getValues()) {
+    // Note patch for string offset value.
+    OutDebugStrOffsetsSection.notePatch(
+        DebugStrPatch{{OutDebugStrOffsetsSection.OS.tell()}, String});
+
+    // Emit placeholder for offset value.
+    OutDebugStrOffsetsSection.emitOffset(0xBADDEF);
+  }
+
+  // Patch section length.
+  OutDebugStrOffsetsSection.apply(
+      OffsetAfterSectionLength -
+          OutDebugStrOffsetsSection.getFormParams().getDwarfOffsetByteSize(),
+      dwarf::DW_FORM_sec_offset,
+      OutDebugStrOffsetsSection.OS.tell() - OffsetAfterSectionLength);
+
+  return Error::success();
+}
+
 /// Emit the pubnames or pubtypes section contribution for \p
 /// Unit into \p Sec. The data is provided in \p Info.
 std::optional<uint64_t>
 DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
-                                   DwarfUnit::AccelInfo &Info,
+                                   const DwarfUnit::AccelInfo &Info,
                                    std::optional<uint64_t> LengthOffset) {
   if (!LengthOffset) {
     // Emit the header.
@@ -160,7 +202,7 @@ void DwarfUnit::emitPubAccelerators() {
   std::optional<uint64_t> NamesLengthOffset;
   std::optional<uint64_t> TypesLengthOffset;
 
-  AcceleratorRecords.forEach([&](DwarfUnit::AccelInfo &Info) {
+  forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
     if (Info.AvoidForPubSections)
       return;
 
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
index 0835fad1e667a38..9640a8ee711eb0e 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
@@ -10,6 +10,7 @@
 #define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERUNIT_H
 
 #include "DWARFLinkerGlobalData.h"
+#include "IndexedValuesMap.h"
 #include "OutputSections.h"
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DWARFLinkerParallel/DWARFLinker.h"
@@ -30,16 +31,11 @@ class DwarfUnit : public OutputSections {
   DwarfUnit(LinkingGlobalData &GlobalData, unsigned ID,
             StringRef ClangModuleName)
       : OutputSections(GlobalData), ID(ID), ClangModuleName(ClangModuleName),
-        OutUnitDIE(nullptr) {
-    AcceleratorRecords.setAllocator(&GlobalData.getAllocator());
-  }
+        OutUnitDIE(nullptr) {}
 
   /// Unique id of the unit.
   unsigned getUniqueID() const { return ID; }
 
-  /// Return language of this unit.
-  uint16_t getLanguage() const { return Language; }
-
   /// Returns size of this(newly generated) compile unit.
   uint64_t getUnitSize() const { return UnitSize; }
 
@@ -91,11 +87,14 @@ class DwarfUnit : public OutputSections {
   Error emitAbbreviations();
 
   /// Emit .debug_info section for unit DIEs.
-  Error emitDebugInfo(Triple &TargetTriple);
+  Error emitDebugInfo(const Triple &TargetTriple);
 
   /// Emit .debug_line section.
-  Error emitDebugLine(Triple &TargetTriple,
+  Error emitDebugLine(const Triple &TargetTriple,
                       const DWARFDebugLine::LineTable &OutLineTable);
+
+  /// Emit the .debug_str_offsets section for current unit.
+  Error emitDebugStringOffsetSection();
   /// @}
 
   /// \defgroup Methods used for reporting warnings and errors:
@@ -124,7 +123,7 @@ class DwarfUnit : public OutputSections {
     StringEntry *String = nullptr;
 
     /// Output offset of the DIE this entry describes.
-    uint64_t OutOffset = 0;
+    uint64_t OutOffset;
 
     /// Hash of the fully qualified name.
     uint32_t QualifiedNameHash = 0;
@@ -135,71 +134,27 @@ class DwarfUnit : public OutputSections {
     /// Type of this accelerator record.
     AccelType Type = AccelType::None;
 
-    /// Avoid using this entry for pub sections.
+    /// Avoid emitting this entry for pub sections.
     bool AvoidForPubSections : 1;
 
     /// Is this an ObjC class implementation?
     bool ObjcClassImplementation : 1;
   };
 
-  void rememberNameForAccelerators(StringEntry *Name, uint64_t OutOffset,
-                                   dwarf::Tag Tag, bool AvoidForPubSections) {
-    AccelInfo Info;
-
-    Info.Type = AccelType::Name;
-    Info.String = Name;
-    Info.OutOffset = OutOffset;
-    Info.Tag = Tag;
-    Info.AvoidForPubSections = AvoidForPubSections;
-
-    AcceleratorRecords.add(Info);
-  }
-  void rememberNamespaceForAccelerators(StringEntry *Name, uint64_t OutOffset,
-                                        dwarf::Tag Tag) {
-    AccelInfo Info;
-
-    Info.Type = AccelType::Namespace;
-    Info.String = Name;
-    Info.OutOffset = OutOffset;
-    Info.Tag = Tag;
-
-    AcceleratorRecords.add(Info);
-  }
-  void rememberObjCNameForAccelerators(StringEntry *Name, uint64_t OutOffset,
-                                       dwarf::Tag Tag) {
-    AccelInfo Info;
-
-    Info.Type = AccelType::ObjC;
-    Info.String = Name;
-    Info.OutOffset = OutOffset;
-    Info.Tag = Tag;
-    Info.AvoidForPubSections = true;
-
-    AcceleratorRecords.add(Info);
-  }
-  void rememberTypeForAccelerators(StringEntry *Name, uint64_t OutOffset,
-                                   dwarf::Tag Tag, uint32_t QualifiedNameHash,
-                                   bool ObjcClassImplementation) {
-    AccelInfo Info;
-
-    Info.Type = AccelType::Type;
-    Info.String = Name;
-    Info.OutOffset = OutOffset;
-    Info.Tag = Tag;
-    Info.QualifiedNameHash = QualifiedNameHash;
-    Info.ObjcClassImplementation = ObjcClassImplementation;
-
-    AcceleratorRecords.add(Info);
-  }
-
   /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
   void emitPubAccelerators();
 
-  /// Accelerator tables data.
-  ArrayList<AccelInfo> AcceleratorRecords;
+  /// Enumerates accelerator data.
+  virtual void
+  forEachAcceleratorRecord(function_ref<void(AccelInfo &)> Handler) = 0;
 
   /// @}
 
+  /// Returns index(inside .debug_str_offsets) of specified string.
+  virtual uint64_t getDebugStrIndex(const StringEntry *String) {
+    return DebugStringIndexMap.getValueIndex(String);
+  }
+
 protected:
   /// Emit single abbreviation entry.
   void emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
@@ -207,16 +162,12 @@ class DwarfUnit : public OutputSections {
 
   /// Emit single pubnames/pubtypes accelerator entry.
   std::optional<uint64_t>
-  emitPubAcceleratorEntry(SectionDescriptor &OutSection,
-                          DwarfUnit::AccelInfo &Info,
+  emitPubAcceleratorEntry(SectionDescriptor &OutSection, const AccelInfo &Info,
                           std::optional<uint64_t> LengthOffset);
 
   /// Unique ID for the unit.
   unsigned ID = 0;
 
-  /// The DW_AT_language of this unit.
-  uint16_t Language = 0;
-
   /// The name of this unit.
   std::string UnitName;
 
@@ -239,8 +190,31 @@ class DwarfUnit : public OutputSections {
 
   /// Output unit DIE.
   DIE *OutUnitDIE = nullptr;
+
+  /// Cache for file names for this unit.
+  using FileNamesCache =
+      DenseMap<uint64_t, std::pair<std::string, std::string>>;
+  FileNamesCache FileNames;
+
+  /// Maps a string into the index inside .debug_str_offsets section.
+  IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
 };
 
+inline bool isODRLanguage(uint16_t Language) {
+  switch (Language) {
+  case dwarf::DW_LANG_C_plus_plus:
+  case dwarf::DW_LANG_C_plus_plus_03:
+  case dwarf::DW_LANG_C_plus_plus_11:
+  case dwarf::DW_LANG_C_plus_plus_14:
+  case dwarf::DW_LANG_ObjC_plus_plus:
+    return true;
+  default:
+    return false;
+  };
+
+  return false;
+}
+
 } // end of namespace dwarflinker_parallel
 } // end namespace llvm
 
diff --git a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h b/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h
index 4aef0d0d67303da..fc7f8cbc4a8e7bd 100644
--- a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h
+++ b/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h
@@ -149,6 +149,7 @@ class DebugLineSectionEmitter {
       // A null-terminated string containing the full or relative path name of a
       // source file.
       Section.emitString(File.Name.getForm(), *FileNameStr);
+
       // An unsigned LEB128 number representing the directory index of a
       // directory in the include_directories section.
       encodeULEB128(File.DirIdx, Section.OS);
diff --git a/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp b/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp
index 3a69c3821e8b52b..8767cc0fc6e77c4 100644
--- a/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp
@@ -12,18 +12,20 @@
 namespace llvm {
 namespace dwarflinker_parallel {
 
-#ifndef NDEBUG
 /// A broken link in the keep chain. By recording both the parent and the child
 /// we can show only broken links for DIEs with multiple children.
 struct BrokenLink {
-  BrokenLink(DWARFDie Parent, DWARFDie Child) : Parent(Parent), Child(Child) {}
+  BrokenLink(DWARFDie Parent, DWARFDie Child, const char *Message)
+      : Parent(Parent), Child(Child), Message(Message) {}
   DWARFDie Parent;
   DWARFDie Child;
+  std::string Message;
 };
 
 /// Verify the keep chain by looking for DIEs that are kept but who's parent
 /// isn't.
-void DependencyTracker::verifyKeepChain(CompileUnit &CU) {
+void DependencyTracker::verifyKeepChain() {
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   SmallVector<DWARFDie> Worklist;
   Worklist.push_back(CU.getOrigUnit().getUnitDIE());
 
@@ -37,176 +39,585 @@ void DependencyTracker::verifyKeepChain(CompileUnit &CU) {
     if (!Current.isValid())
       continue;
 
-    const bool CurrentDieIsKept = CU.getDIEInfo(Current).getKeep() ||
-                                  CU.getDIEInfo(Current).getKeepChildren();
+    CompileUnit::DIEInfo &CurrentInfo =
+        CU.getDIEInfo(Current.getDebugInfoEntry());
+    const bool ParentPlainDieIsKept = CurrentInfo.needToKeepInPlainDwarf();
+    const bool ParentTypeDieIsKept = CurrentInfo.needToPlaceInTypeTable();
 
     for (DWARFDie Child : reverse(Current.children())) {
       Worklist.push_back(Child);
 
-      const bool ChildDieIsKept = CU.getDIEInfo(Child).getKeep() ||
-                                  CU.getDIEInfo(Child).getKeepChildren();
-      if (!CurrentDieIsKept && ChildDieIsKept)
-        BrokenLinks.emplace_back(Current, Child);
+      CompileUnit::DIEInfo &ChildInfo =
+          CU.getDIEInfo(Child.getDebugInfoEntry());
+      const bool ChildPlainDieIsKept = ChildInfo.needToKeepInPlainDwarf();
+      const bool ChildTypeDieIsKept = ChildInfo.needToPlaceInTypeTable();
+
+      if (!ParentPlainDieIsKept && ChildPlainDieIsKept)
+        BrokenLinks.emplace_back(Current, Child,
+                                 "Found invalid link in keep chain");
+
+      if (Child.getTag() == dwarf::DW_TAG_subprogram) {
+        if (!ChildInfo.getKeep() && isLiveSubprogramEntry(UnitEntryPairTy(
+                                        &CU, Child.getDebugInfoEntry()))) {
+          BrokenLinks.emplace_back(Current, Child,
+                                   "Live subprogram is not marked as kept");
+        }
+      }
+
+      if (!ChildInfo.getODRAvailable()) {
+        assert(!ChildTypeDieIsKept);
+        continue;
+      }
+
+      if (!ParentTypeDieIsKept && ChildTypeDieIsKept)
+        BrokenLinks.emplace_back(Current, Child,
+                                 "Found invalid link in keep chain");
+
+      if (CurrentInfo.getIsInAnonNamespaceScope() &&
+          ChildInfo.needToPlaceInTypeTable()) {
+        BrokenLinks.emplace_back(Current, Child,
+                                 "Found invalid placement marking for member "
+                                 "of anonymous namespace");
+      }
     }
   }
 
   if (!BrokenLinks.empty()) {
     for (BrokenLink Link : BrokenLinks) {
-      WithColor::error() << formatv(
-          "Found invalid link in keep chain between {0:x} and {1:x}\n",
-          Link.Parent.getOffset(), Link.Child.getOffset());
+      errs() << "\n=================================\n";
+      WithColor::error() << formatv("{0} between {1:x} and {2:x}", Link.Message,
+                                    Link.Parent.getOffset(),
+                                    Link.Child.getOffset());
 
-      errs() << "Parent:";
+      errs() << "\nParent:";
       Link.Parent.dump(errs(), 0, {});
+      errs() << "\n";
       CU.getDIEInfo(Link.Parent).dump();
 
-      errs() << "Child:";
+      errs() << "\nChild:";
       Link.Child.dump(errs(), 2, {});
+      errs() << "\n";
       CU.getDIEInfo(Link.Child).dump();
     }
     report_fatal_error("invalid keep chain");
   }
-}
 #endif
+}
 
-bool DependencyTracker::resolveDependenciesAndMarkLiveness(CompileUnit &CU) {
-  // We do not track liveness inside Clang modules. We also do not track
-  // liveness if UpdateIndexTablesOnly is requested.
-  TrackLiveness = !(CU.isClangModule() ||
-                    CU.getGlobalData().getOptions().UpdateIndexTablesOnly);
+bool DependencyTracker::resolveDependenciesAndMarkLiveness(
+    bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
   RootEntriesWorkList.clear();
 
   // Search for live root DIEs.
-  collectRootsToKeep(CU, CU.getDebugInfoEntry(0));
+  CompileUnit::DIEInfo &CUInfo = CU.getDIEInfo(CU.getDebugInfoEntry(0));
+  CUInfo.setPlacement(CompileUnit::PlainDwarf);
+  collectRootsToKeep(UnitEntryPairTy{&CU, CU.getDebugInfoEntry(0)},
+                     std::nullopt, false);
 
   // Mark live DIEs as kept.
-  return markLiveRootsAsKept();
+  return markCollectedLiveRootsAsKept(InterCUProcessingStarted,
+                                      HasNewInterconnectedCUs);
 }
 
-void DependencyTracker::collectRootsToKeep(CompileUnit &CU,
-                                           const DWARFDebugInfoEntry *Entry) {
-  if (!TrackLiveness) {
-    addItemToWorklist(CU, Entry);
+void DependencyTracker::addActionToRootEntriesWorkList(
+    LiveRootWorklistActionTy Action, const UnitEntryPairTy &Entry,
+    std::optional<UnitEntryPairTy> ReferencedBy) {
+  if (ReferencedBy) {
+    RootEntriesWorkList.emplace_back(Action, Entry, *ReferencedBy);
     return;
   }
 
-  switch (Entry->getTag()) {
-  case dwarf::DW_TAG_subprogram:
-  case dwarf::DW_TAG_label:
-    if (isLiveSubprogramEntry(CU, Entry)) {
-      addItemToWorklist(CU, Entry);
+  RootEntriesWorkList.emplace_back(Action, Entry);
+}
+
+void DependencyTracker::collectRootsToKeep(
+    const UnitEntryPairTy &Entry, std::optional<UnitEntryPairTy> ReferencedBy,
+    bool IsLiveParent) {
+  for (const DWARFDebugInfoEntry *CurChild =
+           Entry.CU->getFirstChildEntry(Entry.DieEntry);
+       CurChild && CurChild->getAbbreviationDeclarationPtr();
+       CurChild = Entry.CU->getSiblingEntry(CurChild)) {
+    UnitEntryPairTy ChildEntry(Entry.CU, CurChild);
+    CompileUnit::DIEInfo &ChildInfo = Entry.CU->getDIEInfo(CurChild);
+
+    bool IsLiveChild = false;
+
+    switch (CurChild->getTag()) {
+    case dwarf::DW_TAG_label: {
+      IsLiveChild = isLiveSubprogramEntry(ChildEntry);
+
+      // Keep label referencing live address.
+      // Keep label which is child of live parent entry.
+      if (IsLiveChild || (IsLiveParent && ChildInfo.getHasAnAddress())) {
+        addActionToRootEntriesWorkList(
+            LiveRootWorklistActionTy::MarkLiveEntryRec, ChildEntry,
+            ReferencedBy);
+      }
+    } break;
+    case dwarf::DW_TAG_subprogram: {
+      IsLiveChild = isLiveSubprogramEntry(ChildEntry);
+
+      // Keep subprogram referencing live address.
+      if (IsLiveChild) {
+        // If subprogram is in module scope and this module allows ODR
+        // deduplication set "TypeTable" placement, otherwise set "" placement
+        LiveRootWorklistActionTy Action =
+            (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
+                ? LiveRootWorklistActionTy::MarkTypeEntryRec
+                : LiveRootWorklistActionTy::MarkLiveEntryRec;
+
+        addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
+      }
+    } break;
+    case dwarf::DW_TAG_constant:
+    case dwarf::DW_TAG_variable: {
+      IsLiveChild = isLiveVariableEntry(ChildEntry, IsLiveParent);
+
+      // Keep variable referencing live address.
+      if (IsLiveChild) {
+        // If variable is in module scope and this module allows ODR
+        // deduplication set "TypeTable" placement, otherwise set "" placement
+
+        LiveRootWorklistActionTy Action =
+            (ChildInfo.getIsInMouduleScope() && ChildInfo.getODRAvailable())
+                ? LiveRootWorklistActionTy::MarkTypeEntryRec
+                : LiveRootWorklistActionTy::MarkLiveEntryRec;
+
+        addActionToRootEntriesWorkList(Action, ChildEntry, ReferencedBy);
+      }
+    } break;
+    case dwarf::DW_TAG_base_type: {
+      // Always keep base types.
+      addActionToRootEntriesWorkList(
+          LiveRootWorklistActionTy::MarkSingleLiveEntry, ChildEntry,
+          ReferencedBy);
+    } break;
+    case dwarf::DW_TAG_imported_module:
+    case dwarf::DW_TAG_imported_declaration:
+    case dwarf::DW_TAG_imported_unit: {
+      // Always keep DIEs having DW_AT_import attribute.
+      if (Entry.DieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
+        addActionToRootEntriesWorkList(
+            LiveRootWorklistActionTy::MarkSingleLiveEntry, ChildEntry,
+            ReferencedBy);
+        break;
+      }
+
+      addActionToRootEntriesWorkList(
+          LiveRootWorklistActionTy::MarkSingleTypeEntry, ChildEntry,
+          ReferencedBy);
+    } break;
+    case dwarf::DW_TAG_type_unit:
+    case dwarf::DW_TAG_partial_unit:
+    case dwarf::DW_TAG_compile_unit: {
+      llvm_unreachable("Called for incorrect DIE");
+    } break;
+    default:
+      // Nothing to do.
       break;
     }
-    [[fallthrough]];
-  case dwarf::DW_TAG_compile_unit:
-  case dwarf::DW_TAG_namespace:
-  case dwarf::DW_TAG_module:
-  case dwarf::DW_TAG_lexical_block: {
-    for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(Entry);
-         CurChild && CurChild->getAbbreviationDeclarationPtr();
-         CurChild = CU.getSiblingEntry(CurChild))
-      collectRootsToKeep(CU, CurChild);
-  } break;
-  case dwarf::DW_TAG_constant:
-  case dwarf::DW_TAG_variable: {
-    if (isLiveVariableEntry(CU, Entry))
-      addItemToWorklist(CU, Entry);
-  } break;
-  case dwarf::DW_TAG_base_type: {
-    addItemToWorklist(CU, Entry);
-  } break;
-  case dwarf::DW_TAG_imported_module:
-  case dwarf::DW_TAG_imported_declaration:
-  case dwarf::DW_TAG_imported_unit: {
-    addItemToWorklist(CU, Entry);
-  } break;
-  default:
-    // Nothing to do.
-    break;
+
+    collectRootsToKeep(ChildEntry, ReferencedBy, IsLiveChild || IsLiveParent);
   }
 }
 
-bool DependencyTracker::markLiveRootsAsKept() {
+bool DependencyTracker::markCollectedLiveRootsAsKept(
+    bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
   bool Res = true;
 
+  // Mark roots as kept.
   while (!RootEntriesWorkList.empty()) {
-    RootEntryTy CurrentItem = RootEntriesWorkList.pop_back_val();
-
-    if (!markDIEEntryAsKeptRec(CurrentItem, CurrentItem.CU,
-                               CurrentItem.RootEntry))
+    LiveRootWorklistItemTy Root = RootEntriesWorkList.pop_back_val();
+
+    if (markDIEEntryAsKeptRec(Root.getAction(), Root.getRootEntry(),
+                              Root.getRootEntry(), InterCUProcessingStarted,
+                              HasNewInterconnectedCUs)) {
+      if (Root.hasReferencedByOtherEntry())
+        Dependencies.push_back(Root);
+    } else
       Res = false;
   }
 
   return Res;
 }
 
-bool DependencyTracker::markDIEEntryAsKeptRec(
-    const RootEntryTy &RootItem, CompileUnit &CU,
-    const DWARFDebugInfoEntry *Entry) {
-  if (Entry->getAbbreviationDeclarationPtr() == nullptr)
-    return true;
+bool DependencyTracker::updateDependenciesCompleteness() {
+  bool HasNewDependency = false;
+  for (LiveRootWorklistItemTy &Root : Dependencies) {
+    assert(Root.hasReferencedByOtherEntry() &&
+           "Root entry without dependency inside the dependencies list");
+
+    UnitEntryPairTy RootEntry = Root.getRootEntry();
+    CompileUnit::DIEInfo &RootInfo =
+        RootEntry.CU->getDIEInfo(RootEntry.DieEntry);
+
+    UnitEntryPairTy ReferencedByEntry = Root.getReferencedByEntry();
+    CompileUnit::DIEInfo &ReferencedByInfo =
+        ReferencedByEntry.CU->getDIEInfo(ReferencedByEntry.DieEntry);
+
+    if (!RootInfo.needToPlaceInTypeTable() &&
+        ReferencedByInfo.needToPlaceInTypeTable()) {
+      HasNewDependency = true;
+      setPlainDwarfPlacementRec(ReferencedByEntry);
+
+      // FIXME: we probably need to update getKeepTypeChildren status for
+      // parents of *Root.ReferencedBy.
+    }
+  }
+
+  return HasNewDependency;
+}
+
+void DependencyTracker::setPlainDwarfPlacementRec(
+    const UnitEntryPairTy &Entry) {
+  CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
+  if (Info.getPlacement() == CompileUnit::PlainDwarf &&
+      !Info.getKeepTypeChildren())
+    return;
 
-  CompileUnit::DIEInfo &Info = CU.getDIEInfo(Entry);
+  Info.setPlacement(CompileUnit::PlainDwarf);
+  Info.unsetKeepTypeChildren();
+  markParentsAsKeepingChildren(Entry);
 
-  if (Info.getKeep())
+  for (const DWARFDebugInfoEntry *CurChild =
+           Entry.CU->getFirstChildEntry(Entry.DieEntry);
+       CurChild && CurChild->getAbbreviationDeclarationPtr();
+       CurChild = Entry.CU->getSiblingEntry(CurChild))
+    setPlainDwarfPlacementRec(UnitEntryPairTy{Entry.CU, CurChild});
+}
+
+static bool isNamespaceLikeEntry(const DWARFDebugInfoEntry *Entry) {
+  switch (Entry->getTag()) {
+  case dwarf::DW_TAG_compile_unit:
+  case dwarf::DW_TAG_module:
+  case dwarf::DW_TAG_namespace:
     return true;
 
-  // Mark parents as 'KeepChildren'.
-  std::optional<uint32_t> ParentIdx = Entry->getParentIdx();
+  default:
+    return false;
+  }
+}
+
+bool isAlreadyMarked(const CompileUnit::DIEInfo &Info,
+                     CompileUnit::DieOutputPlacement NewPlacement) {
+  if (!Info.getKeep())
+    return false;
+
+  switch (NewPlacement) {
+  case CompileUnit::TypeTable:
+    return Info.needToPlaceInTypeTable();
+
+  case CompileUnit::PlainDwarf:
+    return Info.needToKeepInPlainDwarf();
+
+  case CompileUnit::Both:
+    return Info.needToPlaceInTypeTable() && Info.needToKeepInPlainDwarf();
+
+  case CompileUnit::NotSet:
+    llvm_unreachable("Unset placement type is specified.");
+  };
+}
+
+bool isAlreadyMarked(const UnitEntryPairTy &Entry,
+                     CompileUnit::DieOutputPlacement NewPlacement) {
+  return isAlreadyMarked(Entry.CU->getDIEInfo(Entry.DieEntry), NewPlacement);
+}
+
+void DependencyTracker::markParentsAsKeepingChildren(
+    const UnitEntryPairTy &Entry) {
+  if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
+    return;
+
+  CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
+  bool NeedKeepTypeChildren = Info.needToPlaceInTypeTable();
+  bool NeedKeepPlainChildren = Info.needToKeepInPlainDwarf();
+
+  bool AreTypeParentsDone = !NeedKeepTypeChildren;
+  bool ArePlainParentsDone = !NeedKeepPlainChildren;
+
+  // Mark parents as 'Keep*Children'.
+  std::optional<uint32_t> ParentIdx = Entry.DieEntry->getParentIdx();
   while (ParentIdx) {
-    const DWARFDebugInfoEntry *ParentEntry = CU.getDebugInfoEntry(*ParentIdx);
-    CompileUnit::DIEInfo &ParentInfo = CU.getDIEInfo(*ParentIdx);
-    if (ParentInfo.getKeepChildren())
+    const DWARFDebugInfoEntry *ParentEntry =
+        Entry.CU->getDebugInfoEntry(*ParentIdx);
+    CompileUnit::DIEInfo &ParentInfo = Entry.CU->getDIEInfo(*ParentIdx);
+
+    if (!AreTypeParentsDone && NeedKeepTypeChildren) {
+      if (ParentInfo.getKeepTypeChildren())
+        AreTypeParentsDone = true;
+      else {
+        bool AddToWorklist = !isAlreadyMarked(
+            ParentInfo, CompileUnit::DieOutputPlacement::TypeTable);
+        ParentInfo.setKeepTypeChildren();
+        if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
+          addActionToRootEntriesWorkList(
+              LiveRootWorklistActionTy::MarkTypeChildrenRec,
+              UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
+        }
+      }
+    }
+
+    if (!ArePlainParentsDone && NeedKeepPlainChildren) {
+      if (ParentInfo.getKeepPlainChildren())
+        ArePlainParentsDone = true;
+      else {
+        bool AddToWorklist = !isAlreadyMarked(
+            ParentInfo, CompileUnit::DieOutputPlacement::PlainDwarf);
+        ParentInfo.setKeepPlainChildren();
+        if (AddToWorklist && !isNamespaceLikeEntry(ParentEntry)) {
+          addActionToRootEntriesWorkList(
+              LiveRootWorklistActionTy::MarkLiveChildrenRec,
+              UnitEntryPairTy{Entry.CU, ParentEntry}, std::nullopt);
+        }
+      }
+    }
+
+    if (AreTypeParentsDone && ArePlainParentsDone)
       break;
-    ParentInfo.setKeepChildren();
+
     ParentIdx = ParentEntry->getParentIdx();
   }
+}
+
+// This function tries to set specified \p Placement for the \p Entry.
+// Depending on the concrete entry, the placement could be:
+//  a) changed to another.
+//  b) joined with current entry placement.
+//  c) set as requested.
+static CompileUnit::DieOutputPlacement
+getFinalPlacementForEntry(const UnitEntryPairTy &Entry,
+                          CompileUnit::DieOutputPlacement Placement) {
+  assert((Placement != CompileUnit::NotSet) && "Placement is not set");
+  CompileUnit::DIEInfo &EntryInfo = Entry.CU->getDIEInfo(Entry.DieEntry);
+
+  if (!EntryInfo.getODRAvailable())
+    return CompileUnit::PlainDwarf;
+
+  if (Entry.DieEntry->getTag() == dwarf::DW_TAG_variable) {
+    // Do not put variable into the "TypeTable" and "PlainDwarf" at the same
+    // time.
+    if (EntryInfo.getPlacement() == CompileUnit::PlainDwarf ||
+        EntryInfo.getPlacement() == CompileUnit::Both)
+      return CompileUnit::PlainDwarf;
+
+    if (Placement == CompileUnit::PlainDwarf || Placement == CompileUnit::Both)
+      return CompileUnit::PlainDwarf;
+  }
+
+  switch (EntryInfo.getPlacement()) {
+  case CompileUnit::NotSet:
+    return Placement;
+
+  case CompileUnit::TypeTable:
+    return Placement == CompileUnit::PlainDwarf ? CompileUnit::Both : Placement;
+
+  case CompileUnit::PlainDwarf:
+    return Placement == CompileUnit::TypeTable ? CompileUnit::Both : Placement;
+
+  case CompileUnit::Both:
+    return CompileUnit::Both;
+  };
+
+  llvm_unreachable("Unknown placement type.");
+  return Placement;
+}
+
+bool DependencyTracker::markDIEEntryAsKeptRec(
+    LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
+    const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
+    std::atomic<bool> &HasNewInterconnectedCUs) {
+  if (Entry.DieEntry->getAbbreviationDeclarationPtr() == nullptr)
+    return true;
+
+  CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
+
+  // Calculate final placement placement.
+  CompileUnit::DieOutputPlacement Placement = getFinalPlacementForEntry(
+      Entry,
+      isLiveAction(Action) ? CompileUnit::PlainDwarf : CompileUnit::TypeTable);
+  assert((Info.getODRAvailable() || isLiveAction(Action) ||
+          Placement == CompileUnit::PlainDwarf) &&
+         "Wrong kind of placement for ODR unavailable entry");
+
+  if (!isChildrenAction(Action))
+    if (isAlreadyMarked(Entry, Placement))
+      return true;
 
   // Mark current DIE as kept.
   Info.setKeep();
-  setDIEPlacementAndTypename(Info);
+  Info.setPlacement(Placement);
 
-  // Set liveness information.
-  switch (Entry->getTag()) {
-  case dwarf::DW_TAG_constant:
-  case dwarf::DW_TAG_variable: {
-    isLiveVariableEntry(CU, Entry);
-  } break;
-  case dwarf::DW_TAG_subprogram:
-  case dwarf::DW_TAG_label: {
-    isLiveSubprogramEntry(CU, Entry);
-  } break;
-  default:
-    // Nothing to do.
-    break;
-  }
+  // Set keep children property for parents.
+  markParentsAsKeepingChildren(Entry);
+
+  UnitEntryPairTy FinalRootEntry =
+      Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram ? Entry : RootEntry;
 
   // Analyse referenced DIEs.
   bool Res = true;
-  if (!maybeAddReferencedRoots(RootItem, CU, Entry))
+  if (!maybeAddReferencedRoots(Action, FinalRootEntry, Entry,
+                               InterCUProcessingStarted,
+                               HasNewInterconnectedCUs))
     Res = false;
 
-  // Navigate children.
-  for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(Entry);
+  // Return if we do not need to process children.
+  if (isSingleAction(Action))
+    return Res;
+
+  // Process children.
+  // Check for subprograms special case.
+  if (Entry.DieEntry->getTag() == dwarf::DW_TAG_subprogram &&
+      Info.getODRAvailable()) {
+    // Subprograms is a special case. As it can be root for type DIEs
+    // and itself may be subject to move into the artificial type unit.
+    //  a) Non removable children(like DW_TAG_formal_parameter) should always
+    //     be cloned. They are placed into the "PlainDwarf" and into the
+    //     "TypeTable".
+    //  b) ODR deduplication candidates(type DIEs) children should not be put
+    //  into the "PlainDwarf".
+    //  c) Children keeping addresses and locations(like DW_TAG_call_site)
+    //  should not be put into the "TypeTable".
+    for (const DWARFDebugInfoEntry *CurChild =
+             Entry.CU->getFirstChildEntry(Entry.DieEntry);
+         CurChild && CurChild->getAbbreviationDeclarationPtr();
+         CurChild = Entry.CU->getSiblingEntry(CurChild)) {
+      CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
+
+      switch (CurChild->getTag()) {
+      case dwarf::DW_TAG_variable:
+      case dwarf::DW_TAG_constant:
+      case dwarf::DW_TAG_subprogram:
+      case dwarf::DW_TAG_label: {
+        if (ChildInfo.getHasAnAddress())
+          continue;
+      } break;
+
+      // Entries having following tags could not be removed from the subprogram.
+      case dwarf::DW_TAG_lexical_block:
+      case dwarf::DW_TAG_friend:
+      case dwarf::DW_TAG_inheritance:
+      case dwarf::DW_TAG_formal_parameter:
+      case dwarf::DW_TAG_unspecified_parameters:
+      case dwarf::DW_TAG_template_type_parameter:
+      case dwarf::DW_TAG_template_value_parameter:
+      case dwarf::DW_TAG_GNU_template_parameter_pack:
+      case dwarf::DW_TAG_GNU_formal_parameter_pack:
+      case dwarf::DW_TAG_GNU_template_template_param:
+      case dwarf::DW_TAG_thrown_type: {
+        // Go to the default child handling.
+      } break;
+
+      default: {
+        bool ChildIsTypeTableCandidate = isTypeTableCandidate(CurChild);
+
+        // Skip child marked to be copied into the artificial type unit.
+        if (isLiveAction(Action) && ChildIsTypeTableCandidate)
+          continue;
+
+        // Skip child marked to be copied into the plain unit.
+        if (isTypeAction(Action) && !ChildIsTypeTableCandidate)
+          continue;
+
+        // Go to the default child handling.
+      } break;
+      }
+
+      if (!markDIEEntryAsKeptRec(
+              Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
+              InterCUProcessingStarted, HasNewInterconnectedCUs))
+        Res = false;
+    }
+
+    return Res;
+  }
+
+  // Recursively process children.
+  for (const DWARFDebugInfoEntry *CurChild =
+           Entry.CU->getFirstChildEntry(Entry.DieEntry);
        CurChild && CurChild->getAbbreviationDeclarationPtr();
-       CurChild = CU.getSiblingEntry(CurChild)) {
-    if (!markDIEEntryAsKeptRec(RootItem, CU, CurChild))
+       CurChild = Entry.CU->getSiblingEntry(CurChild)) {
+    CompileUnit::DIEInfo ChildInfo = Entry.CU->getDIEInfo(CurChild);
+    switch (CurChild->getTag()) {
+    case dwarf::DW_TAG_variable:
+    case dwarf::DW_TAG_constant:
+    case dwarf::DW_TAG_subprogram:
+    case dwarf::DW_TAG_label: {
+      if (ChildInfo.getHasAnAddress())
+        continue;
+    } break;
+    default:
+      break; // Nothing to do.
+    };
+
+    if (!markDIEEntryAsKeptRec(
+            Action, FinalRootEntry, UnitEntryPairTy{Entry.CU, CurChild},
+            InterCUProcessingStarted, HasNewInterconnectedCUs))
       Res = false;
   }
 
   return Res;
 }
 
+bool DependencyTracker::isTypeTableCandidate(
+    const DWARFDebugInfoEntry *DIEEntry) {
+  switch (DIEEntry->getTag()) {
+  default:
+    return false;
+
+  case dwarf::DW_TAG_imported_module:
+  case dwarf::DW_TAG_imported_declaration:
+  case dwarf::DW_TAG_imported_unit:
+  case dwarf::DW_TAG_array_type:
+  case dwarf::DW_TAG_class_type:
+  case dwarf::DW_TAG_enumeration_type:
+  case dwarf::DW_TAG_pointer_type:
+  case dwarf::DW_TAG_reference_type:
+  case dwarf::DW_TAG_string_type:
+  case dwarf::DW_TAG_structure_type:
+  case dwarf::DW_TAG_subroutine_type:
+  case dwarf::DW_TAG_typedef:
+  case dwarf::DW_TAG_union_type:
+  case dwarf::DW_TAG_variant:
+  case dwarf::DW_TAG_module:
+  case dwarf::DW_TAG_ptr_to_member_type:
+  case dwarf::DW_TAG_set_type:
+  case dwarf::DW_TAG_subrange_type:
+  case dwarf::DW_TAG_base_type:
+  case dwarf::DW_TAG_const_type:
+  case dwarf::DW_TAG_enumerator:
+  case dwarf::DW_TAG_file_type:
+  case dwarf::DW_TAG_packed_type:
+  case dwarf::DW_TAG_thrown_type:
+  case dwarf::DW_TAG_volatile_type:
+  case dwarf::DW_TAG_dwarf_procedure:
+  case dwarf::DW_TAG_restrict_type:
+  case dwarf::DW_TAG_interface_type:
+  case dwarf::DW_TAG_namespace:
+  case dwarf::DW_TAG_unspecified_type:
+  case dwarf::DW_TAG_shared_type:
+  case dwarf::DW_TAG_rvalue_reference_type:
+  case dwarf::DW_TAG_coarray_type:
+  case dwarf::DW_TAG_dynamic_type:
+  case dwarf::DW_TAG_atomic_type:
+  case dwarf::DW_TAG_immutable_type:
+  case dwarf::DW_TAG_function_template:
+  case dwarf::DW_TAG_class_template:
+    return true;
+  }
+}
+
 bool DependencyTracker::maybeAddReferencedRoots(
-    const RootEntryTy &RootItem, CompileUnit &CU,
-    const DWARFDebugInfoEntry *Entry) {
-  const auto *Abbrev = Entry->getAbbreviationDeclarationPtr();
+    LiveRootWorklistActionTy Action, const UnitEntryPairTy &RootEntry,
+    const UnitEntryPairTy &Entry, bool InterCUProcessingStarted,
+    std::atomic<bool> &HasNewInterconnectedCUs) {
+  const auto *Abbrev = Entry.DieEntry->getAbbreviationDeclarationPtr();
   if (Abbrev == nullptr)
     return true;
 
-  DWARFUnit &Unit = CU.getOrigUnit();
+  DWARFUnit &Unit = Entry.CU->getOrigUnit();
   DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
-  uint64_t Offset = Entry->getOffset() + getULEB128Size(Abbrev->getCode());
+  uint64_t Offset =
+      Entry.DieEntry->getOffset() + getULEB128Size(Abbrev->getCode());
 
   // For each DIE attribute...
   for (const auto &AttrSpec : Abbrev->attributes()) {
@@ -220,132 +631,157 @@ bool DependencyTracker::maybeAddReferencedRoots(
     Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit);
 
     // Resolve reference.
-    std::optional<std::pair<CompileUnit *, uint32_t>> RefDie =
-        CU.resolveDIEReference(
-            Val, Context.InterCUProcessingStarted
-                     ? ResolveInterCUReferencesMode::Resolve
-                     : ResolveInterCUReferencesMode::AvoidResolving);
+    std::optional<UnitEntryPairTy> RefDie = Entry.CU->resolveDIEReference(
+        Val, InterCUProcessingStarted
+                 ? ResolveInterCUReferencesMode::Resolve
+                 : ResolveInterCUReferencesMode::AvoidResolving);
     if (!RefDie) {
-      CU.warn("cann't find referenced DIE", Entry);
+      Entry.CU->warn("cann't find referenced DIE", Entry.DieEntry);
       continue;
     }
 
-    if (RefDie->second == 0) {
+    if (!RefDie->DieEntry) {
       // Delay resolving reference.
-      RefDie->first->setInterconnectedCU();
-      CU.setInterconnectedCU();
-      Context.HasNewInterconnectedCUs = true;
+      RefDie->CU->setInterconnectedCU();
+      Entry.CU->setInterconnectedCU();
+      HasNewInterconnectedCUs = true;
       return false;
     }
 
-    assert(CU.getUniqueID() == RefDie->first->getUniqueID() ||
-           Context.InterCUProcessingStarted);
+    assert((Entry.CU->getUniqueID() == RefDie->CU->getUniqueID() ||
+            InterCUProcessingStarted) &&
+           "Inter-CU reference while inter-CU processing is not started");
+
+    CompileUnit::DIEInfo &RefInfo = RefDie->CU->getDIEInfo(RefDie->DieEntry);
+    if (!RefInfo.getODRAvailable())
+      Action = LiveRootWorklistActionTy::MarkLiveEntryRec;
+    else if (RefInfo.getODRAvailable() &&
+             llvm::is_contained(getODRAttributes(), AttrSpec.Attr))
+      // Note: getODRAttributes does not include DW_AT_containing_type.
+      // It should be OK as we do getRootForSpecifiedEntry(). So any containing
+      // type would be found as the root for the entry.
+      Action = LiveRootWorklistActionTy::MarkTypeEntryRec;
+    else if (isLiveAction(Action))
+      Action = LiveRootWorklistActionTy::MarkLiveEntryRec;
+    else
+      Action = LiveRootWorklistActionTy::MarkTypeEntryRec;
+
+    if (AttrSpec.Attr == dwarf::DW_AT_import) {
+      if (isNamespaceLikeEntry(RefDie->DieEntry)) {
+        addActionToRootEntriesWorkList(
+            isTypeAction(Action)
+                ? LiveRootWorklistActionTy::MarkSingleTypeEntry
+                : LiveRootWorklistActionTy::MarkSingleLiveEntry,
+            *RefDie, RootEntry);
+        continue;
+      }
 
-    addItemToWorklist(*RefDie->first,
-                      RefDie->first->getDebugInfoEntry(RefDie->second));
+      addActionToRootEntriesWorkList(Action, *RefDie, RootEntry);
+      continue;
+    }
+
+    UnitEntryPairTy RootForReferencedDie = getRootForSpecifiedEntry(*RefDie);
+    addActionToRootEntriesWorkList(Action, RootForReferencedDie, RootEntry);
   }
 
   return true;
 }
 
-// Returns true if the specified DIE type allows removing children.
-static bool childrenCanBeRemoved(uint32_t Tag) {
-  switch (Tag) {
-  default:
-    return true;
-  case dwarf::DW_TAG_class_type:
-  case dwarf::DW_TAG_common_block:
-  case dwarf::DW_TAG_lexical_block:
-  case dwarf::DW_TAG_structure_type:
-  case dwarf::DW_TAG_subprogram:
-  case dwarf::DW_TAG_subroutine_type:
-  case dwarf::DW_TAG_union_type:
-  case dwarf::DW_TAG_array_type:
-    return false;
-  }
-  llvm_unreachable("Invalid Tag");
-}
-
-void DependencyTracker::addItemToWorklist(CompileUnit &CU,
-                                          const DWARFDebugInfoEntry *Entry) {
-  if (Entry->getAbbreviationDeclarationPtr() == nullptr)
-    return;
+UnitEntryPairTy
+DependencyTracker::getRootForSpecifiedEntry(UnitEntryPairTy Entry) {
+  UnitEntryPairTy Result = Entry;
+
+  do {
+    switch (Entry.DieEntry->getTag()) {
+    case dwarf::DW_TAG_subprogram:
+    case dwarf::DW_TAG_label:
+    case dwarf::DW_TAG_variable:
+    case dwarf::DW_TAG_constant: {
+      return Result;
+    } break;
+
+    default: {
+      // Nothing to do.
+    }
+    }
 
-  const DWARFDebugInfoEntry *EntryToAdd = Entry;
+    std::optional<uint32_t> ParentIdx = Result.DieEntry->getParentIdx();
+    if (!ParentIdx)
+      return Result;
 
-  // If parent does not allow children removing then use that parent as a root
-  // DIE.
-  std::optional<uint32_t> ParentIdx = Entry->getParentIdx();
-  while (ParentIdx) {
-    const DWARFDebugInfoEntry *ParentEntry = CU.getDebugInfoEntry(*ParentIdx);
-    if (childrenCanBeRemoved(ParentEntry->getTag()))
+    const DWARFDebugInfoEntry *ParentEntry =
+        Result.CU->getDebugInfoEntry(*ParentIdx);
+    if (isNamespaceLikeEntry(ParentEntry))
       break;
-    EntryToAdd = ParentEntry;
-    ParentIdx = ParentEntry->getParentIdx();
-  }
+    Result.DieEntry = ParentEntry;
+  } while (true);
 
-  // Check if the DIE entry is already kept.
-  if (CU.getDIEInfo(EntryToAdd).getKeep())
-    return;
-
-  RootEntriesWorkList.emplace_back(CU, EntryToAdd);
+  return Result;
 }
 
-bool DependencyTracker::isLiveVariableEntry(CompileUnit &CU,
-                                            const DWARFDebugInfoEntry *Entry) {
-  DWARFDie DIE = CU.getDIE(Entry);
-  CompileUnit::DIEInfo &Info = CU.getDIEInfo(DIE);
+bool DependencyTracker::isLiveVariableEntry(const UnitEntryPairTy &Entry,
+                                            bool IsLiveParent) {
+  DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
+  CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(DIE);
 
-  if (TrackLiveness) {
+  if (Info.getTrackLiveness()) {
     const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
 
-    // Global variables with constant value can always be kept.
     if (!Info.getIsInFunctionScope() &&
-        Abbrev->findAttributeIndex(dwarf::DW_AT_const_value))
-      return true;
-
-    // See if there is a relocation to a valid debug map entry inside this
-    // variable's location. The order is important here. We want to always check
-    // if the variable has a location expression address.
-    // However, we don't want a static variable in a function to force us to
-    // keep the enclosing function, unless requested explicitly.
-    std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
-        CU.getContaingFile().Addresses->getVariableRelocAdjustment(DIE);
-
-    if (!LocExprAddrAndRelocAdjustment.second)
-      return false;
+        Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) {
+      // Global variables with constant value can always be kept.
+    } else {
+      // See if there is a relocation to a valid debug map entry inside this
+      // variable's location. The order is important here. We want to always
+      // check if the variable has a location expression address. However, we
+      // don't want a static variable in a function to force us to keep the
+      // enclosing function, unless requested explicitly.
+      std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
+          Entry.CU->getContaingFile().Addresses->getVariableRelocAdjustment(
+              DIE);
+
+      if (LocExprAddrAndRelocAdjustment.first)
+        Info.setHasAnAddress();
+
+      if (!LocExprAddrAndRelocAdjustment.second)
+        return false;
 
-    if ((Info.getIsInFunctionScope()) &&
-        !LLVM_UNLIKELY(CU.getGlobalData().getOptions().KeepFunctionForStatic))
-      return false;
+      if (!IsLiveParent && Info.getIsInFunctionScope() &&
+          !Entry.CU->getGlobalData().getOptions().KeepFunctionForStatic)
+        return false;
+    }
   }
+  Info.setHasAnAddress();
 
-  if (CU.getGlobalData().getOptions().Verbose) {
+  if (Entry.CU->getGlobalData().getOptions().Verbose) {
     outs() << "Keeping variable DIE:";
     DIDumpOptions DumpOpts;
     DumpOpts.ChildRecurseDepth = 0;
-    DumpOpts.Verbose = CU.getGlobalData().getOptions().Verbose;
+    DumpOpts.Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
     DIE.dump(outs(), 8 /* Indent */, DumpOpts);
   }
 
   return true;
 }
 
-bool DependencyTracker::isLiveSubprogramEntry(
-    CompileUnit &CU, const DWARFDebugInfoEntry *Entry) {
-  DWARFDie DIE = CU.getDIE(Entry);
+bool DependencyTracker::isLiveSubprogramEntry(const UnitEntryPairTy &Entry) {
+  DWARFDie DIE = Entry.CU->getDIE(Entry.DieEntry);
+  CompileUnit::DIEInfo &Info = Entry.CU->getDIEInfo(Entry.DieEntry);
+  std::optional<DWARFFormValue> LowPCVal = DIE.find(dwarf::DW_AT_low_pc);
 
   std::optional<uint64_t> LowPc;
   std::optional<uint64_t> HighPc;
   std::optional<int64_t> RelocAdjustment;
-
-  if (TrackLiveness) {
-    LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
+  if (Info.getTrackLiveness()) {
+    LowPc = dwarf::toAddress(LowPCVal);
     if (!LowPc)
       return false;
 
+    Info.setHasAnAddress();
+
     RelocAdjustment =
-        CU.getContaingFile().Addresses->getSubprogramRelocAdjustment(DIE);
+        Entry.CU->getContaingFile().Addresses->getSubprogramRelocAdjustment(
+            DIE);
     if (!RelocAdjustment)
       return false;
 
@@ -354,16 +790,18 @@ bool DependencyTracker::isLiveSubprogramEntry(
 
       HighPc = DIE.getHighPC(*LowPc);
       if (!HighPc) {
-        CU.warn("function without high_pc. Range will be discarded.", &DIE);
+        Entry.CU->warn("function without high_pc. Range will be discarded.",
+                       &DIE);
         return false;
       }
 
       if (*LowPc > *HighPc) {
-        CU.warn("low_pc greater than high_pc. Range will be discarded.", &DIE);
+        Entry.CU->warn("low_pc greater than high_pc. Range will be discarded.",
+                       &DIE);
         return false;
       }
-    } else if (DIE.getTag() == dwarf::DW_TAG_variable) {
-      if (CU.hasLabelAt(*LowPc))
+    } else if (DIE.getTag() == dwarf::DW_TAG_label) {
+      if (Entry.CU->hasLabelAt(*LowPc))
         return false;
 
       // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider
@@ -371,33 +809,29 @@ bool DependencyTracker::isLiveSubprogramEntry(
       // info generation bugs aside, this is really wrong in the case of labels,
       // where a label marking the end of a function will have a PC == CU's
       // high_pc.
-      if (dwarf::toAddress(
-              CU.getOrigUnit().getUnitDIE().find(dwarf::DW_AT_high_pc))
+      if (dwarf::toAddress(Entry.CU->find(Entry.DieEntry, dwarf::DW_AT_high_pc))
               .value_or(UINT64_MAX) <= LowPc)
         return false;
 
-      CU.addLabelLowPc(*LowPc, *RelocAdjustment);
+      Entry.CU->addLabelLowPc(*LowPc, *RelocAdjustment);
     }
-  }
+  } else
+    Info.setHasAnAddress();
 
-  if (CU.getGlobalData().getOptions().Verbose) {
+  if (Entry.CU->getGlobalData().getOptions().Verbose) {
     outs() << "Keeping subprogram DIE:";
     DIDumpOptions DumpOpts;
     DumpOpts.ChildRecurseDepth = 0;
-    DumpOpts.Verbose = CU.getGlobalData().getOptions().Verbose;
+    DumpOpts.Verbose = Entry.CU->getGlobalData().getOptions().Verbose;
     DIE.dump(outs(), 8 /* Indent */, DumpOpts);
   }
 
-  if (!TrackLiveness || DIE.getTag() == dwarf::DW_TAG_label)
+  if (!Info.getTrackLiveness() || DIE.getTag() == dwarf::DW_TAG_label)
     return true;
 
-  CU.addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
+  Entry.CU->addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
   return true;
 }
 
-void DependencyTracker::setDIEPlacementAndTypename(CompileUnit::DIEInfo &Info) {
-  Info.setPlacement(CompileUnit::PlainDwarf);
-}
-
 } // end of namespace dwarflinker_parallel
 } // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DependencyTracker.h b/llvm/lib/DWARFLinkerParallel/DependencyTracker.h
index 69e57bc3ea4d264..abd5371471eb95a 100644
--- a/llvm/lib/DWARFLinkerParallel/DependencyTracker.h
+++ b/llvm/lib/DWARFLinkerParallel/DependencyTracker.h
@@ -10,7 +10,7 @@
 #define LLVM_LIB_DWARFLINKERPARALLEL_DEPENDENCYTRACKER_H
 
 #include "DWARFLinkerCompileUnit.h"
-#include "DWARFLinkerImpl.h"
+#include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/SmallVector.h"
 
 namespace llvm {
@@ -19,10 +19,12 @@ class DWARFDie;
 
 namespace dwarflinker_parallel {
 
-/// This class discovers DIEs dependencies and marks "live" DIEs.
+/// This class discovers DIEs dependencies: marks "live" DIEs, marks DIE
+/// locations (whether DIE should be cloned as regular DIE or it should be put
+/// into the artificial type unit).
 class DependencyTracker {
 public:
-  DependencyTracker(DWARFLinkerImpl::LinkContext &Context) : Context(Context) {}
+  DependencyTracker(CompileUnit &CU) : CU(CU) {}
 
   /// Recursively walk the \p DIE tree and look for DIEs to keep. Store that
   /// information in \p CU's DIEInfo.
@@ -30,70 +32,223 @@ class DependencyTracker {
   /// This function is the entry point of the DIE selection algorithm. It is
   /// expected to walk the DIE tree and(through the mediation of
   /// Context.File.Addresses) ask for relocation adjustment value on each
-  /// DIE that might be a 'root DIE'.
+  /// DIE that might be a 'root DIE'(f.e. subprograms, variables).
   ///
   /// Returns true if all dependencies are correctly discovered. Inter-CU
   /// dependencies cannot be discovered if referenced CU is not analyzed yet.
   /// If that is the case this method returns false.
-  bool resolveDependenciesAndMarkLiveness(CompileUnit &CU);
+  bool resolveDependenciesAndMarkLiveness(
+      bool InterCUProcessingStarted,
+      std::atomic<bool> &HasNewInterconnectedCUs);
 
-  /// Recursively walk the \p DIE tree and check "keepness" information.
-  /// It is an error if parent node does not have "keep" flag, while
-  /// child have one. This function dump error at stderr in that case.
-#ifndef NDEBUG
-  static void verifyKeepChain(CompileUnit &CU);
-#endif
+  /// Check if dependencies have incompatible placement.
+  /// If that is the case modify placement to be compatible.
+  /// \returns true if any placement was updated, otherwise returns false.
+  /// This method should be called as a followup processing after
+  /// resolveDependenciesAndMarkLiveness().
+  bool updateDependenciesCompleteness();
+
+  /// Recursively walk the \p DIE tree and check "keepness" and "placement"
+  /// information. It is an error if parent node does not have "keep" flag,
+  /// while child has one. It is an error if parent node has "TypeTable"
+  /// placement while child has "PlainDwarf" placement. This function dump error
+  /// at stderr in that case.
+  void verifyKeepChain();
 
 protected:
-  struct RootEntryTy {
-    RootEntryTy(CompileUnit &CU, const DWARFDebugInfoEntry *RootEntry)
-        : CU(CU), RootEntry(RootEntry) {}
+  enum class LiveRootWorklistActionTy : uint8_t {
+    /// Mark current item as live entry.
+    MarkSingleLiveEntry = 0,
+
+    /// Mark current item as type entry.
+    MarkSingleTypeEntry,
+
+    /// Mark current item and all its children as live entry.
+    MarkLiveEntryRec,
+
+    /// Mark current item and all its children as type entry.
+    MarkTypeEntryRec,
+
+    /// Mark all children of current item as live entry.
+    MarkLiveChildrenRec,
+
+    /// Mark all children of current item as type entry.
+    MarkTypeChildrenRec,
+  };
+
+  /// \returns true if the specified action is for the "PlainDwarf".
+  bool isLiveAction(LiveRootWorklistActionTy Action) {
+    switch (Action) {
+    default:
+      return false;
+
+    case LiveRootWorklistActionTy::MarkSingleLiveEntry:
+    case LiveRootWorklistActionTy::MarkLiveEntryRec:
+    case LiveRootWorklistActionTy::MarkLiveChildrenRec:
+      return true;
+    }
+  }
+
+  /// \returns true if the specified action is for the "TypeTable".
+  bool isTypeAction(LiveRootWorklistActionTy Action) {
+    switch (Action) {
+    default:
+      return false;
+
+    case LiveRootWorklistActionTy::MarkSingleTypeEntry:
+    case LiveRootWorklistActionTy::MarkTypeEntryRec:
+    case LiveRootWorklistActionTy::MarkTypeChildrenRec:
+      return true;
+    }
+  }
+
+  /// \returns true if the specified action affects only Root entry
+  /// itself and does not affect it`s children.
+  bool isSingleAction(LiveRootWorklistActionTy Action) {
+    switch (Action) {
+    default:
+      return false;
+
+    case LiveRootWorklistActionTy::MarkSingleLiveEntry:
+    case LiveRootWorklistActionTy::MarkSingleTypeEntry:
+      return true;
+    }
+  }
 
-    // Compile unit keeping root entry.
-    CompileUnit &CU;
+  /// \returns true if the specified action affects only Root entry
+  /// itself and does not affect it`s children.
+  bool isChildrenAction(LiveRootWorklistActionTy Action) {
+    switch (Action) {
+    default:
+      return false;
 
-    // Root entry.
-    const DWARFDebugInfoEntry *RootEntry;
+    case LiveRootWorklistActionTy::MarkLiveChildrenRec:
+    case LiveRootWorklistActionTy::MarkTypeChildrenRec:
+      return true;
+    }
+  }
+
+  /// Class keeping live worklist item data.
+  class LiveRootWorklistItemTy {
+  public:
+    LiveRootWorklistItemTy() = default;
+    LiveRootWorklistItemTy(const LiveRootWorklistItemTy &) = default;
+    LiveRootWorklistItemTy(LiveRootWorklistActionTy Action,
+                           UnitEntryPairTy RootEntry) {
+      RootCU.setInt(static_cast<uint8_t>(Action));
+      RootCU.setPointer(RootEntry.CU);
+
+      RootDieEntry = RootEntry.DieEntry;
+    }
+    LiveRootWorklistItemTy(LiveRootWorklistActionTy Action,
+                           UnitEntryPairTy RootEntry,
+                           UnitEntryPairTy ReferencedBy) {
+      RootCU.setPointer(RootEntry.CU);
+      RootCU.setInt(static_cast<uint8_t>(Action));
+      RootDieEntry = RootEntry.DieEntry;
+
+      ReferencedByCU = ReferencedBy.CU;
+      ReferencedByDieEntry = ReferencedBy.DieEntry;
+    }
+
+    UnitEntryPairTy getRootEntry() const {
+      return UnitEntryPairTy{RootCU.getPointer(), RootDieEntry};
+    }
+
+    CompileUnit::DieOutputPlacement getPlacement() const {
+      return static_cast<CompileUnit::DieOutputPlacement>(RootCU.getInt());
+    }
+
+    bool hasReferencedByOtherEntry() const { return ReferencedByCU != nullptr; }
+
+    UnitEntryPairTy getReferencedByEntry() const {
+      assert(ReferencedByCU);
+      assert(ReferencedByDieEntry);
+      return UnitEntryPairTy{ReferencedByCU, ReferencedByDieEntry};
+    }
+
+    LiveRootWorklistActionTy getAction() const {
+      return static_cast<LiveRootWorklistActionTy>(RootCU.getInt());
+    }
+
+  protected:
+    /// Root entry.
+    /// ASSUMPTION: 3 bits are used to store LiveRootWorklistActionTy value.
+    /// Thus LiveRootWorklistActionTy should have no more eight elements.
+    PointerIntPair<CompileUnit *, 3> RootCU;
+    const DWARFDebugInfoEntry *RootDieEntry = nullptr;
+
+    /// Another root entry which references this RootDieEntry.
+    /// ReferencedByDieEntry is kept to update placement.
+    /// if RootDieEntry has placement incompatible with placement
+    /// of ReferencedByDieEntry then it should be updated.
+    CompileUnit *ReferencedByCU = nullptr;
+    const DWARFDebugInfoEntry *ReferencedByDieEntry = nullptr;
   };
 
-  using RootEntriesListTy = SmallVector<RootEntryTy>;
+  using RootEntriesListTy = SmallVector<LiveRootWorklistItemTy>;
 
   /// This function navigates DIEs tree starting from specified \p Entry.
-  /// It puts 'root DIE' into the worklist.
-  void collectRootsToKeep(CompileUnit &CU, const DWARFDebugInfoEntry *Entry);
+  /// It puts found 'root DIE' into the worklist. The \p CollectLiveEntries
+  /// instructs to collect either live roots(like subprograms having live
+  /// DW_AT_low_pc) or otherwise roots which is not live(they need to be
+  /// collected if they are imported f.e. by DW_TAG_imported_module).
+  void collectRootsToKeep(const UnitEntryPairTy &Entry,
+                          std::optional<UnitEntryPairTy> ReferencedBy,
+                          bool IsLiveParent);
 
   /// Returns true if specified variable references live code section.
-  bool isLiveVariableEntry(CompileUnit &CU, const DWARFDebugInfoEntry *Entry);
+  static bool isLiveVariableEntry(const UnitEntryPairTy &Entry,
+                                  bool IsLiveParent);
 
   /// Returns true if specified subprogram references live code section.
-  bool isLiveSubprogramEntry(CompileUnit &CU, const DWARFDebugInfoEntry *Entry);
+  static bool isLiveSubprogramEntry(const UnitEntryPairTy &Entry);
 
-  /// Examine worklist and mark all 'root DIE's as kept.
-  bool markLiveRootsAsKept();
+  /// Examine worklist and mark all 'root DIE's as kept and set "Placement"
+  /// property.
+  bool markCollectedLiveRootsAsKept(bool InterCUProcessingStarted,
+                                    std::atomic<bool> &HasNewInterconnectedCUs);
 
   /// Mark whole DIE tree as kept recursively.
-  bool markDIEEntryAsKeptRec(const RootEntryTy &RootItem, CompileUnit &CU,
-                             const DWARFDebugInfoEntry *Entry);
+  bool markDIEEntryAsKeptRec(LiveRootWorklistActionTy Action,
+                             const UnitEntryPairTy &RootEntry,
+                             const UnitEntryPairTy &Entry,
+                             bool InterCUProcessingStarted,
+                             std::atomic<bool> &HasNewInterconnectedCUs);
+
+  /// Mark parents as keeping children.
+  void markParentsAsKeepingChildren(const UnitEntryPairTy &Entry);
+
+  /// Mark whole DIE tree as placed in "PlainDwarf".
+  void setPlainDwarfPlacementRec(const UnitEntryPairTy &Entry);
+
+  /// Check referenced DIEs and add them into the worklist.
+  bool maybeAddReferencedRoots(LiveRootWorklistActionTy Action,
+                               const UnitEntryPairTy &RootEntry,
+                               const UnitEntryPairTy &Entry,
+                               bool InterCUProcessingStarted,
+                               std::atomic<bool> &HasNewInterconnectedCUs);
 
-  /// Check referenced DIEs and add them into the worklist if neccessary.
-  bool maybeAddReferencedRoots(const RootEntryTy &RootItem, CompileUnit &CU,
-                               const DWARFDebugInfoEntry *Entry);
+  /// \returns true if \p DIEEntry can possibly be put into the artificial type
+  /// unit.
+  bool isTypeTableCandidate(const DWARFDebugInfoEntry *DIEEntry);
 
-  /// Add 'root DIE' into the worklist.
-  void addItemToWorklist(CompileUnit &CU, const DWARFDebugInfoEntry *Entry);
+  /// \returns root for the specified \p Entry.
+  UnitEntryPairTy getRootForSpecifiedEntry(UnitEntryPairTy Entry);
 
-  /// Set kind of placement(whether it goes into type table, plain dwarf or
-  /// both) for the specified die \p DieIdx.
-  void setDIEPlacementAndTypename(CompileUnit::DIEInfo &Info);
+  /// Add action item to the work list.
+  void
+  addActionToRootEntriesWorkList(LiveRootWorklistActionTy Action,
+                                 const UnitEntryPairTy &Entry,
+                                 std::optional<UnitEntryPairTy> ReferencedBy);
 
-  /// Flag indicating whether liveness information should be examined.
-  bool TrackLiveness = false;
+  CompileUnit &CU;
 
-  /// List of CU, Entry pairs which are 'root DIE's.
+  /// List of entries which are 'root DIE's.
   RootEntriesListTy RootEntriesWorkList;
 
-  /// Link context for the analyzed CU.
-  DWARFLinkerImpl::LinkContext &Context;
+  /// List of entries dependencies.
+  RootEntriesListTy Dependencies;
 };
 
 } // end namespace dwarflinker_parallel
diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp b/llvm/lib/DWARFLinkerParallel/OutputSections.cpp
index 8e7caa7bb407425..9c3e3ebd220aaf4 100644
--- a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp
+++ b/llvm/lib/DWARFLinkerParallel/OutputSections.cpp
@@ -8,6 +8,7 @@
 
 #include "OutputSections.h"
 #include "DWARFLinkerCompileUnit.h"
+#include "DWARFLinkerTypeUnit.h"
 #include "llvm/ADT/StringSwitch.h"
 
 namespace llvm {
@@ -92,6 +93,33 @@ DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,
       RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),
       RefDieIdxOrClonedOffset(RefIdx) {}
 
+DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,
+                                           TypeEntry *RefTypeName)
+    : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}
+
+DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,
+                                                     DIE *Die,
+                                                     TypeEntry *TypeName,
+                                                     TypeEntry *RefTypeName)
+    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
+      RefTypeName(RefTypeName) {}
+
+DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,
+                                     TypeEntry *TypeName, StringEntry *String)
+    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
+      String(String) {}
+
+DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,
+                                             TypeEntry *TypeName,
+                                             StringEntry *String)
+    : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),
+      String(String) {}
+
+DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,
+                                               StringEntry *Directory,
+                                               StringEntry *FilePath)
+    : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}
+
 void SectionDescriptor::clearAllSectionData() {
   StartOffset = 0;
   clearSectionContent();
@@ -102,6 +130,10 @@ void SectionDescriptor::clearAllSectionData() {
   ListDebugDieRefPatch.erase();
   ListDebugULEB128DieRefPatch.erase();
   ListDebugOffsetPatch.erase();
+  ListDebugType2TypeDieRefPatch.erase();
+  ListDebugTypeDeclFilePatch.erase();
+  ListDebugTypeLineStrPatch.erase();
+  ListDebugTypeStrPatch.erase();
 }
 
 void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
@@ -144,6 +176,30 @@ void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
   }
 }
 
+void SectionDescriptor::emitString(dwarf::Form StringForm,
+                                   const char *StringVal) {
+  assert(StringVal != nullptr);
+
+  switch (StringForm) {
+  case dwarf::DW_FORM_string: {
+    emitInplaceString(StringVal);
+  } break;
+  case dwarf::DW_FORM_strp: {
+    notePatch(DebugStrPatch{
+        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
+    emitStringPlaceholder();
+  } break;
+  case dwarf::DW_FORM_line_strp: {
+    notePatch(DebugLineStrPatch{
+        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
+    emitStringPlaceholder();
+  } break;
+  default:
+    llvm_unreachable("Unsupported string form");
+    break;
+  };
+}
+
 void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
   switch (Size) {
   case 1: {
@@ -171,30 +227,6 @@ void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {
   }
 }
 
-void SectionDescriptor::emitString(dwarf::Form StringForm,
-                                   const char *StringVal) {
-  assert(StringVal != nullptr);
-
-  switch (StringForm) {
-  case dwarf::DW_FORM_string: {
-    emitInplaceString(StringVal);
-  } break;
-  case dwarf::DW_FORM_strp: {
-    notePatch(DebugStrPatch{
-        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
-    emitStringPlaceholder();
-  } break;
-  case dwarf::DW_FORM_line_strp: {
-    notePatch(DebugLineStrPatch{
-        {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});
-    emitStringPlaceholder();
-  } break;
-  default:
-    llvm_unreachable("Unsupported string form");
-    break;
-  };
-}
-
 void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
                               uint64_t Val) {
   switch (AttrForm) {
@@ -330,8 +362,8 @@ void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
 void OutputSections::applyPatches(
     SectionDescriptor &Section,
     StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
-    StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings) {
-
+    StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
+    TypeUnit *TypeUnitPtr) {
   Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
     DwarfStringPoolEntryWithExtString *Entry =
         DebugStrStrings.getExistingEntry(Patch.String);
@@ -339,6 +371,26 @@ void OutputSections::applyPatches(
 
     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
   });
+  Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
+    assert(TypeUnitPtr != nullptr);
+    TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
+    assert(TypeEntry &&
+           formatv("No data for type {0}", Patch.TypeName->getKey())
+               .str()
+               .c_str());
+
+    if (&TypeEntry->getFinalDie() != Patch.Die)
+      return;
+
+    DwarfStringPoolEntryWithExtString *Entry =
+        DebugStrStrings.getExistingEntry(Patch.String);
+    assert(Entry != nullptr);
+
+    Patch.PatchOffset +=
+        Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
+
+    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);
+  });
 
   Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
     DwarfStringPoolEntryWithExtString *Entry =
@@ -347,6 +399,26 @@ void OutputSections::applyPatches(
 
     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
   });
+  Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {
+    assert(TypeUnitPtr != nullptr);
+    TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
+    assert(TypeEntry &&
+           formatv("No data for type {0}", Patch.TypeName->getKey())
+               .str()
+               .c_str());
+
+    if (&TypeEntry->getFinalDie() != Patch.Die)
+      return;
+
+    DwarfStringPoolEntryWithExtString *Entry =
+        DebugLineStrStrings.getExistingEntry(Patch.String);
+    assert(Entry != nullptr);
+
+    Patch.PatchOffset +=
+        Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());
+
+    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);
+  });
 
   std::optional<SectionDescriptor *> RangeSection;
   if (Format.Version >= 5)
@@ -404,6 +476,46 @@ void OutputSections::applyPatches(
                       Patch.RefDieIdxOrClonedOffset);
       });
 
+  Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {
+    assert(TypeUnitPtr != nullptr);
+    assert(Patch.RefTypeName != nullptr);
+
+    TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();
+    assert(TypeEntry &&
+           formatv("No data for type {0}", Patch.RefTypeName->getKey())
+               .str()
+               .c_str());
+
+    Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,
+                  TypeEntry->getFinalDie().getOffset());
+  });
+
+  Section.ListDebugType2TypeDieRefPatch.forEach(
+      [&](DebugType2TypeDieRefPatch &Patch) {
+        assert(TypeUnitPtr != nullptr);
+        TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
+        assert(TypeEntry &&
+               formatv("No data for type {0}", Patch.TypeName->getKey())
+                   .str()
+                   .c_str());
+
+        if (&TypeEntry->getFinalDie() != Patch.Die)
+          return;
+
+        Patch.PatchOffset += Patch.Die->getOffset() +
+                             getULEB128Size(Patch.Die->getAbbrevNumber());
+
+        assert(Patch.RefTypeName != nullptr);
+        TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();
+        assert(TypeEntry &&
+               formatv("No data for type {0}", Patch.RefTypeName->getKey())
+                   .str()
+                   .c_str());
+
+        Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,
+                      RefTypeEntry->getFinalDie().getOffset());
+      });
+
   Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {
     uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;
 
diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.h b/llvm/lib/DWARFLinkerParallel/OutputSections.h
index b101ac61935c5cf..f23b2efb869da8e 100644
--- a/llvm/lib/DWARFLinkerParallel/OutputSections.h
+++ b/llvm/lib/DWARFLinkerParallel/OutputSections.h
@@ -31,6 +31,8 @@
 namespace llvm {
 namespace dwarflinker_parallel {
 
+class TypeUnit;
+
 /// List of tracked debug tables.
 enum class DebugSectionKind : uint8_t {
   DebugInfo = 0,
@@ -113,7 +115,7 @@ struct DebugDieRefPatch : SectionPatch {
                    uint32_t RefIdx);
 
   PointerIntPair<CompileUnit *, 1> RefCU;
-  uint64_t RefDieIdxOrClonedOffset;
+  uint64_t RefDieIdxOrClonedOffset = 0;
 };
 
 /// This structure is used to update reference to the DIE of ULEB128 form.
@@ -122,7 +124,53 @@ struct DebugULEB128DieRefPatch : SectionPatch {
                           CompileUnit *RefCU, uint32_t RefIdx);
 
   PointerIntPair<CompileUnit *, 1> RefCU;
-  uint64_t RefDieIdxOrClonedOffset;
+  uint64_t RefDieIdxOrClonedOffset = 0;
+};
+
+/// This structure is used to update reference to the type DIE.
+struct DebugDieTypeRefPatch : SectionPatch {
+  DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName);
+
+  TypeEntry *RefTypeName = nullptr;
+};
+
+/// This structure is used to update reference to the type DIE.
+struct DebugType2TypeDieRefPatch : SectionPatch {
+  DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
+                            TypeEntry *RefTypeName);
+
+  DIE *Die = nullptr;
+  TypeEntry *TypeName = nullptr;
+  TypeEntry *RefTypeName = nullptr;
+};
+
+struct DebugTypeStrPatch : SectionPatch {
+  DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
+                    StringEntry *String);
+
+  DIE *Die = nullptr;
+  TypeEntry *TypeName = nullptr;
+  StringEntry *String = nullptr;
+};
+
+struct DebugTypeLineStrPatch : SectionPatch {
+  DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName,
+                        StringEntry *String);
+
+  DIE *Die = nullptr;
+  TypeEntry *TypeName = nullptr;
+  StringEntry *String = nullptr;
+};
+
+struct DebugTypeDeclFilePatch {
+  DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory,
+                         StringEntry *FilePath);
+
+  DIE *Die = nullptr;
+  TypeEntry *TypeName = nullptr;
+  StringEntry *Directory = nullptr;
+  StringEntry *FilePath = nullptr;
+  uint32_t FileID = 0;
 };
 
 /// Type for section data.
@@ -140,16 +188,20 @@ struct SectionDescriptor {
 
   SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
                     dwarf::FormParams Format, llvm::endianness Endianess)
-      : OS(Contents), GlobalData(GlobalData), SectionKind(SectionKind),
-        Format(Format), Endianess(Endianess) {
-    ListDebugStrPatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugLineStrPatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugRangePatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugLocPatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugDieRefPatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugULEB128DieRefPatch.setAllocator(&GlobalData.getAllocator());
-    ListDebugOffsetPatch.setAllocator(&GlobalData.getAllocator());
-  }
+      : OS(Contents), ListDebugStrPatch(&GlobalData.getAllocator()),
+        ListDebugLineStrPatch(&GlobalData.getAllocator()),
+        ListDebugRangePatch(&GlobalData.getAllocator()),
+        ListDebugLocPatch(&GlobalData.getAllocator()),
+        ListDebugDieRefPatch(&GlobalData.getAllocator()),
+        ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()),
+        ListDebugOffsetPatch(&GlobalData.getAllocator()),
+        ListDebugDieTypeRefPatch(&GlobalData.getAllocator()),
+        ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()),
+        ListDebugTypeStrPatch(&GlobalData.getAllocator()),
+        ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),
+        ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),
+        GlobalData(GlobalData), SectionKind(SectionKind), Format(Format),
+        Endianess(Endianess) {}
 
   /// Erase whole section contents(data bits, list of patches).
   void clearAllSectionData();
@@ -178,9 +230,16 @@ struct SectionDescriptor {
   ADD_PATCHES_LIST(DebugDieRefPatch)
   ADD_PATCHES_LIST(DebugULEB128DieRefPatch)
   ADD_PATCHES_LIST(DebugOffsetPatch)
-
-  /// Offsets to some fields are not known at the moment of noting patch.
-  /// In that case we remember pointers to patch offset to update them later.
+  ADD_PATCHES_LIST(DebugDieTypeRefPatch)
+  ADD_PATCHES_LIST(DebugType2TypeDieRefPatch)
+  ADD_PATCHES_LIST(DebugTypeStrPatch)
+  ADD_PATCHES_LIST(DebugTypeLineStrPatch)
+  ADD_PATCHES_LIST(DebugTypeDeclFilePatch)
+
+  /// While creating patches, offsets to attributes may be partially
+  /// unknown(because size of abbreviation number is unknown). In such case we
+  /// remember patch itself and pointer to patch application offset to add size
+  /// of abbreviation number later.
   template <typename T>
   void notePatchWithOffsetUpdate(const T &Patch,
                                  OffsetsPtrVector &PatchesOffsetsList) {
@@ -222,7 +281,6 @@ struct SectionDescriptor {
   /// Emit specified integer value into the current section contents.
   void emitIntVal(uint64_t Val, unsigned Size);
 
-  /// Emit specified string value into the current section contents.
   void emitString(dwarf::Form StringForm, const char *StringVal);
 
   /// Emit specified inplace string value into the current section contents.
@@ -395,7 +453,8 @@ class OutputSections {
   /// Enumerate all sections, for each section apply all section patches.
   void applyPatches(SectionDescriptor &Section,
                     StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,
-                    StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings);
+                    StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,
+                    TypeUnit *TypeUnitPtr);
 
   /// Endiannes for the sections.
   llvm::endianness getEndianness() const { return Endianness; }
diff --git a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp b/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp
new file mode 100644
index 000000000000000..e0900f7a8e3d3eb
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp
@@ -0,0 +1,767 @@
+//===- SyntheticTypeNameBuilder.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntheticTypeNameBuilder.h"
+#include "DWARFLinkerCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+Error SyntheticTypeNameBuilder::assignName(
+    UnitEntryPairTy InputUnitEntryPair,
+    std::optional<std::pair<size_t, size_t>> ChildIndex) {
+  [[maybe_unused]] const CompileUnit::DIEInfo &Info =
+      InputUnitEntryPair.CU->getDIEInfo(InputUnitEntryPair.DieEntry);
+  assert(Info.needToPlaceInTypeTable() &&
+         "Cann't assign name for non-type DIE");
+
+  if (InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry) !=
+      nullptr)
+    return Error::success();
+
+  SyntheticName.resize(0);
+  RecursionDepth = 0;
+  return addDIETypeName(InputUnitEntryPair, ChildIndex, true);
+}
+
+void SyntheticTypeNameBuilder::addArrayDimension(
+    UnitEntryPairTy InputUnitEntryPair) {
+  for (const DWARFDebugInfoEntry *CurChild =
+           InputUnitEntryPair.CU->getFirstChildEntry(
+               InputUnitEntryPair.DieEntry);
+       CurChild && CurChild->getAbbreviationDeclarationPtr();
+       CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
+    if (CurChild->getTag() == dwarf::DW_TAG_subrange_type ||
+        CurChild->getTag() == dwarf::DW_TAG_generic_subrange) {
+      SyntheticName += "[";
+      if (std::optional<DWARFFormValue> Val =
+              InputUnitEntryPair.CU->find(CurChild, dwarf::DW_AT_count)) {
+        if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
+          SyntheticName += std::to_string(*ConstVal);
+        } else if (std::optional<int64_t> ConstVal =
+                       Val->getAsSignedConstant()) {
+          SyntheticName += std::to_string(*ConstVal);
+        }
+      }
+
+      SyntheticName += "]";
+    }
+  }
+}
+
+static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
+Error SyntheticTypeNameBuilder::addSignature(UnitEntryPairTy InputUnitEntryPair,
+                                             bool addTemplateParameters) {
+  // Add entry type.
+  if (Error Err = addReferencedODRDies(InputUnitEntryPair, false, TypeAttr))
+    return Err;
+  SyntheticName += ':';
+
+  SmallVector<const DWARFDebugInfoEntry *, 10> TemplateParameters;
+  SmallVector<const DWARFDebugInfoEntry *, 20> FunctionParameters;
+  for (const DWARFDebugInfoEntry *CurChild =
+           InputUnitEntryPair.CU->getFirstChildEntry(
+               InputUnitEntryPair.DieEntry);
+       CurChild && CurChild->getAbbreviationDeclarationPtr();
+       CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
+    dwarf::Tag ChildTag = CurChild->getTag();
+    if (addTemplateParameters &&
+        (ChildTag == dwarf::DW_TAG_template_type_parameter ||
+         ChildTag == dwarf::DW_TAG_template_value_parameter))
+      TemplateParameters.push_back(CurChild);
+    else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
+             ChildTag == dwarf::DW_TAG_unspecified_parameters)
+      FunctionParameters.push_back(CurChild);
+    else if (addTemplateParameters &&
+             ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
+      for (const DWARFDebugInfoEntry *CurGNUChild =
+               InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
+           CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
+           CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
+        TemplateParameters.push_back(CurGNUChild);
+    } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
+      for (const DWARFDebugInfoEntry *CurGNUChild =
+               InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
+           CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
+           CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
+        FunctionParameters.push_back(CurGNUChild);
+    }
+  }
+
+  // Add parameters.
+  if (Error Err = addParamNames(*InputUnitEntryPair.CU, FunctionParameters))
+    return Err;
+
+  // Add template parameters.
+  if (Error Err =
+          addTemplateParamNames(*InputUnitEntryPair.CU, TemplateParameters))
+    return Err;
+
+  return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addParamNames(
+    CompileUnit &CU,
+    SmallVector<const DWARFDebugInfoEntry *, 20> &FunctionParameters) {
+  SyntheticName += '(';
+  for (const DWARFDebugInfoEntry *FunctionParameter : FunctionParameters) {
+    if (SyntheticName.back() != '(')
+      SyntheticName += ", ";
+    if (dwarf::toUnsigned(CU.find(FunctionParameter, dwarf::DW_AT_artificial),
+                          0))
+      SyntheticName += "^";
+    if (Error Err = addReferencedODRDies(
+            UnitEntryPairTy{&CU, FunctionParameter}, false, TypeAttr))
+      return Err;
+  }
+  SyntheticName += ')';
+  return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addTemplateParamNames(
+    CompileUnit &CU,
+    SmallVector<const DWARFDebugInfoEntry *, 10> &TemplateParameters) {
+  if (!TemplateParameters.empty()) {
+    SyntheticName += '<';
+    for (const DWARFDebugInfoEntry *Parameter : TemplateParameters) {
+      if (SyntheticName.back() != '<')
+        SyntheticName += ", ";
+
+      if (Parameter->getTag() == dwarf::DW_TAG_template_value_parameter) {
+        if (std::optional<DWARFFormValue> Val =
+                CU.find(Parameter, dwarf::DW_AT_const_value)) {
+          if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
+            SyntheticName += std::to_string(*ConstVal);
+          else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
+            SyntheticName += std::to_string(*ConstVal);
+        }
+      }
+
+      if (Error Err = addReferencedODRDies(UnitEntryPairTy{&CU, Parameter},
+                                           false, TypeAttr))
+        return Err;
+    }
+    SyntheticName += '>';
+  }
+  return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addOrderedName(
+    std::pair<size_t, size_t> ChildIdx) {
+  std::string Name;
+  llvm::raw_string_ostream stream(Name);
+  stream << format_hex_no_prefix(ChildIdx.first, ChildIdx.second);
+  SyntheticName += Name;
+}
+
+// Examine DIE and return type deduplication candidate: some DIEs could not be
+// deduplicated, namespace may refer to another namespace.
+static std::optional<UnitEntryPairTy>
+getTypeDeduplicationCandidate(UnitEntryPairTy UnitEntryPair) {
+  switch (UnitEntryPair.DieEntry->getTag()) {
+  case dwarf::DW_TAG_null:
+  case dwarf::DW_TAG_compile_unit:
+  case dwarf::DW_TAG_partial_unit:
+  case dwarf::DW_TAG_type_unit:
+  case dwarf::DW_TAG_skeleton_unit: {
+    return std::nullopt;
+  }
+  case dwarf::DW_TAG_namespace: {
+    // Check if current namespace refers another.
+    if (UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_extension))
+      UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
+
+    // Content of anonimous namespaces should not be deduplicated.
+    if (!UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_name))
+      llvm_unreachable("Cann't deduplicate anonimous namespace");
+
+    return UnitEntryPair;
+  }
+  default:
+    return UnitEntryPair;
+  }
+}
+
+Error SyntheticTypeNameBuilder::addParentName(
+    UnitEntryPairTy &InputUnitEntryPair) {
+  std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
+  if (!UnitEntryPair)
+    return Error::success();
+
+  UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
+  if (!UnitEntryPair)
+    return Error::success();
+
+  if (TypeEntry *ImmediateParentName =
+          UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry)) {
+    SyntheticName += ImmediateParentName->getKey();
+    SyntheticName += ".";
+    return Error::success();
+  }
+
+  // Collect parent entries.
+  SmallVector<UnitEntryPairTy, 10> Parents;
+  do {
+    Parents.push_back(*UnitEntryPair);
+
+    UnitEntryPair = UnitEntryPair->getParent();
+    if (!UnitEntryPair)
+      break;
+
+    UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
+    if (!UnitEntryPair)
+      break;
+
+  } while (!UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry));
+
+  // Assign name for each parent entry.
+  size_t NameStart = SyntheticName.size();
+  for (UnitEntryPairTy Parent : reverse(Parents)) {
+    SyntheticName.resize(NameStart);
+    if (Error Err = addDIETypeName(Parent, std::nullopt, true))
+      return Err;
+  }
+
+  // Add parents delimiter.
+  SyntheticName += ".";
+  return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addDieNameFromDeclFileAndDeclLine(
+    UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
+  if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
+          InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_file)) {
+    if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
+            InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_line)) {
+      if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
+              InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
+                  *DeclFileVal)) {
+        SyntheticName += DirAndFilename->first;
+        SyntheticName += DirAndFilename->second;
+
+        if (std::optional<uint64_t> DeclLineIntVal =
+                dwarf::toUnsigned(*DeclLineVal)) {
+          SyntheticName += " ";
+          SyntheticName += utohexstr(*DeclLineIntVal);
+        }
+
+        HasDeclFileName = true;
+      }
+    }
+  }
+}
+
+void SyntheticTypeNameBuilder::addValueName(UnitEntryPairTy InputUnitEntryPair,
+                                            dwarf::Attribute Attr) {
+  if (std::optional<DWARFFormValue> Val =
+          InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
+    if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
+      SyntheticName += " ";
+      SyntheticName += std::to_string(*ConstVal);
+    } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
+      SyntheticName += " ";
+      SyntheticName += std::to_string(*ConstVal);
+    }
+  }
+}
+
+Error SyntheticTypeNameBuilder::addReferencedODRDies(
+    UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor,
+    ArrayRef<dwarf::Attribute> ODRAttrs) {
+  bool FirstIteration = true;
+  for (dwarf::Attribute Attr : ODRAttrs) {
+    if (std::optional<DWARFFormValue> AttrValue =
+            InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
+      std::optional<UnitEntryPairTy> RefDie =
+          InputUnitEntryPair.CU->resolveDIEReference(
+              *AttrValue, ResolveInterCUReferencesMode::Resolve);
+
+      if (!RefDie)
+        continue;
+
+      if (!RefDie->DieEntry)
+        return createStringError(std::errc::invalid_argument,
+                                 "Cann't resolve DIE reference");
+
+      if (!FirstIteration)
+        SyntheticName += ",";
+
+      RecursionDepth++;
+      if (RecursionDepth > 1000)
+        return createStringError(
+            std::errc::invalid_argument,
+            "Cann't parse input DWARF. Recursive dependence.");
+
+      if (Error Err =
+              addDIETypeName(*RefDie, std::nullopt, AssignNameToTypeDescriptor))
+        return Err;
+      RecursionDepth--;
+      FirstIteration = false;
+    }
+  }
+
+  return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addTypeName(UnitEntryPairTy InputUnitEntryPair,
+                                            bool AddParentNames) {
+  bool HasLinkageName = false;
+  bool HasShortName = false;
+  bool HasTemplatesInShortName = false;
+  bool HasDeclFileName = false;
+
+  // Try to get name from the DIE.
+  if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
+          InputUnitEntryPair.DieEntry,
+          {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
+    // Firstly check for linkage name.
+    SyntheticName += dwarf::toStringRef(Val);
+    HasLinkageName = true;
+  } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
+                 InputUnitEntryPair.DieEntry, dwarf::DW_AT_name)) {
+    // Then check for short name.
+    StringRef Name = dwarf::toStringRef(Val);
+    SyntheticName += Name;
+
+    HasShortName = true;
+    HasTemplatesInShortName =
+        Name.endswith(">") && Name.count("<") != 0 && !Name.endswith("<=>");
+  } else {
+    // Finally check for declaration attributes.
+    addDieNameFromDeclFileAndDeclLine(InputUnitEntryPair, HasDeclFileName);
+  }
+
+  // Add additional name parts for some DIEs.
+  switch (InputUnitEntryPair.DieEntry->getTag()) {
+  case dwarf::DW_TAG_union_type:
+  case dwarf::DW_TAG_interface_type:
+  case dwarf::DW_TAG_class_type:
+  case dwarf::DW_TAG_structure_type:
+  case dwarf::DW_TAG_subroutine_type:
+  case dwarf::DW_TAG_subprogram: {
+    if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
+                                    dwarf::DW_AT_artificial))
+      SyntheticName += "^";
+
+    // No need to add signature information for linkage name,
+    // also no need to add template parameters name if short name already
+    // includes them.
+    if (!HasLinkageName)
+      if (Error Err =
+              addSignature(InputUnitEntryPair, !HasTemplatesInShortName))
+        return Err;
+  } break;
+  case dwarf::DW_TAG_coarray_type:
+  case dwarf::DW_TAG_array_type: {
+    addArrayDimension(InputUnitEntryPair);
+  } break;
+  case dwarf::DW_TAG_subrange_type: {
+    addValueName(InputUnitEntryPair, dwarf::DW_AT_count);
+  } break;
+  case dwarf::DW_TAG_template_value_parameter: {
+    if (!HasTemplatesInShortName) {
+      // TODO add support for DW_AT_location
+      addValueName(InputUnitEntryPair, dwarf::DW_AT_const_value);
+    }
+  } break;
+  default: {
+    // Nothing to do.
+  } break;
+  }
+
+  // If name for the DIE is not determined yet add referenced types to the name.
+  if (!HasLinkageName && !HasShortName && !HasDeclFileName) {
+    if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
+                                    getODRAttributes()))
+      if (Error Err = addReferencedODRDies(InputUnitEntryPair, AddParentNames,
+                                           getODRAttributes()))
+        return Err;
+  }
+
+  return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addDIETypeName(
+    UnitEntryPairTy InputUnitEntryPair,
+    std::optional<std::pair<size_t, size_t>> ChildIndex,
+    bool AssignNameToTypeDescriptor) {
+  std::optional<UnitEntryPairTy> UnitEntryPair =
+      getTypeDeduplicationCandidate(InputUnitEntryPair);
+  if (!UnitEntryPair)
+    return Error::success();
+
+  TypeEntry *TypeEntryPtr =
+      InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry);
+  // Check if DIE already has a name.
+  if (!TypeEntryPtr) {
+    size_t NameStart = SyntheticName.size();
+    if (AssignNameToTypeDescriptor) {
+      if (Error Err = addParentName(*UnitEntryPair))
+        return Err;
+    }
+    addTypePrefix(UnitEntryPair->DieEntry);
+
+    if (ChildIndex) {
+      addOrderedName(*ChildIndex);
+    } else {
+      if (Error Err = addTypeName(*UnitEntryPair, AssignNameToTypeDescriptor))
+        return Err;
+    }
+
+    if (AssignNameToTypeDescriptor) {
+      // Add built name to the DIE.
+      TypeEntryPtr = TypePoolRef.insert(SyntheticName.substr(NameStart));
+      InputUnitEntryPair.CU->setDieTypeEntry(InputUnitEntryPair.DieEntry,
+                                             TypeEntryPtr);
+    }
+  } else
+    SyntheticName += TypeEntryPtr->getKey();
+
+  return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addTypePrefix(
+    const DWARFDebugInfoEntry *DieEntry) {
+  switch (DieEntry->getTag()) {
+  case dwarf::DW_TAG_base_type: {
+    SyntheticName += "{0}";
+  } break;
+  case dwarf::DW_TAG_namespace: {
+    SyntheticName += "{1}";
+  } break;
+  case dwarf::DW_TAG_formal_parameter: {
+    SyntheticName += "{2}";
+  } break;
+  // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
+  case dwarf::DW_TAG_unspecified_parameters: {
+    SyntheticName += "{2}";
+  } break;
+  case dwarf::DW_TAG_template_type_parameter: {
+    SyntheticName += "{3}";
+  } break;
+  // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
+  case dwarf::DW_TAG_template_value_parameter: {
+    SyntheticName += "{3}";
+  } break;
+  case dwarf::DW_TAG_GNU_formal_parameter_pack: {
+    SyntheticName += "{4}";
+  } break;
+  case dwarf::DW_TAG_GNU_template_parameter_pack: {
+    SyntheticName += "{5}";
+  } break;
+  case dwarf::DW_TAG_inheritance: {
+    SyntheticName += "{6}";
+  } break;
+  case dwarf::DW_TAG_array_type: {
+    SyntheticName += "{7}";
+  } break;
+  case dwarf::DW_TAG_class_type: {
+    SyntheticName += "{8}";
+  } break;
+  case dwarf::DW_TAG_enumeration_type: {
+    SyntheticName += "{9}";
+  } break;
+  case dwarf::DW_TAG_imported_declaration: {
+    SyntheticName += "{A}";
+  } break;
+  case dwarf::DW_TAG_member: {
+    SyntheticName += "{B}";
+  } break;
+  case dwarf::DW_TAG_pointer_type: {
+    SyntheticName += "{C}";
+  } break;
+  case dwarf::DW_TAG_reference_type: {
+    SyntheticName += "{D}";
+  } break;
+  case dwarf::DW_TAG_string_type: {
+    SyntheticName += "{E}";
+  } break;
+  case dwarf::DW_TAG_structure_type: {
+    SyntheticName += "{F}";
+  } break;
+  case dwarf::DW_TAG_subroutine_type: {
+    SyntheticName += "{G}";
+  } break;
+  case dwarf::DW_TAG_typedef: {
+    SyntheticName += "{H}";
+  } break;
+  case dwarf::DW_TAG_union_type: {
+    SyntheticName += "{I}";
+  } break;
+  case dwarf::DW_TAG_variant: {
+    SyntheticName += "{J}";
+  } break;
+  case dwarf::DW_TAG_inlined_subroutine: {
+    SyntheticName += "{K}";
+  } break;
+  case dwarf::DW_TAG_module: {
+    SyntheticName += "{L}";
+  } break;
+  case dwarf::DW_TAG_ptr_to_member_type: {
+    SyntheticName += "{M}";
+  } break;
+  case dwarf::DW_TAG_set_type: {
+    SyntheticName += "{N}";
+  } break;
+  case dwarf::DW_TAG_subrange_type: {
+    SyntheticName += "{O}";
+  } break;
+  case dwarf::DW_TAG_with_stmt: {
+    SyntheticName += "{P}";
+  } break;
+  case dwarf::DW_TAG_access_declaration: {
+    SyntheticName += "{Q}";
+  } break;
+  case dwarf::DW_TAG_catch_block: {
+    SyntheticName += "{R}";
+  } break;
+  case dwarf::DW_TAG_const_type: {
+    SyntheticName += "{S}";
+  } break;
+  case dwarf::DW_TAG_constant: {
+    SyntheticName += "{T}";
+  } break;
+  case dwarf::DW_TAG_enumerator: {
+    SyntheticName += "{U}";
+  } break;
+  case dwarf::DW_TAG_file_type: {
+    SyntheticName += "{V}";
+  } break;
+  case dwarf::DW_TAG_friend: {
+    SyntheticName += "{W}";
+  } break;
+  case dwarf::DW_TAG_namelist: {
+    SyntheticName += "{X}";
+  } break;
+  case dwarf::DW_TAG_namelist_item: {
+    SyntheticName += "{Y}";
+  } break;
+  case dwarf::DW_TAG_packed_type: {
+    SyntheticName += "{Z}";
+  } break;
+  case dwarf::DW_TAG_subprogram: {
+    SyntheticName += "{a}";
+  } break;
+  case dwarf::DW_TAG_thrown_type: {
+    SyntheticName += "{b}";
+  } break;
+  case dwarf::DW_TAG_variant_part: {
+    SyntheticName += "{c}";
+  } break;
+  case dwarf::DW_TAG_variable: {
+    SyntheticName += "{d}";
+  } break;
+  case dwarf::DW_TAG_volatile_type: {
+    SyntheticName += "{e}";
+  } break;
+  case dwarf::DW_TAG_dwarf_procedure: {
+    SyntheticName += "{f}";
+  } break;
+  case dwarf::DW_TAG_restrict_type: {
+    SyntheticName += "{g}";
+  } break;
+  case dwarf::DW_TAG_interface_type: {
+    SyntheticName += "{h}";
+  } break;
+  case dwarf::DW_TAG_imported_module: {
+    SyntheticName += "{i}";
+  } break;
+  case dwarf::DW_TAG_unspecified_type: {
+    SyntheticName += "{j}";
+  } break;
+  case dwarf::DW_TAG_imported_unit: {
+    SyntheticName += "{k}";
+  } break;
+  case dwarf::DW_TAG_condition: {
+    SyntheticName += "{l}";
+  } break;
+  case dwarf::DW_TAG_shared_type: {
+    SyntheticName += "{m}";
+  } break;
+  case dwarf::DW_TAG_rvalue_reference_type: {
+    SyntheticName += "{n}";
+  } break;
+  case dwarf::DW_TAG_template_alias: {
+    SyntheticName += "{o}";
+  } break;
+  case dwarf::DW_TAG_coarray_type: {
+    SyntheticName += "{p}";
+  } break;
+  case dwarf::DW_TAG_generic_subrange: {
+    SyntheticName += "{q}";
+  } break;
+  case dwarf::DW_TAG_dynamic_type: {
+    SyntheticName += "{r}";
+  } break;
+  case dwarf::DW_TAG_atomic_type: {
+    SyntheticName += "{s}";
+  } break;
+  case dwarf::DW_TAG_call_site: {
+    SyntheticName += "{t}";
+  } break;
+  case dwarf::DW_TAG_call_site_parameter: {
+    SyntheticName += "{u}";
+  } break;
+  case dwarf::DW_TAG_immutable_type: {
+    SyntheticName += "{v}";
+  } break;
+  case dwarf::DW_TAG_entry_point: {
+    SyntheticName += "{w}";
+  } break;
+  case dwarf::DW_TAG_label: {
+    SyntheticName += "{x}";
+  } break;
+  case dwarf::DW_TAG_lexical_block: {
+    SyntheticName += "{y}";
+  } break;
+  case dwarf::DW_TAG_common_block: {
+    SyntheticName += "{z}";
+  } break;
+  case dwarf::DW_TAG_common_inclusion: {
+    SyntheticName += "{|}";
+  } break;
+  case dwarf::DW_TAG_try_block: {
+    SyntheticName += "{~}";
+  } break;
+
+  case dwarf::DW_TAG_null: {
+    llvm_unreachable("No type prefix for DW_TAG_null");
+  } break;
+  case dwarf::DW_TAG_compile_unit: {
+    llvm_unreachable("No type prefix for DW_TAG_compile_unit");
+  } break;
+  case dwarf::DW_TAG_partial_unit: {
+    llvm_unreachable("No type prefix for DW_TAG_partial_unit");
+  } break;
+  case dwarf::DW_TAG_type_unit: {
+    llvm_unreachable("No type prefix for DW_TAG_type_unit");
+  } break;
+  case dwarf::DW_TAG_skeleton_unit: {
+    llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
+  } break;
+
+  default: {
+    SyntheticName += "{~~";
+    SyntheticName += utohexstr(DieEntry->getTag());
+    SyntheticName += "}";
+  } break;
+  }
+}
+
+OrderedChildrenIndexAssigner::OrderedChildrenIndexAssigner(
+    CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
+  switch (DieEntry->getTag()) {
+  case dwarf::DW_TAG_array_type:
+  case dwarf::DW_TAG_coarray_type:
+  case dwarf::DW_TAG_class_type:
+  case dwarf::DW_TAG_common_block:
+  case dwarf::DW_TAG_lexical_block:
+  case dwarf::DW_TAG_structure_type:
+  case dwarf::DW_TAG_subprogram:
+  case dwarf::DW_TAG_subroutine_type:
+  case dwarf::DW_TAG_union_type:
+  case dwarf::DW_TAG_GNU_template_template_param:
+  case dwarf::DW_TAG_GNU_formal_parameter_pack: {
+    NeedCountChildren = true;
+  } break;
+  case dwarf::DW_TAG_enumeration_type: {
+    // TODO : do we need to add condition
+    NeedCountChildren = true;
+  } break;
+  default: {
+    // Nothing to do.
+  }
+  }
+
+  // Calculate maximal index value
+  if (NeedCountChildren) {
+    for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(DieEntry);
+         CurChild && CurChild->getAbbreviationDeclarationPtr();
+         CurChild = CU.getSiblingEntry(CurChild)) {
+      std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, CurChild);
+      if (!ArrayIndex)
+        continue;
+
+      assert((*ArrayIndex < ChildIndexesWidth.size()) &&
+             "Wrong index for ChildIndexesWidth");
+      ChildIndexesWidth[*ArrayIndex]++;
+    }
+
+    // Calculate index field width(number of digits in hexadecimal
+    // representation).
+    for (size_t &Width : ChildIndexesWidth) {
+      size_t digitsCounter = 1;
+      size_t NumToCompare = 15;
+
+      while (NumToCompare < Width) {
+        NumToCompare <<= 4;
+        digitsCounter++;
+      }
+
+      Width = digitsCounter;
+    }
+  }
+}
+
+std::optional<size_t> OrderedChildrenIndexAssigner::tagToArrayIndex(
+    CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
+  if (!NeedCountChildren)
+    return std::nullopt;
+
+  switch (DieEntry->getTag()) {
+  case dwarf::DW_TAG_unspecified_parameters:
+  case dwarf::DW_TAG_formal_parameter:
+    return 0;
+  case dwarf::DW_TAG_template_value_parameter:
+  case dwarf::DW_TAG_template_type_parameter:
+    return 1;
+  case dwarf::DW_TAG_enumeration_type:
+    if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
+      if (*ParentIdx && CU.getDebugInfoEntry(*ParentIdx)->getTag() ==
+                            dwarf::DW_TAG_array_type)
+        return 2;
+    }
+    return std::nullopt;
+  case dwarf::DW_TAG_subrange_type:
+    return 3;
+  case dwarf::DW_TAG_generic_subrange:
+    return 4;
+  case dwarf::DW_TAG_enumerator:
+    return 5;
+  case dwarf::DW_TAG_namelist_item:
+    return 6;
+  case dwarf::DW_TAG_member:
+    return 7;
+  default:
+    return std::nullopt;
+  };
+}
+
+std::optional<std::pair<size_t, size_t>>
+OrderedChildrenIndexAssigner::getChildIndex(
+    CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
+  std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, ChildDieEntry);
+  if (!ArrayIndex)
+    return std::nullopt;
+
+  assert((*ArrayIndex < OrderedChildIdxs.size()) &&
+         "Wrong index for ChildIndexesWidth");
+  assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
+         "Index width exceeds 16 digits.");
+
+  std::pair<size_t, size_t> Result = std::make_pair(
+      OrderedChildIdxs[*ArrayIndex], ChildIndexesWidth[*ArrayIndex]);
+  OrderedChildIdxs[*ArrayIndex]++;
+  return Result;
+}
+
+} // end of namespace dwarflinker_parallel
+} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h b/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h
new file mode 100644
index 000000000000000..c9dce4e94fb0dc3
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h
@@ -0,0 +1,155 @@
+//===- SyntheticTypeNameBuilder.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===/
+
+#ifndef LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
+#define LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
+
+#include "DWARFLinkerCompileUnit.h"
+#include "DWARFLinkerGlobalData.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+class DWARFDebugInfoEntry;
+
+namespace dwarflinker_parallel {
+struct LinkContext;
+class TypeTableUnit;
+class CompileUnit;
+
+/// The helper class to build type name based on DIE properties.
+/// It builds synthetic name based on explicit attributes: DW_AT_name,
+/// DW_AT_linkage_name or based on implicit attributes(DW_AT_decl*).
+/// Names for specific DIEs(like subprograms, template classes...) include
+/// additional attributes: subprogram parameters, template parameters,
+/// array ranges. Examples of built name:
+///
+/// class A {  }                    : {8}A
+///
+/// namspace llvm { class A {  } }  : {1}llvm{8}A
+///
+/// template <int> structure B { }  : {F}B<{0}int>
+///
+/// void foo ( int p1, float p3 )   : {a}void foo({0}int, {0}int)
+///
+/// int *ptr;                       : {c}ptr {0}int
+///
+/// int var;                        : {d}var
+///
+/// These names is used to refer DIEs describing types.
+class SyntheticTypeNameBuilder {
+public:
+  SyntheticTypeNameBuilder(TypePool &TypePoolRef) : TypePoolRef(TypePoolRef) {}
+
+  /// Create synthetic name for the specified DIE \p InputUnitEntryPair
+  /// and assign created name to the DIE type info. \p ChildIndex is used
+  /// to create name for ordered DIEs(function arguments f.e.).
+  Error assignName(UnitEntryPairTy InputUnitEntryPair,
+                   std::optional<std::pair<size_t, size_t>> ChildIndex);
+
+protected:
+  /// Add array type dimension.
+  void addArrayDimension(UnitEntryPairTy InputUnitEntryPair);
+
+  /// Add signature( entry type plus type of parameters plus type of template
+  /// parameters(if \p addTemplateParameters is true).
+  Error addSignature(UnitEntryPairTy InputUnitEntryPair,
+                     bool addTemplateParameters);
+
+  /// Add specified \p FunctionParameters to the built name.
+  Error addParamNames(
+      CompileUnit &CU,
+      SmallVector<const DWARFDebugInfoEntry *, 20> &FunctionParameters);
+
+  /// Add specified \p TemplateParameters to the built name.
+  Error addTemplateParamNames(
+      CompileUnit &CU,
+      SmallVector<const DWARFDebugInfoEntry *, 10> &TemplateParameters);
+
+  /// Add ordered name to the built name.
+  void addOrderedName(CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry);
+
+  /// Analyze \p InputUnitEntryPair's ODR attributes and put names
+  /// of the referenced type dies to the built name.
+  Error addReferencedODRDies(UnitEntryPairTy InputUnitEntryPair,
+                             bool AssignNameToTypeDescriptor,
+                             ArrayRef<dwarf::Attribute> ODRAttrs);
+
+  /// Add names of parent dies to the built name.
+  Error addParentName(UnitEntryPairTy &InputUnitEntryPair);
+
+  /// \returns synthetic name of the specified \p DieEntry.
+  /// The name is constructed from the dwarf::DW_AT_decl_file
+  /// and dwarf::DW_AT_decl_line attributes.
+  void addDieNameFromDeclFileAndDeclLine(UnitEntryPairTy &InputUnitEntryPair,
+                                         bool &HasDeclFileName);
+
+  /// Add type prefix to the built name.
+  void addTypePrefix(const DWARFDebugInfoEntry *DieEntry);
+
+  /// Add type name to the built name.
+  Error addTypeName(UnitEntryPairTy InputUnitEntryPair, bool AddParentNames);
+
+  /// Analyze \p InputUnitEntryPair for the type name and possibly assign
+  /// built type name to the DIE's type info.
+  /// NOTE: while analyzing types we may create different kind of names
+  /// for the same type depending on whether the type is part of another type.
+  /// f.e. DW_TAG_formal_parameter would receive "{02}01" name when
+  /// examined alone. Or "{0}int" name when it is a part of a function name:
+  /// {a}void foo({0}int). The \p AssignNameToTypeDescriptor tells whether
+  /// the type name is part of another type name and then should not be assigned
+  /// to DIE type descriptor.
+  Error addDIETypeName(UnitEntryPairTy InputUnitEntryPair,
+                       std::optional<std::pair<size_t, size_t>> ChildIndex,
+                       bool AssignNameToTypeDescriptor);
+
+  /// Add ordered name to the built name.
+  void addOrderedName(std::pair<size_t, size_t> ChildIdx);
+
+  /// Add value name to the built name.
+  void addValueName(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr);
+
+  /// Buffer keeping bult name.
+  SmallString<1000> SyntheticName;
+
+  /// Recursion counter
+  size_t RecursionDepth = 0;
+
+  /// Type pool
+  TypePool &TypePoolRef;
+};
+
+/// This class helps to assign indexes for DIE children.
+/// Indexes are used to create type name for children which
+/// should be presented in the original order(function parameters,
+/// array dimensions, enumeration members, class/structure members).
+class OrderedChildrenIndexAssigner {
+public:
+  OrderedChildrenIndexAssigner(CompileUnit &CU,
+                               const DWARFDebugInfoEntry *DieEntry);
+
+  /// Returns index of the specified child and width of hexadecimal
+  /// representation.
+  std::optional<std::pair<size_t, size_t>>
+  getChildIndex(CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry);
+
+protected:
+  using OrderedChildrenIndexesArrayTy = std::array<size_t, 8>;
+
+  std::optional<size_t> tagToArrayIndex(CompileUnit &CU,
+                                        const DWARFDebugInfoEntry *DieEntry);
+
+  bool NeedCountChildren = false;
+  OrderedChildrenIndexesArrayTy OrderedChildIdxs = {0};
+  OrderedChildrenIndexesArrayTy ChildIndexesWidth = {0};
+};
+
+} // end namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
diff --git a/llvm/lib/DWARFLinkerParallel/TypePool.h b/llvm/lib/DWARFLinkerParallel/TypePool.h
new file mode 100644
index 000000000000000..bbb3261027ce894
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/TypePool.h
@@ -0,0 +1,177 @@
+//===- TypePool.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
+#define LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
+
+#include "ArrayList.h"
+#include "llvm/ADT/ConcurrentHashtable.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/Support/Allocator.h"
+#include <atomic>
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+class TypePool;
+class CompileUnit;
+class TypeEntryBody;
+
+using TypeEntry = StringMapEntry<std::atomic<TypeEntryBody *>>;
+
+/// Keeps cloned data for the type DIE.
+class TypeEntryBody {
+public:
+  /// Returns copy of type DIE which should be emitted into resulting file.
+  DIE &getFinalDie() const {
+    if (Die)
+      return *Die;
+
+    assert(DeclarationDie);
+    return *DeclarationDie;
+  }
+
+  /// Returns true if type die entry has only declaration die.
+  bool hasOnlyDeclaration() const { return Die == nullptr; }
+
+  /// Creates type DIE for the specified name.
+  static TypeEntryBody *create(parallel::PerThreadBumpPtrAllocator &Allocator) {
+    TypeEntryBody *Result = Allocator.Allocate<TypeEntryBody>();
+    new (Result) TypeEntryBody(Allocator);
+    return Result;
+  }
+
+  /// TypeEntryBody keeps partially cloned DIEs corresponding to this type.
+  /// The two kinds of DIE can be kept: declaration and definition.
+  /// If definition DIE was met while parsing input DWARF then this DIE would
+  /// be used as a final DIE for this type. If definition DIE is not met then
+  /// declaration DIE would be used as a final DIE.
+
+  // Keeps definition die.
+  std::atomic<DIE *> Die = {nullptr};
+
+  // Keeps declaration die.
+  std::atomic<DIE *> DeclarationDie = {nullptr};
+
+  // True if parent type die is declaration.
+  std::atomic<bool> ParentIsDeclaration = {true};
+
+  /// Children for current type.
+  ArrayList<TypeEntry *, 5> Children;
+
+protected:
+  TypeEntryBody() = delete;
+  TypeEntryBody(const TypeEntryBody &RHS) = delete;
+  TypeEntryBody(TypeEntryBody &&RHS) = delete;
+  TypeEntryBody &operator=(const TypeEntryBody &RHS) = delete;
+  TypeEntryBody &operator=(const TypeEntryBody &&RHS) = delete;
+
+  TypeEntryBody(parallel::PerThreadBumpPtrAllocator &Allocator)
+      : Children(&Allocator) {}
+};
+
+class TypeEntryInfo {
+public:
+  /// \returns Hash value for the specified \p Key.
+  static inline uint64_t getHashValue(const StringRef &Key) {
+    return xxh3_64bits(Key);
+  }
+
+  /// \returns true if both \p LHS and \p RHS are equal.
+  static inline bool isEqual(const StringRef &LHS, const StringRef &RHS) {
+    return LHS == RHS;
+  }
+
+  /// \returns key for the specified \p KeyData.
+  static inline StringRef getKey(const TypeEntry &KeyData) {
+    return KeyData.getKey();
+  }
+
+  /// \returns newly created object of KeyDataTy type.
+  static inline TypeEntry *
+  create(const StringRef &Key, parallel::PerThreadBumpPtrAllocator &Allocator) {
+    return TypeEntry::create(Key, Allocator);
+  }
+};
+
+/// TypePool keeps type descriptors which contain partially cloned DIE
+/// correspinding to each type. Types are identified by names.
+class TypePool : ConcurrentHashTableByPtr<StringRef, TypeEntry,
+                                          parallel::PerThreadBumpPtrAllocator,
+                                          TypeEntryInfo> {
+public:
+  TypePool()
+      : ConcurrentHashTableByPtr<StringRef, TypeEntry,
+                                 parallel::PerThreadBumpPtrAllocator,
+                                 TypeEntryInfo>(Allocator) {
+    Root = TypeEntry::create("", Allocator);
+    Root->getValue().store(TypeEntryBody::create(Allocator));
+  }
+
+  TypeEntry *insert(StringRef Name) {
+    return ConcurrentHashTableByPtr<StringRef, TypeEntry,
+                                    parallel::PerThreadBumpPtrAllocator,
+                                    TypeEntryInfo>::insert(Name)
+        .first;
+  }
+
+  /// Create or return existing type entry body for the specified \p Entry.
+  /// Link that entry as child for the specified \p ParentEntry.
+  /// \returns The existing or created type entry body.
+  TypeEntryBody *getOrCreateTypeEntryBody(TypeEntry *Entry,
+                                          TypeEntry *ParentEntry) {
+    TypeEntryBody *DIE = Entry->getValue().load();
+    if (DIE)
+      return DIE;
+
+    TypeEntryBody *NewDIE = TypeEntryBody::create(Allocator);
+    if (Entry->getValue().compare_exchange_weak(DIE, NewDIE)) {
+      ParentEntry->getValue().load()->Children.add(Entry);
+      return NewDIE;
+    }
+
+    return DIE;
+  }
+
+  /// Sort children for each kept type entry.
+  void sortTypes() {
+    std::function<void(TypeEntry * Entry)> SortChildrenRec =
+        [&](TypeEntry *Entry) {
+          Entry->getValue().load()->Children.sort(TypesComparator);
+          Entry->getValue().load()->Children.forEach(SortChildrenRec);
+        };
+
+    SortChildrenRec(getRoot());
+  }
+
+  /// Return root for all type entries.
+  TypeEntry *getRoot() const { return Root; }
+
+  /// Return thread local allocator used by pool.
+  BumpPtrAllocator &getThreadLocalAllocator() {
+    return Allocator.getThreadLocalAllocator();
+  }
+
+protected:
+  std::function<bool(const TypeEntry *LHS, const TypeEntry *RHS)>
+      TypesComparator = [](const TypeEntry *LHS, const TypeEntry *RHS) -> bool {
+    return LHS->getKey() < RHS->getKey();
+  };
+
+  // Root of all type entries.
+  TypeEntry *Root = nullptr;
+
+private:
+  parallel::PerThreadBumpPtrAllocator Allocator;
+};
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
diff --git a/llvm/lib/DWARFLinkerParallel/Utils.h b/llvm/lib/DWARFLinkerParallel/Utils.h
new file mode 100644
index 000000000000000..91f9dca46a82b1c
--- /dev/null
+++ b/llvm/lib/DWARFLinkerParallel/Utils.h
@@ -0,0 +1,40 @@
+//===- Utils.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
+#define LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+/// This function calls \p Iteration() until it returns false.
+/// If number of iterations exceeds \p MaxCounter then an Error is returned.
+/// This function should be used for loops which assumed to have number of
+/// iterations significantly smaller than \p MaxCounter to avoid infinite
+/// looping in error cases.
+inline Error finiteLoop(function_ref<Expected<bool>()> Iteration,
+                        size_t MaxCounter = 100000) {
+  size_t iterationsCounter = 0;
+  while (iterationsCounter++ < MaxCounter) {
+    Expected<bool> IterationResultOrError = Iteration();
+    if (!IterationResultOrError)
+      return IterationResultOrError.takeError();
+
+    if (!IterationResultOrError.get())
+      return Error::success();
+  }
+
+  return createStringError(std::errc::invalid_argument, "Infinite recursion");
+}
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
diff --git a/llvm/test/tools/dsymutil/ARM/DWARFLinkerParallel/accel-imported-declarations.test b/llvm/test/tools/dsymutil/ARM/DWARFLinkerParallel/accel-imported-declarations.test
new file mode 100644
index 000000000000000..3f75991cdc471e1
--- /dev/null
+++ b/llvm/test/tools/dsymutil/ARM/DWARFLinkerParallel/accel-imported-declarations.test
@@ -0,0 +1,80 @@
+RUN: dsymutil --linker llvm -accelerator=Dwarf \
+RUN:   -oso-prepend-path=%p/../../Inputs \
+RUN:   %p/../../Inputs/accel-imported-declaration.macho-arm64 -o %t.dwarf.dSYM
+RUN: dsymutil --linker llvm -accelerator=Apple \
+RUN:   -oso-prepend-path=%p/../../Inputs \
+RUN:   %p/../../Inputs/accel-imported-declaration.macho-arm64 -o %t.apple.dSYM
+
+RUN: llvm-dwarfdump -v %t.dwarf.dSYM | FileCheck %s -check-prefixes=DWARF,COMMON
+RUN: llvm-dwarfdump -v %t.apple.dSYM | FileCheck %s -check-prefixes=APPLE,COMMON
+
+COMMON: .debug_info contents
+COMMON: DW_TAG_compile_unit
+COMMON: DW_AT_name{{.*}}"__artificial_type_unit"
+COMMON: DW_TAG_base_type
+COMMON: DW_AT_name{{.*}}"int"
+COMMON: DW_TAG_namespace
+COMMON: DW_AT_name{{.*}}"A"
+COMMON: DW_TAG_namespace
+COMMON: DW_AT_name{{.*}}"B"
+COMMON: 0x[[NAMESPACE_C_1:[0-9a-f]*]]: DW_TAG_namespace
+COMMON: DW_AT_name{{.*}}"C"
+COMMON-NOT: DW_TAG_variable
+COMMON: 0x[[NAMESPACE_C_2:[0-9a-f]*]]: DW_TAG_imported_declaration
+COMMON: DW_AT_import{{.*}}[[NAMESPACE_C_1]]
+COMMON: DW_AT_name{{.*}}"C"
+COMMON: DW_TAG_imported_module
+COMMON: DW_AT_import{{.*}}[[NAMESPACE_C_1]]
+
+
+COMMON: DW_TAG_compile_unit
+COMMON: {{.*}}DW_TAG_namespace
+COMMON:   DW_AT_name{{.*}}"A"
+COMMON: {{.*}}DW_TAG_namespace
+COMMON:   DW_AT_name{{.*}}"B"
+COMMON: 0x[[NAMESPACE_C_3:[0-9a-f]*]]: DW_TAG_namespace
+COMMON:   DW_AT_name{{.*}}"C"
+COMMON: 0x[[VAR_A:[0-9a-f]*]]: DW_TAG_variable
+COMMON: DW_TAG_imported_declaration
+COMMON:   DW_AT_import{{.*}}[[VAR_A]]
+
+DWARF:      .debug_names contents:
+DWARF:      Bucket 0 [
+DWARF-NEXT:   Name {{.*}} {
+DWARF-NEXT:     Hash: {{.*}}
+DWARF-NEXT:     String: {{.*}} "C"
+DWARF-NEXT:     Entry {{.*}} {
+DWARF-NEXT:       Abbrev: {{.*}}
+DWARF-NEXT:       Tag: DW_TAG_namespace
+DWARF:       DW_IDX_die_offset: 0x0000002f
+DWARF-NEXT:     }
+DWARF-NEXT:     Entry {{.*}} {
+DWARF-NEXT:       Abbrev: {{.*}}
+DWARF:       Tag: DW_TAG_imported_declaration
+DWARF:       DW_IDX_die_offset: 0x00000035
+DWARF-NEXT:     }
+DWARF-NEXT:     Entry {{.*}} {
+DWARF-NEXT:       Abbrev: {{.*}}
+DWARF-NEXT:       Tag: DW_TAG_namespace
+DWARF:       DW_IDX_die_offset: 0x0000003c
+DWARF-NEXT:     }
+
+DWARF-NEXT:   }
+
+APPLE:      .apple_namespaces contents:
+APPLE:      Bucket 1 [
+APPLE-NEXT:   Hash {{.*}} [
+APPLE-NEXT:     Name@{{.*}} {
+APPLE-NEXT:       String: {{.*}} "C"
+APPLE-NEXT:       Data 0 [
+APPLE-NEXT:         Atom[0]: 0x[[NAMESPACE_C_1]]
+APPLE-NEXT:       ]
+APPLE-NEXT:       Data 1 [
+APPLE-NEXT:         Atom[0]: 0x[[NAMESPACE_C_2]]
+APPLE-NEXT:       ]
+APPLE-NEXT:       Data 2 [
+APPLE-NEXT:         Atom[0]: 0x[[NAMESPACE_C_3]]
+APPLE-NEXT:       ]
+APPLE:          }
+APPLE-NEXT:   ]
+APPLE-NEXT: ]
diff --git a/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test b/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
index f1680ced6e5b4f0..057e89d060b1d27 100644
--- a/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
+++ b/llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test
@@ -4,14 +4,6 @@ RUN: dsymutil -accelerator=Apple -oso-prepend-path=%p/../Inputs %p/../Inputs/acc
 RUN: llvm-dwarfdump -v %t.dwarf.dSYM | FileCheck %s -check-prefixes=DWARF,COMMON
 RUN: llvm-dwarfdump -v %t.apple.dSYM | FileCheck %s -check-prefixes=APPLE,COMMON
 
-RUN: dsymutil --linker llvm -accelerator=Dwarf -oso-prepend-path=%p/../Inputs \
-RUN:   %p/../Inputs/accel-imported-declaration.macho-arm64 -o %t.dwarf.dSYM
-RUN: dsymutil --linker llvm -accelerator=Apple -oso-prepend-path=%p/../Inputs \
-RUN:   %p/../Inputs/accel-imported-declaration.macho-arm64 -o %t.apple.dSYM
-
-RUN: llvm-dwarfdump -v %t.dwarf.dSYM | FileCheck %s -check-prefixes=DWARF,COMMON
-RUN: llvm-dwarfdump -v %t.apple.dSYM | FileCheck %s -check-prefixes=APPLE,COMMON
-
 COMMON: .debug_info contents
 COMMON: {{.*}}DW_TAG_namespace
 COMMON:   DW_AT_name{{.*}}"A"
@@ -19,7 +11,7 @@ COMMON: {{.*}}DW_TAG_namespace
 COMMON:   DW_AT_name{{.*}}"B"
 COMMON: [[NAMESPACE:0x[0-9a-f]*]]:{{.*}}DW_TAG_namespace
 COMMON:   DW_AT_name{{.*}}"C"
-COMMON: [[IMPORTED:0x[0-9a-f]*]]:{{.*}}DW_TAG_imported_declaration
+COMMON: 0x0000005c:{{.*}}DW_TAG_imported_declaration
 COMMON:   DW_AT_name{{.*}}"C"
 
 DWARF:      .debug_names contents:
@@ -30,12 +22,12 @@ DWARF-NEXT:     String: {{.*}} "C"
 DWARF-NEXT:     Entry {{.*}} {
 DWARF-NEXT:       Abbrev: {{.*}}
 DWARF-NEXT:       Tag: DW_TAG_namespace
-DWARF-NEXT:       DW_IDX_die_offset: [[NAMESPACE]]
+DWARF:       DW_IDX_die_offset: [[NAMESPACE]]
 DWARF-NEXT:     }
 DWARF-NEXT:     Entry {{.*}} {
 DWARF-NEXT:       Abbrev: {{.*}}
-DWARF-NEXT:       Tag: DW_TAG_imported_declaration
-DWARF-NEXT:       DW_IDX_die_offset: [[IMPORTED]]
+DWARF:       Tag: DW_TAG_imported_declaration
+DWARF:       DW_IDX_die_offset: 0x0000005c
 DWARF-NEXT:     }
 DWARF-NEXT:   }
 
@@ -48,8 +40,8 @@ APPLE-NEXT:       Data 0 [
 APPLE-NEXT:         Atom[0]: [[NAMESPACE]]
 APPLE-NEXT:       ]
 APPLE-NEXT:       Data 1 [
-APPLE-NEXT:         Atom[0]: [[IMPORTED]]
+APPLE-NEXT:         Atom[0]: {{0x0000005c|0x0000006f}}
 APPLE-NEXT:       ]
-APPLE-NEXT:     }
+APPLE:          }
 APPLE-NEXT:   ]
 APPLE-NEXT: ]
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-addr-base.test b/llvm/test/tools/dsymutil/ARM/dwarf5-addr-base.test
index 00dcde718e36225..ca4a951e770ba2a 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-addr-base.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-addr-base.test
@@ -50,15 +50,30 @@ RUN: dsymutil -y %p/dummy-debug-map-amr64.map -oso-prepend-path=%p/../Inputs/DWA
 RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s
 
 RUN: rm -rf %t.dir && mkdir -p %t.dir
-RUN: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+RUN: dsymutil --linker llvm --no-odr -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
 RUN:   -o %t.dir/dwarf5-addr-base.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s
 
+RUN: rm -rf %t.dir && mkdir -p %t.dir
+RUN: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
+RUN:   -o %t.dir/dwarf5-addr-base.dSYM
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefixes=CHECK,CHECK-LLVM
+
+
 RUN: rm -rf %t.dir && mkdir -p %t.dir
 RUN: dsymutil --update -y %p/dummy-debug-map-amr64.map -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base -o %t.dir/dwarf5-addr-base.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s --check-prefix=UPD
 
+RUN: rm -rf %t.dir && mkdir -p %t.dir
+RUN: dsymutil --linker llvm --no-odr --update -y %p/dummy-debug-map-amr64.map \
+RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
+RUN:   -o %t.dir/dwarf5-addr-base.dSYM
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefix=UPD
+
 RUN: rm -rf %t.dir && mkdir -p %t.dir
 RUN: dsymutil --linker llvm --update -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
@@ -66,30 +81,36 @@ RUN:   -o %t.dir/dwarf5-addr-base.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
 RUN:   FileCheck %s --check-prefix=UPD
 
+
 CHECK: .debug_info contents:
-CHECK-NEXT: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08
 
-CHECK: 0x0000000c: DW_TAG_compile_unit [1] *
-CHECK:               DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000008)
+CHECK-LLVM: Compile Unit: length = 0x0000001f, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
+CHECK-LLVM: DW_TAG_compile_unit
+CHECK-LLVM: DW_TAG_base_type
+
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
+
+CHECK: DW_TAG_compile_unit
+CHECK:   DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000008)
 
-CHECK: 0x0000002c:   DW_TAG_subprogram [2] * (0x0000000c)
+CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x[[ADDR1:[0-9a-f]+]])
 
 
-CHECK: 0x0000004e: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 
-CHECK: 0x0000005a: DW_TAG_compile_unit [1] *
+CHECK: DW_TAG_compile_unit
 CHECK:              DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000018)
 
-CHECK: 0x0000007a:   DW_TAG_subprogram [2] * (0x0000005a)
+CHECK: DW_TAG_subprogram
 CHECK-NEXT:                 DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x[[ADDR2:[0-9a-f]+]])
 
-CHECK: 0x0000009c: Compile Unit: length = 0x00000043, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x00{{00|b4}}, addr_size = 0x08
+CHECK: Compile Unit: length = 0x00000043, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 
-CHECK: 0x000000a8: DW_TAG_compile_unit {{.*}} *
+CHECK: DW_TAG_compile_unit
 CHECK: DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000028)
 
-CHECK: 0x000000c1:   DW_TAG_subprogram [2] * (0x000000a8)
+CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                 DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x[[ADDR3:[0-9a-f]+]])
 
 CHECK: .debug_addr contents:
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
index 324a156484119f8..0199bf28681bc4f 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
@@ -34,17 +34,31 @@ RUN: dsymutil -y %p/dummy-debug-map-amr64.map -oso-prepend-path=%p/../Inputs/DWA
 RUN: llvm-dwarfdump %t.dir/dwarf5-dwarf4-combination-macho.dSYM -a --verbose | FileCheck %s
 
 RUN: rm -rf %t.dir && mkdir -p %t.dir
-RUN: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+RUN: dsymutil --no-odr --linker llvm -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-DWARF4-combination \
 RUN:   -o %t.dir/dwarf5-dwarf4-combination-macho.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-dwarf4-combination-macho.dSYM \
 RUN:   -a --verbose | FileCheck %s
 
+### Uncomment following when llvm-dwarfdump will dump address ranges
+### correctly for severall compile units case.
+COM: rm -rf %t.dir && mkdir -p %t.dir
+COM: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+COM:   -oso-prepend-path=%p/../Inputs/DWARF5-DWARF4-combination \
+COM:   -o %t.dir/dwarf5-dwarf4-combination-macho.dSYM
+COM: llvm-dwarfdump %t.dir/dwarf5-dwarf4-combination-macho.dSYM \
+COM:   -a --verbose | FileCheck %s --check-prefixes=CHECK,CHECK-LLVM
+
+
 CHECK:.debug_abbrev contents:
 CHECK-NEXT: Abbrev table for offset: 0x00000000
 
 CHECK: .debug_info contents:
-CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 
+CHECK-LLVM: Compile Unit: length = 0x0000001f,  format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
+CHECK-LLVM: DW_TAG_compile_unit
+CHECK-LLVM: DW_TAG_base_type
+
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 CHECK: DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "a.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -54,17 +68,17 @@ CHECK: DW_AT_comp_dir [DW_FORM_strx]     (indexed (00000004) string = "/Users/sh
 CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[RANGELIST_OFFSET:[0-9a-f]+]]
 CHECK-NEXT:                  [0x[[RANGELIST_OFFSET_START:[0-9a-f]+]], 0x[[RANGELIST_OFFSET_END:[0-9a-f]+]]))
 CHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000008)
-CHECK: 0x0000002c:   DW_TAG_subprogram [2] * (0x0000000c)
+CHECK:   DW_TAG_subprogram
 CHECK-NEXT:  DW_AT_low_pc [DW_FORM_addrx]     (indexed (00000000) address = 0x[[#%.16x,LOCLIST_LOWPC:]])
 CHECK: DW_AT_linkage_name [DW_FORM_strx]       (indexed (00000005) string = "_Z4foo2i")
 CHECK: DW_AT_name [DW_FORM_strx]       (indexed (00000006) string = "foo2")
-CHECK: 0x0000003c:     DW_TAG_formal_parameter [3]   (0x0000002c)
+CHECK:     DW_TAG_formal_parameter
 CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOCLIST_OFFSET:[0-9a-f]+]]: 
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]]
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]])
 CHECK: DW_AT_name [DW_FORM_strx]     (indexed (00000007) string = "a")
 
-CHECK: 0x0000004e: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08 
+CHECK: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = {{.*}}, addr_size = 0x08
 CHECK: DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000e0] = "b.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strp] ( .debug_str[0x00000039] = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -74,11 +88,11 @@ CHECK: DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x000000a3] = "/Users/shub
 CHECK:              DW_AT_low_pc [DW_FORM_addr]       (0x[[#%.16x,RANGE_LOWPC:]])
 CHECK-NEXT:              DW_AT_ranges [DW_FORM_sec_offset] (0x00000000
 CHECK-NEXT:                 [0x[[#%.16x,RANGE_START:]], 0x[[#%.16x,RANGE_END:]]))
-CHECK: 0x00000080:   DW_TAG_subprogram {{.*}} * (0x00000059)
+CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                DW_AT_low_pc [DW_FORM_addr]     (0x[[#%.16x,LOC_LOWPC:]])
 CHECK: DW_AT_linkage_name [DW_FORM_strp]       ( .debug_str[0x000000e6] = "_Z3bari")
 CHECK: DW_AT_name [DW_FORM_strp]       ( .debug_str[0x000000ee] = "bar")
-CHECK: 0x0000009d:     DW_TAG_formal_parameter {{.*}}   (0x00000080)
+CHECK:     DW_TAG_formal_parameter
 CHECK-NEXT:                  DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]: 
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START:]], 0x[[#%.16x,LOC_PAIR_END:]]): [[LOC_EXPR:.*]]
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START2:]], 0x[[#%.16x,LOC_PAIR_END2:]]): [[LOC_EXPR2:.*]])
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test
index 3008db9a0d63c21..13409b2a07a31f6 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-macho.test
@@ -22,21 +22,33 @@ RUN: dsymutil -y %p/dummy-debug-map-amr64.map -oso-prepend-path=%p/../Inputs/DWA
 RUN: llvm-dwarfdump %t.dir/dwarf5-macho.dSYM -a --verbose | FileCheck %s
 
 RUN: rm -rf %t.dir && mkdir -p %t.dir
-RUN: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+RUN: dsymutil --linker llvm --no-odr -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5 -o %t.dir/dwarf5-macho.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-macho.dSYM -a --verbose | FileCheck %s
 
+### Uncomment following when llvm-dwarfdump will print resolved address ranges
+### for the case mutiplue compile units.
+COM: rm -rf %t.dir && mkdir -p %t.dir
+COM: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
+COM:   -oso-prepend-path=%p/../Inputs/DWARF5 -o %t.dir/dwarf5-macho.dSYM
+COM: llvm-dwarfdump %t.dir/dwarf5-macho.dSYM -a --verbose | FileCheck %s \
+COM: --check-prefixes=CHECK,CHECK-LLVM
+
+
 CHECK:.debug_abbrev contents:
 CHECK-NEXT: Abbrev table for offset: 0x00000000
 
 CHECK: .debug_info contents:
-CHECK-NEXT: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 
+CHECK-LLVM: Compile Unit: length = 0x0000001f, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
+CHECK-LLVM: DW_TAG_compile_unit
+CHECK-LLVM: DW_TAG_base_type
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x[[RANGELIST_OFFSET:[0-9a-f]+]]
 CHECK-NEXT:                  [0x[[RANGELIST_OFFSET_START:[0-9a-f]+]], 0x[[RANGELIST_OFFSET_END:[0-9a-f]+]]))
 CHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]      (0x00000008)
-CHECK: 0x0000002c:   DW_TAG_subprogram [2] * (0x0000000c)
+CHECK:   DW_TAG_subprogram
 CHECK-NEXT:  DW_AT_low_pc [DW_FORM_addrx]     (indexed (00000000) address = 0x[[#%.16x,LOCLIST_LOWPC:]])
-CHECK: 0x0000003c:     DW_TAG_formal_parameter [3]   (0x0000002c)
+CHECK:     DW_TAG_formal_parameter
 CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]: 
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]]
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]])
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-str-offsets-base-strx.test b/llvm/test/tools/dsymutil/ARM/dwarf5-str-offsets-base-strx.test
index ac813fc6203708d..73decc497ea36ee 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-str-offsets-base-strx.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-str-offsets-base-strx.test
@@ -56,21 +56,40 @@ RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s --c
 RUN: dsymutil --update -y %p/dummy-debug-map-amr64.map -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base -o %t.dir/dwarf5-addr-base.dSYM
 RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s --check-prefixes=UPD,GLOBALUPD
 
+RUN: rm -rf %t.dir && mkdir -p %t.dir
+RUN: dsymutil --linker llvm --no-odr -y %p/dummy-debug-map-amr64.map \
+RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
+RUN:   -o %t.dir/dwarf5-addr-base.dSYM
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefixes=CHECK,LOCAL
+
 RUN: rm -rf %t.dir && mkdir -p %t.dir
 RUN: dsymutil --linker llvm -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
 RUN:   -o %t.dir/dwarf5-addr-base.dSYM
-RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s --check-prefixes=CHECK,LOCAL
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefixes=CHECK,LOCAL,CHECK-LLVM
+
+RUN: dsymutil --linker llvm --no-odr --update -y %p/dummy-debug-map-amr64.map \
+RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
+RUN:   -o %t.dir/dwarf5-addr-base.dSYM
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefixes=UPD,LOCALUPD
 
 RUN: dsymutil --linker llvm --update -y %p/dummy-debug-map-amr64.map \
 RUN:   -oso-prepend-path=%p/../Inputs/DWARF5-addr-base-str-off-base \
 RUN:   -o %t.dir/dwarf5-addr-base.dSYM
-RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | FileCheck %s --check-prefixes=UPD,LOCALUPD
+RUN: llvm-dwarfdump %t.dir/dwarf5-addr-base.dSYM -a --verbose | \
+RUN:   FileCheck %s --check-prefixes=UPD,LOCALUPD
+
 
 CHECK: .debug_info contents:
-CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x0000004e)
+CHECK-LLVM: Compile Unit: length = 0x0000001f, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
+CHECK-LLVM: DW_TAG_compile_unit
+CHECK-LLVM: DW_TAG_base_type
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 
-CHECK: 0x0000000c: DW_TAG_compile_unit [1] *
+CHECK: DW_TAG_compile_unit
 CHECK:               DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 15.0.0 (clang-1500.0.31.1)")
 CHECK:               DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "a.cpp")
 CHECK:               DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Users/shubham/apple-internal/Xcode-Rainbow/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk")
@@ -78,24 +97,24 @@ CHECK:               DW_AT_APPLE_sdk [DW_FORM_strx]    (indexed (00000003) strin
 CHECK:               DW_AT_str_offsets_base [DW_FORM_sec_offset]       (0x00000008)
 CHECK:               DW_AT_comp_dir [DW_FORM_strx]     (indexed (00000004) string = "/Users/shubham/Development/test109275485")
 
-CHECK: 0x0000002c:   DW_TAG_subprogram [2] * (0x0000000c)
+CHECK:   DW_TAG_subprogram
 CHECK:                 DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x0000000000010000)
 CHECK:                 DW_AT_linkage_name [DW_FORM_strx]       (indexed (00000005) string = "_Z4foo2i")
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (00000006) string = "foo2")
 
-CHECK: 0x0000003c:     DW_TAG_formal_parameter [3]   (0x0000002c)
+CHECK:     DW_TAG_formal_parameter
 CHECK:                   DW_AT_name [DW_FORM_strx]     (indexed (00000007) string = "a")
 
-CHECK: 0x00000048:     NULL
+CHECK:     NULL
 
-CHECK: 0x00000049:   DW_TAG_base_type [4]   (0x0000000c)
+CHECK:   DW_TAG_base_type
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (00000008) string = "int")
 
-CHECK: 0x0000004d:   NULL
+CHECK: NULL
 
-CHECK: 0x0000004e: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08 (next unit at 0x0000009c)
+CHECK: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 
-CHECK: 0x0000005a: DW_TAG_compile_unit [1] *
+CHECK: DW_TAG_compile_unit
 CHECK:               DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 15.0.0 (clang-1500.0.31.1)")
 CHECK:               DW_AT_name [DW_FORM_strx] (indexed (0000000{{9|1}}) string = "b.cpp")
 CHECK:               DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Users/shubham/apple-internal/Xcode-Rainbow/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk")
@@ -103,23 +122,23 @@ CHECK:               DW_AT_APPLE_sdk [DW_FORM_strx]    (indexed (00000003) strin
 CHECK:               DW_AT_str_offsets_base [DW_FORM_sec_offset]       (0x000000{{08|34}})
 CHECK:               DW_AT_comp_dir [DW_FORM_strx]     (indexed (00000004) string = "/Users/shubham/Development/test109275485")
 
-CHECK: 0x0000007a:   DW_TAG_subprogram [2] * (0x0000005a)
+CHECK:   DW_TAG_subprogram
 CHECK:                 DW_AT_linkage_name [DW_FORM_strx]       (indexed (0000000{{a|5}}) string = "_Z4bar2i")
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (0000000{{b|6}}) string = "bar2")
 
-CHECK: 0x0000008a:     DW_TAG_formal_parameter [3]   (0x0000007a)
+CHECK:     DW_TAG_formal_parameter
 CHECK:                   DW_AT_name [DW_FORM_strx]     (indexed (00000007) string = "a")
 
-CHECK: 0x00000096:     NULL
+CHECK:     NULL
 
-CHECK: 0x00000097:   DW_TAG_base_type [4]   (0x0000005a)
+CHECK:   DW_TAG_base_type
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (00000008) string = "int")
 
-CHECK: 0x0000009b:   NULL
+CHECK:   NULL
 
-CHECK: 0x0000009c: Compile Unit: length = 0x00000043, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x00{{00|b4}}, addr_size = 0x08 (next unit at 0x000000e3)
+CHECK: Compile Unit: length = 0x00000043, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = {{.*}}, addr_size = 0x08
 
-CHECK: 0x000000a8: DW_TAG_compile_unit {{.*}} *
+CHECK: DW_TAG_compile_unit
 CHECK:               DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 15.0.0 (clang-1500.0.31.1)")
 CHECK:               DW_AT_name [DW_FORM_strx] (indexed (0000000{{c|1}}) string = "c.cpp")
 CHECK:               DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Users/shubham/apple-internal/Xcode-Rainbow/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk")
@@ -127,19 +146,19 @@ CHECK:               DW_AT_APPLE_sdk [DW_FORM_strx]    (indexed (00000003) strin
 CHECK:               DW_AT_str_offsets_base [DW_FORM_sec_offset]       (0x000000{{08|60}})
 CHECK:               DW_AT_comp_dir [DW_FORM_strx]     (indexed (00000004) string = "/Users/shubham/Development/test109275485")
 
-CHECK: 0x000000c1:   DW_TAG_subprogram [2] * (0x000000a8)
+CHECK:   DW_TAG_subprogram
 CHECK:                 DW_AT_linkage_name [DW_FORM_strx]       (indexed (0000000{{d|5}}) string = "_Z3bazi")
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (0000000{{e|6}}) string = "baz")
 
-CHECK: 0x000000d1:     DW_TAG_formal_parameter [3]   (0x000000c1)
+CHECK:     DW_TAG_formal_parameter
 CHECK:                   DW_AT_name [DW_FORM_strx]     (indexed (0000000{{f|7}}) string = "x")
 
-CHECK: 0x000000dd:     NULL
+CHECK:     NULL
 
-CHECK: 0x000000de:   DW_TAG_base_type [4]   (0x000000a8)
+CHECK:   DW_TAG_base_type
 CHECK:                 DW_AT_name [DW_FORM_strx]       (indexed (00000008) string = "int")
 
-CHECK: 0x000000e2:   NULL
+CHECK:    NULL
 
 CHECK: .debug_str contents:
 CHECK-NEXT: 0x00000000: ""
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/dead-stripped.cpp b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/dead-stripped.cpp
new file mode 100644
index 000000000000000..a94d06f2ab64d27
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/dead-stripped.cpp
@@ -0,0 +1,67 @@
+// RUN: dsymutil --linker llvm --no-odr -f -y %p/../dummy-debug-map.map -oso-prepend-path \
+// RUN: %p/../../Inputs/dead-stripped -o - | llvm-dwarfdump - --debug-info | \
+// RUN: FileCheck %s --implicit-check-not \
+// RUN: "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}"
+//
+// RUN: dsymutil --linker llvm -f -y %p/../dummy-debug-map.map -oso-prepend-path \
+// RUN: %p/../../Inputs/dead-stripped -o - | llvm-dwarfdump - --debug-info | \
+// RUN: FileCheck %s --implicit-check-not \
+// RUN: "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}" \
+// RUN: --check-prefixes=CHECK-LLVM
+
+// The test was compiled with:
+// clang++ -O2 -g -c dead-strip.cpp -o 1.o
+
+// The goal of the test is to exercise dsymutil's behavior in presence of
+// functions/variables that have been dead-stripped by the linker but
+// that are still present in the linked debug info (in this case because
+// they have been DW_TAG_import'd in another namespace).
+
+// CHECK-LLVM: DW_TAG_compile_unit
+// CHECK-LLVM: DW_AT_name{{.*}}"__artificial_type_unit"
+// CHECK-LLVM: DW_TAG_namespace
+// CHECK-LLVM: DW_AT_name{{.*}}"N"
+// CHECK-LLVM: NULL
+//
+// CHECK-LLVM: DW_TAG_compile_unit
+// CHECK-LLVM:   DW_AT_low_pc
+// CHECK-LLVM:   DW_AT_high_pc
+// CHECK-LLVM: DW_TAG_base_type
+// CHECK-LLVM: DW_TAG_imported_module
+// CHECK-LLVM: DW_TAG_subprogram
+// CHECK-LLVM:   DW_AT_low_pc
+// CHECK-LLVM:   DW_AT_high_pc
+// CHECK-LLVM: DW_TAG_base_type
+// CHECK-LLVM: NULL
+
+// Everything in the N namespace below doesn't have a debug map entry, and
+// thus is considered dead (::foo() has a debug map entry, otherwise dsymutil
+// would just drop the CU altogether).
+
+// CHECK: DW_TAG_compile_unit
+// CHECK:   DW_AT_low_pc
+// CHECK:   DW_AT_high_pc
+// CHECK:   DW_TAG_namespace
+namespace N {
+int blah = 42;
+
+__attribute__((always_inline)) int foo() { return blah; }
+
+int bar(unsigned i) {
+	int val = foo();
+	if (i)
+		return val + bar(i-1);
+	return foo();
+}
+}
+// CHECK: DW_TAG_base_type
+// CHECK: DW_TAG_imported_module
+// CHECK: DW_TAG_subprogram
+// CHECK:   DW_AT_low_pc
+// CHECK:   DW_AT_high_pc
+// CHECK: DW_TAG_base_type
+// CHECK: NULL
+
+using namespace N;
+
+void foo() {}
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/empty-CU.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/empty-CU.test
new file mode 100644
index 000000000000000..b2d178cee0282cc
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/empty-CU.test
@@ -0,0 +1,5 @@
+RUN: llvm-mc %p/../../Inputs/empty-CU.s -filetype obj -triple x86_64-apple-darwin -o %t.o
+RUN: dsymutil --linker llvm --update -f %t.o -o - | llvm-dwarfdump -v - -debug-info | FileCheck %s
+
+CHECK: .debug_info contents:
+CHECK-NOT: DW_TAG_compile_unit
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/inlined-static-variable.cpp b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/inlined-static-variable.cpp
new file mode 100644
index 000000000000000..97d7e630e7c6722
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/inlined-static-variable.cpp
@@ -0,0 +1,74 @@
+// RUN: dsymutil --linker llvm -f -y %p/../dummy-debug-map.map -oso-prepend-path \
+// RUN:   %p/../../Inputs/inlined-static-variable -o - -keep-function-for-static | \
+// RUN:   llvm-dwarfdump - | FileCheck %s --implicit-check-not \
+// RUN: "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}" \
+// RUN: --check-prefixes=CHECK
+
+// clang -g -c inlined-static-variable.cpp -o 4.o
+
+// The functions removed and not_removed are not in the debug map and are
+// considered dead, but they are also inlined into the function foo which is
+// in the debug map. Those function-local globals are alive and thus should
+// have locations in the debug info even if their functions do not.
+
+inline __attribute__((always_inline)) int removed() {
+  static int a = 0;
+  return ++a;
+}
+
+__attribute__((always_inline)) int not_removed() {
+  static int b = 0;
+  return ++b;
+}
+
+int unused() {
+  static int c = 0;
+  return ++c;
+}
+
+int foo() {
+  return removed() + not_removed();
+}
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+// CHECK: DW_TAG_base_type
+// CHECK:   DW_AT_name{{.*}}"int"
+// CHECK: DW_TAG_subprogram
+// CHECK:   DW_AT_name{{.*}}"not_removed"
+// CHECK: DW_TAG_subprogram
+// CHECK:   DW_AT_name{{.*}}"removed"
+// CHECK: NULL
+
+// CHECK: DW_TAG_compile_unit
+// CHECK:   DW_AT_low_pc
+// CHECK:   DW_AT_high_pc
+// CHECK:   DW_TAG_subprogram
+// CHECK:   DW_AT_name{{.*}}"removed"
+// CHECK-NOT: DW_AT_low_pc
+// CHECK-NOT: DW_AT_low_pc
+// CHECK:   DW_TAG_variable
+// CHECK:   DW_AT_name{{.*}}"a"
+// CHECK:   {{.*}}DW_OP_addr
+// CHECK:   NULL
+// CHECK:   DW_TAG_base_type
+// CHECK:   DW_TAG_subprogram
+// CHECK:   DW_AT_name{{.*}}"not_removed"
+// CHECK-NOT: DW_AT_low_pc
+// CHECK-NOT: DW_AT_low_pc
+// CHECK:   DW_TAG_variable
+// CHECK:   DW_AT_name{{.*}}"b"
+// CHECK:   {{.*}}DW_OP_addr
+// CHECK:   NULL
+// CHECK:   DW_TAG_subprogram
+// CHECK:     DW_AT_low_pc
+// CHECK:     DW_AT_high_pc
+// CHECK:     DW_AT_name	("foo")
+// CHECK:     DW_TAG_inlined_subroutine
+// CHECK:       DW_AT_low_pc
+// CHECK:       DW_AT_high_pc
+// CHECK:     DW_TAG_inlined_subroutine
+// CHECK:       DW_AT_low_pc
+// CHECK:       DW_AT_high_pc
+// CHECK:     NULL
+// CHECK:   NULL
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/keep-func.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/keep-func.test
new file mode 100644
index 000000000000000..6d8757391d6c68d
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/keep-func.test
@@ -0,0 +1,36 @@
+$ cat main.cpp
+#include <stdio.h>
+
+static void Foo(void)
+{
+  typedef struct {
+    int x1;
+    int x2;
+  } FOO_VAR_TYPE;
+  static FOO_VAR_TYPE MyDummyVar __attribute__((aligned(4), used, section("TAD_VIRTUAL, TAD_DUMMY_DATA"), nocommon));
+  printf("Foo called");
+}
+
+int main()
+{
+  Foo();
+  return 1;
+}
+
+$ clang++ -O2 -g main.cpp -c -o main.o
+$ clang++ main.o -o main.out
+
+RUN: dsymutil --linker llvm -oso-prepend-path %p/../../Inputs %p/../../Inputs/private/tmp/keep_func/main.out -o %t.omit.dSYM
+RUN: dsymutil --linker llvm -oso-prepend-path %p/../../Inputs %p/../../Inputs/private/tmp/keep_func/main.out -o %t.keep.dSYM -keep-function-for-static
+RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT
+RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP
+
+KEEP:     DW_AT_name	("x1")
+KEEP:     DW_AT_name	("x2")
+KEEP:     DW_AT_name    ("FOO_VAR_TYPE")
+KEEP:     DW_AT_name    ("MyDummyVar")
+
+OMIT-NOT: DW_AT_name	("MyDummyVar")
+OMIT-NOT: DW_AT_name	("FOO_VAR_TYPE")
+OMIT-NOT: DW_AT_name	("x1")
+OMIT-NOT: DW_AT_name	("x2")
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-anon-namespace.cpp b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-anon-namespace.cpp
new file mode 100644
index 000000000000000..16aacd57517bd2e
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-anon-namespace.cpp
@@ -0,0 +1,68 @@
+/* Compile with:
+   for FILE in `seq 2`; do
+     clang -g -c  odr-anon-namespace.cpp -DFILE$FILE -o odr-anon-namespace/$FILE.o
+   done
+ */
+
+// RUN: dsymutil --linker llvm -f \
+// RUN:   -oso-prepend-path=%p/../../Inputs/odr-anon-namespace \
+// RUN:   -y %p/../dummy-debug-map.map -o - | \
+// RUN:   llvm-dwarfdump -debug-info - | FileCheck %s
+
+#ifdef FILE1
+// Currently dsymutil will unique the contents of anonymous
+// namespaces if they are from the same file/line. Force this
+// namespace to appear different eventhough it's the same (this
+// uniquing is actually a bug kept for backward compatibility, see the
+// comments in DeclContextTree::getChildDeclContext()).
+#line 42
+#endif
+namespace {
+class C {};
+}
+
+void foo() {
+  C c;
+}
+
+// Keep the ifdef guards for FILE1 and FILE2 even if all the code is
+// above to clearly show what the CHECK lines are testing.
+#ifdef FILE1
+
+// CHECK: TAG_compile_unit
+// CHECK-NOT: DW_TAG
+// CHECK: AT_name{{.*}}"odr-anon-namespace.cpp"
+
+// CHECK: DW_TAG_variable
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_name {{.*}}"c"
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_type {{.*}}0x[[C_FILE1:[0-9a-f]*]]
+
+// CHECK: DW_TAG_namespace
+// CHECK-NOT: {{DW_AT_name|NULL|DW_TAG}}
+// CHECK: 0x[[C_FILE1]]:{{.*}}DW_TAG_class_type
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_name{{.*}}"C"
+
+#elif defined(FILE2)
+
+// CHECK: TAG_compile_unit
+// CHECK-NOT: DW_TAG
+// CHECK: AT_name{{.*}}"odr-anon-namespace.cpp"
+
+// CHECK: DW_TAG_variable
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_name {{.*}}"c"
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_type {{.*}}0x[[C_FILE2:[0-9a-f]*]]
+
+// CHECK: DW_TAG_namespace
+// CHECK-NOT: {{DW_AT_name|NULL|DW_TAG}}
+// CHECK: 0x[[C_FILE2]]:{{.*}}DW_TAG_class_type
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_name{{.*}}"C"
+
+#else
+#error "You must define which file you generate"
+#endif
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration.test
new file mode 100644
index 000000000000000..3e8d8557689e36d
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration.test
@@ -0,0 +1,101 @@
+/* Compile with:
+   for FILE in `seq 3`; do
+     clang -g -c  X86/odr-fwd-declaration.cpp -DFILE$FILE -o
+       Inputs/odr-fwd-declaration/$FILE.o done
+*/
+
+// RUN: dsymutil --linker=llvm -f \
+// RUN: -oso-prepend-path=%p/../../Inputs/odr-fwd-declaration \
+// RUN: -y %p/../dummy-debug-map.map -o %t1.out
+// RUN: llvm-dwarfdump -v -debug-info %t1.out | FileCheck %s
+
+#ifdef FILE1
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source1.cpp" 2
+void foo() { Sptrptr ptr1 = 0; }
+
+// First we confirm that types are in type table.
+//
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+// CHECK: DW_TAG_base_type
+
+// CHECK: 0x[[PTR_S:[a-f0-9]*]]: DW_TAG_pointer_type
+// CHECK-NEXT: DW_AT_type{{.*}}{0x[[STRUCT_S:[a-f0-9]*]]} "S"
+
+// CHECK: 0x[[PTR_PTR_S:[a-f0-9]*]]: DW_TAG_pointer_type
+// CHECK-NEXT: DW_AT_type{{.*}}{0x[[TYPEDEF_PTR_S:[a-f0-9]*]]} "Sptr"
+
+// CHECK: 0x[[STRUCT_S]]: DW_TAG_structure_type
+// CHECK-NEXT: DW_AT_name{{.*}}"S"
+
+// CHECK: DW_TAG_member
+// CHECK-NEXT: DW_AT_name{{.*}}"field"
+
+// CHECK: 0x[[TYPEDEF_PTR_S]]: DW_TAG_typedef
+// CHECK-NEXT: DW_AT_type{{.*}}{0x[[PTR_S]]} "S *"
+// CHECK-NEXT: DW_AT_name{{.*}}"Sptr"
+
+// CHECK: 0x[[TYPEDEF_PTR_PTR_S:[a-f0-9]*]]: DW_TAG_typedef
+// CHECK-NEXT: DW_AT_type{{.*}}{0x[[PTR_PTR_S]]} "Sptr *"
+// CHECK-NEXT: DW_AT_name{{.*}}"Sptrptr"
+
+// First we confirm that first compile unit properly references type.
+//
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name{{.*}}"X86/odr-fwd-declaration.cpp"
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr1"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x00000000[[TYPEDEF_PTR_PTR_S]]
+
+#elif defined(FILE2)
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source2.cpp" 2
+struct S {
+  int field;
+};
+void bar() { Sptrptr ptr2 = 0; }
+
+// Next we confirm that the second compile unit properly references types.
+//
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name{{.*}}"X86/odr-fwd-declaration.cpp"
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr2"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x00000000[[TYPEDEF_PTR_PTR_S]]
+
+#elif defined(FILE3)
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source1.cpp" 2
+void foo() { Sptrptr ptr1 = 0; }
+
+// Finally we confirm that third compile unit references types correctly.
+//
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name{{.*}}"X86/odr-fwd-declaration.cpp"
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr1"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x00000000[[TYPEDEF_PTR_PTR_S]]
+// CHECK-NOT: TAG_typedef
+// CHECK-NOT: TAG_pointer
+// CHECK-NOT: TAG_structure_type
+
+#else
+#error "You must define which file you generate"
+#endif
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration2.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration2.test
new file mode 100644
index 000000000000000..439b7d76bb69bf4
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration2.test
@@ -0,0 +1,131 @@
+/* Compile with:
+   for FILE in `seq 3`; do
+     clang -g -c  X86/odr-fwd-declaration2.cpp -DFILE$FILE -o
+       Inputs/odr-fwd-declaration2/$FILE.o done
+*/
+
+// RUN: dsymutil --linker=llvm -f \
+// RUN: -oso-prepend-path=%p/../../Inputs/odr-fwd-declaration2 \
+// RUN: -y %p/../dummy-debug-map.map -o %t1.out
+// RUN: llvm-dwarfdump -v %t1.out -debug-info | FileCheck %s
+
+#ifdef FILE1
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source1.cpp" 2
+void foo() { A *ptr1 = 0; }
+
+// First we check that types are in type table unit.
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: AT_name{{.*}}"__artificial_type_unit"
+
+// CHECK: 0x[[INT_BASE:[a-f0-9]*]]: DW_TAG_base_type
+// CHECK: AT_name{{.*}}"int"
+
+// CHECK: 0x[[PTR_A:[a-f0-9]*]]: DW_TAG_pointer_type
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4]   {{.*}}0x[[STRUCT_A:[a-f0-9]*]]} "A")
+
+// CHECK: 0x[[PTR_B:[a-f0-9]*]]: DW_TAG_pointer_type
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4]   {{.*}}0x[[STRUCT_B:[a-f0-9]*]]} "A::B")
+
+// CHECK: 0x[[REF_B:[a-f0-9]*]]: DW_TAG_reference_type
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4]   {{.*}}0x[[STRUCT_B]]} "A::B")
+
+// CHECK: 0x[[STRUCT_A]]: DW_TAG_structure_type
+// CHECK: AT_name{{.*}}"A"
+
+// CHECK: DW_TAG_member
+// CHECK-NEXT: AT_name{{.*}}"bPtr"
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}{0x[[PTR_B]]} "A::B *")
+
+// CHECK: DW_TAG_member
+// CHECK-NEXT: AT_name{{.*}}"bRef"
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}{0x[[REF_B]]} "A::B &"
+
+// CHECK: DW_TAG_member
+// CHECK-NEXT: AT_name{{.*}}"bPtrToField"
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}{0x[[PTR_TO_FIELD:[a-f0-9]*]]} "int A::B::*"
+
+// CHECK: 0x[[STRUCT_B]]: DW_TAG_structure_type
+// CHECK: AT_name{{.*}}"B"
+
+// CHECK: DW_TAG_member
+// CHECK: AT_name{{.*}}"x"
+
+// CHECK: 0x[[PTR_TO_FIELD]]: DW_TAG_ptr_to_member_type
+// CHECK-NEXT: DW_AT_type [DW_FORM_ref4]   {{.*}}{0x[[INT_BASE]]} "int"
+// CHECK-NEXT: DW_AT_containing_type [DW_FORM_ref4] {{.*}}{0x[[STRUCT_B]]} "A::B")
+
+// Next we check that second compile unit references type from type table unit.
+//
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: AT_name{{.*}}"X86/odr-fwd-declaration2.cpp"
+
+// CHECK: DW_TAG_subprogram
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"ptr1"
+// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[PTR_A]] "A *"
+
+#elif defined(FILE2)
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source2.cpp" 2
+struct A::B {
+  int x;
+};
+void bar() { A *ptr2 = 0; }
+
+// Next we check that thrid compile unit references type from type table unit.
+//
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: AT_name{{.*}}"X86/odr-fwd-declaration2.cpp"
+
+// CHECK: DW_TAG_subprogram
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"ptr2"
+// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[PTR_A]] "A *"
+
+#elif defined(FILE3)
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source2.cpp" 2
+struct A::B {
+  int x;
+};
+void bar() { A *ptr2 = 0; }
+
+// Next we check that fourth compile unit references type from type table unit.
+//
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: AT_name{{.*}}"X86/odr-fwd-declaration2.cpp"
+
+// CHECK: DW_TAG_subprogram
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"ptr2"
+// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000[[PTR_A]] "A *"
+
+#else
+#error "You must define which file you generate"
+#endif
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration3.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration3.test
new file mode 100644
index 000000000000000..9758e4ad4213033
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-fwd-declaration3.test
@@ -0,0 +1,381 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o %t1.out
+# RUN: llvm-dwarfdump -a %t1.out | FileCheck %s
+
+## This test checks debug info for the case when one compilation unit
+## contains forward declaration of the type and another compilation unit
+## contains definition for that type. The result should have type table
+## containing definition for that type and corresponding variables should
+## properly reference that type.
+
+## CU1:
+##
+## class class1;
+## template<int> class class2;
+##
+## class1 *var1;
+## class2<int> *var2;
+##
+## CU2:
+##
+## class class1 {
+##   char member1;
+##   float member2;
+## };
+##
+## template<int> class class2 {
+##   char member1;
+## };
+##
+## class1 *var1;
+## class2<int> *var2;
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+# CHECK: 0x[[CHAR:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"char"
+
+# CHECK: 0x[[FLOAT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"float"
+
+# CHECK: 0x[[INT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"int"
+
+# CHECK: 0x[[CLASS1:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"class1"
+# CHECK: DW_TAG_member
+# CHECK: DW_AT_type{{.*}}0x[[CHAR]] "char"
+# CHECK: DW_AT_name{{.*}}"member1"
+
+# CHECK: DW_TAG_member
+# CHECK: DW_AT_type{{.*}}0x[[FLOAT]] "float"
+# CHECK: DW_AT_name{{.*}}"member2"
+
+# CHECK: 0x[[CLASS2:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"class2"
+# CHECK: DW_TAG_template_type_parameter{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INT]] "int"
+# CHECK: DW_TAG_member
+# CHECK: DW_AT_type{{.*}}0x[[CHAR]] "char"
+# CHECK: DW_AT_name{{.*}}"member1"
+
+# CHECK: 0x[[PTR_CLASS1:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[CLASS1]] "class1"
+
+# CHECK: 0x[[PTR_CLASS2:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[CLASS2]] "class2<int>"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x{{.*}}[[PTR_CLASS1]] "class1 *"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x{{.*}}[[PTR_CLASS2]] "class2<int> *"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU2"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x{{.*}}[[PTR_CLASS1]] "class1 *"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x{{.*}}[[PTR_CLASS2]] "class2<int> *"
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x9c
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0xed
+        offset:    0x0000041c
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x000001FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          false
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           1
+    stroff:          0x710
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_template_type_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_template_type_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 4
+          Values:
+            - CStr: class1
+        - AbbrCode: 5
+          Values:
+            - CStr: class2
+        - AbbrCode: 6
+          Values:
+            - Value:  0x00000030
+        - AbbrCode: 0
+        - AbbrCode: 7
+          Values:
+            - CStr: int
+        - AbbrCode: 8
+          Values:
+            - Value:  0x0000001a
+        - AbbrCode: 8
+          Values:
+            - Value:  0x00000022
+        - AbbrCode: 9
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x00000035
+        - AbbrCode: 9
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x0000003a
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - CStr: class1
+        - AbbrCode: 3
+          Values:
+            - Value:  0x000000b9
+            - CStr: member1
+        - AbbrCode: 3
+          Values:
+            - Value:  0x000000bf
+            - CStr: member2
+        - AbbrCode: 0
+        - AbbrCode: 2
+          Values:
+            - CStr: class2
+        - AbbrCode: 6
+          Values:
+            - Value:  0x000000b4
+        - AbbrCode: 3
+          Values:
+            - Value:  0x000000b9
+            - CStr: member1
+        - AbbrCode: 0
+        - AbbrCode: 7
+          Values:
+            - CStr: int
+        - AbbrCode: 7
+          Values:
+            - CStr: char
+        - AbbrCode: 7
+          Values:
+            - CStr: float
+        - AbbrCode: 8
+          Values:
+            - Value:  0x00000076
+        - AbbrCode: 8
+          Values:
+            - Value:  0x00000099
+        - AbbrCode: 9
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x000000c6
+        - AbbrCode: 9
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x000000cb
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-member-functions.cpp b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-member-functions.cpp
new file mode 100644
index 000000000000000..7135c46630e13a9
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-member-functions.cpp
@@ -0,0 +1,192 @@
+/* Compile with:
+   for FILE in `seq 3`; do
+     clang -g -c  odr-member-functions.cpp -DFILE$FILE -o
+   odr-member-functions/$FILE.o done
+ */
+
+// RUN: dsymutil --linker=llvm -f \
+// RUN: -oso-prepend-path=%p/../../Inputs/odr-member-functions \
+// RUN: -y %p/../dummy-debug-map.map -o %t1.out
+// RUN: llvm-dwarfdump -debug-info %t1.out | FileCheck %s
+
+struct S {
+  __attribute__((always_inline)) void foo() { bar(); }
+  __attribute__((always_inline)) void foo(int i) {
+    if (i)
+      bar();
+  }
+  void bar();
+
+  template <typename T> void baz(T t) {}
+};
+
+#ifdef FILE1
+void foo() { S s; }
+
+// First chack that types are moved into the type table unit.
+
+// CHECK: TAG_compile_unit
+// CHECK: AT_name{{.*}}"__artificial_type_unit"
+
+// CHECK: 0x[[INT_BASE:[0-9a-f]*]]: DW_TAG_base_type
+// CHECK-NEXT: DW_AT_name{{.*}}"int"
+
+// CHECK: 0x[[PTR_S:[0-9a-f]*]]:{{.*}}DW_TAG_pointer_type
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[STRUCT_S:[0-9a-f]*]] "S")
+
+// CHECK: 0x[[STRUCT_S]]:{{.*}}DW_TAG_structure_type
+// CHECK-NEXT: DW_AT_name{{.*}}"S"
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S3barEv"
+// CHECK: DW_AT_name{{.*}}"bar"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[PTR_S]] "S *"
+
+// CHECK: 0x[[BAZ_SUBPROGRAM:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S3bazIiEEvT_"
+// CHECK: DW_AT_name{{.*}}"baz<int>"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[PTR_S]] "S *"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[INT_BASE]] "int"
+
+// CHECK: DW_TAG_template_type_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[INT_BASE]] "int"
+// CHECK-NEXT: DW_AT_name{{.*}}"T"
+
+// CHECK: 0x[[FOO_Ei:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S3fooEi"
+// CHECK: DW_AT_name{{.*}}"foo"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[PTR_S]] "S *"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[INT_BASE]] "int"
+
+// CHECK: 0x[[FOO_Ev:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S3fooEv"
+// CHECK: DW_AT_name{{.*}}"foo"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_type{{.*}}0x[[PTR_S]] "S *"
+
+// For the second unit check that it references structure "S"
+
+// CHECK: TAG_compile_unit
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}}"odr-member-functions.cpp"
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK-NEXT: AT_name{{.*}}"foo"
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"s"
+// CHECK: DW_AT_type{{.*}}(0x00000000[[STRUCT_S]] "S"
+
+#elif defined(FILE2)
+void foo() {
+  S s;
+  // Check that the overloaded member functions are resolved correctly
+  s.foo();
+  s.foo(1);
+}
+
+// For the third unit check that it references member functions of structure S.
+// CHECK: TAG_compile_unit
+// CHECK-NOT: DW_TAG
+// CHECK: AT_name{{.*}}"odr-member-functions.cpp"
+
+// CHECK: 0x[[ABASE_FOO_Ev:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
+// CHECK-NEXT: DW_AT_specification {{.*}}(0x00000000[[FOO_Ev]] "_ZN1S3fooEv"
+// CHECK-NEXT: DW_AT_inline    (DW_INL_inlined)
+// CHECK-NEXT: DW_AT_object_pointer {{.*}}(0x[[ABASE_FOO_Ev_PARAM1:[0-9a-f]*]]
+
+// CHECK: 0x[[ABASE_FOO_Ev_PARAM1]]:{{.*}}DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_name{{.*}}"this"
+// CHECK-NEXT: DW_AT_type{{.*}}(0x00000000[[PTR_S]] "S *"
+
+// CHECK: 0x[[ABASE_FOO_Ei:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
+// CHECK-NEXT: DW_AT_specification {{.*}}(0x00000000[[FOO_Ei]] "_ZN1S3fooEi"
+// CHECK-NEXT: DW_AT_inline    (DW_INL_inlined)
+// CHECK-NEXT: DW_AT_object_pointer {{.*}}(0x[[ABASE_FOO_Ei_PARAM1:[0-9a-f]*]]
+
+// CHECK: 0x[[ABASE_FOO_Ei_PARAM1]]:{{.*}}DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_name{{.*}}"this"
+// CHECK-NEXT: DW_AT_type{{.*}}(0x00000000[[PTR_S]] "S *"
+
+// CHECK: 0x[[ABASE_FOO_Ei_PARAM2:[0-9a-f]*]]:{{.*}}DW_TAG_formal_parameter
+// CHECK-NEXT: DW_AT_name{{.*}}"i"
+// CHECK: DW_AT_type    (0x00000000[[INT_BASE]] "int"
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK: DW_AT_name{{.*}}"foo"
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"s"
+// CHECK: DW_AT_type{{.*}}(0x00000000[[STRUCT_S]] "S"
+
+// CHECK: DW_TAG_inlined_subroutine
+// CHECK: DW_AT_abstract_origin{{.*}}(0x[[ABASE_FOO_Ev]] "_ZN1S3fooEv"
+// CHECK: DW_AT_low_pc
+// CHECK: DW_AT_high_pc
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK: DW_AT_abstract_origin{{.*}}(0x[[ABASE_FOO_Ev_PARAM1]] "this"
+
+// CHECK: DW_TAG_inlined_subroutine
+// CHECK: DW_AT_abstract_origin{{.*}}(0x[[ABASE_FOO_Ei]] "_ZN1S3fooEi"
+// CHECK: DW_AT_low_pc
+// CHECK: DW_AT_high_pc
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK: DW_AT_abstract_origin{{.*}}(0x[[ABASE_FOO_Ei_PARAM1]] "this"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK: DW_AT_abstract_origin{{.*}}(0x[[ABASE_FOO_Ei_PARAM2]] "i"
+
+#elif defined(FILE3)
+void foo() {
+  S s;
+  s.baz<int>(42);
+}
+
+// For the fourth unit check that it references member functions of structure S.
+
+// CHECK: TAG_compile_unit
+// CHECK-NOT: DW_TAG
+// CHECK: AT_name{{.*}}"odr-member-functions.cpp"
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK: DW_AT_name{{.*}}"foo"
+
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name{{.*}}"s"
+// CHECK: DW_AT_type{{.*}}(0x00000000[[STRUCT_S]] "S"
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_object_pointer{{.*}}(0x[[INST_PARAM2:[0-9a-f]*]]
+// CHECK: DW_AT_specification{{.*}}(0x00000000[[BAZ_SUBPROGRAM]] "_ZN1S3bazIiEEvT_"
+
+// CHECK: 0x[[INST_PARAM2]]:{{.*}}DW_TAG_formal_parameter
+// CHECK: DW_AT_name{{.*}}"this"
+// CHECK: DW_AT_type{{.*}}(0x00000000[[PTR_S]] "S *"
+
+// CHECK: DW_TAG_formal_parameter
+// CHECK: DW_AT_name{{.*}}"t"
+// CHECK: DW_AT_type{{.*}}(0x00000000[[INT_BASE]] "int"
+
+// CHECK: DW_TAG_template_type_parameter
+// CHECK: DW_AT_type{{.*}}(0x00000000[[INT_BASE]] "int"
+// CHECK: DW_AT_name{{.*}}"T"
+
+#else
+#error "You must define which file you generate"
+#endif
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-namespace-extension.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-namespace-extension.test
new file mode 100644
index 000000000000000..6c31b48978e9828
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-namespace-extension.test
@@ -0,0 +1,157 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o %t1.out
+# RUN: llvm-dwarfdump -a %t1.out | FileCheck %s
+
+## This test checks that DW_TAG_namespace with DW_AT_extension
+## attribute is joined with referenced namespace.
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: 0x0000000b: DW_TAG_compile_unit
+# CHECK: DW_TAG_namespace
+# CHECK: DW_AT_name{{.*}}"parent_namespace"
+# CHECK-NOT: DW_TAG_namespace
+# CHECK: 0x[[INT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"int"
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_type      (0x00000000[[INT]]
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x2A
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x42
+        offset:    0x000003AA
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x000001FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          false
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           1
+    stroff:          0x710
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+      - Tag:      DW_TAG_namespace
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_namespace
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_extension
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+        - AbbrCode: 2
+          Values:
+            - CStr: parent_namespace
+        - AbbrCode: 3
+          Values:
+            - Value:  0x00000016
+        - AbbrCode: 4
+          Values:
+            - CStr: int
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: var
+            - Value:  0x000000FF
+            - Value:  0x0000002d
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types1.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types1.test
new file mode 100644
index 000000000000000..22a142ab97657c6
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types1.test
@@ -0,0 +1,384 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o %t1.out
+# RUN: llvm-dwarfdump -a %t1.out | FileCheck %s
+
+## This test checks that nested structure containing field of anonymuos type
+## partially moved into the type table. Anonymous part of the structure should be
+## left in the original containg compile unit:
+##
+## CU1:
+##
+## struct s1 { struct s2; }
+##
+## namespace {
+##   struct s3 {};
+## }
+##
+## struct s1::s2 { s3 m; };
+##
+## struct s1::s2 *var1;
+## struct s1::s2::s3 *var2;
+##
+## CU2:
+##
+## struct s1 { struct s2; }
+##
+## struct s1::s2 *var3;
+##
+##
+## Final type table should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("__type_table")
+##
+##   DW_TAG_structure_type
+##     DW_AT_name      ("s1")
+##
+##     DW_TAG_structure_type
+##       DW_AT_name    ("s2")
+##       DW_AT_declaration     (true)
+##
+## CU1 should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("CU1")
+##
+##   DW_TAG_structure_type
+##     DW_AT_name      ("s1")
+##
+##     DW_TAG_structure_type
+##       DW_AT_name    ("s2")
+##
+##       DW_TAG_member
+##         DW_AT_name  ("m")
+##         DW_AT_type  ("(anonymous namespace)::s3")
+##
+##   DW_TAG_namespace
+##
+##     DW_TAG_structure_type
+##       DW_AT_name    ("s3")
+##
+##   DW_TAG_variable
+##     DW_AT_name      ("var1")
+##     DW_AT_type      ("s1::s2 *")
+##
+##   DW_TAG_variable
+##     DW_AT_name      ("var2")
+##     DW_AT_type      ("s1::s2::m *")
+##
+## CU2  should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("CU2")
+##
+##  DW_TAG_variable
+##     DW_AT_name      ("var3")
+##     DW_AT_type      ("s1::s2 *")
+##
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+# CHECK: 0x[[PTR_INNER_STRUCT:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_STRUCT:[0-9a-f]*]] "s1::s2")
+
+# CHECK: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"s1"
+
+# CHECK: 0x[[INNER_STRUCT:[0-9a-f]*]]: DW_TAG_structure_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"s2"
+# CHECK: DW_AT_declaration{{.*}}true
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+
+# CHECK: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"s1"
+
+# CHECK: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"s2"
+
+# CHECK: 0x[[INNER_STRUCT_MEMBER:[0-9a-f]*]]: DW_TAG_member{{.*[[:space:]].*}}DW_AT_name{{.*}}"m"
+# CHECK: DW_AT_type{{.*}}0x[[ANON_STRUCT:[0-9a-f]*]] "(anonymous namespace)::s3"
+
+# CHECK: DW_TAG_namespace
+# CHECK: 0x[[ANON_STRUCT]]: DW_TAG_structure_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"s3"
+
+# CHECK: 0x[[ANON_PTR_INNER_STRUCT:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_STRUCT:[0-9a-f]*]] "s1::s2")
+
+# CHECK: 0x[[PTR_STRUCT_MEMBER:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_STRUCT_MEMBER]] "m"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x[[ANON_PTR_INNER_STRUCT]] "s1::s2 *"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x[[PTR_STRUCT_MEMBER]] "m *"
+
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU2"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var3"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_INNER_STRUCT]] "s1::s2 *"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var4"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_INNER_STRUCT]] "s1::s2 *"
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x76
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0xa7
+        offset:    0x000003f6
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x0
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          true
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           2
+    stroff:          0x720
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_namespace
+        Children: DW_CHILDREN_yes
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 2
+          Values:
+            - CStr: s1
+        - AbbrCode: 2
+          Values:
+            - CStr: s2
+        - AbbrCode: 4
+          Values:
+            - CStr: m
+            - Value:  0x0000002c
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 7
+        - AbbrCode: 3
+          Values:
+            - CStr: s3
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: int
+        - AbbrCode: 6
+          Values:
+            - Value:  0x0000001e
+        - AbbrCode: 6
+          Values:
+            - Value:  0x00000022
+        - AbbrCode: 8
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x00000036
+        - AbbrCode: 8
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x0000003b
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - CStr: s1
+        - AbbrCode: 3
+          Values:
+            - CStr: s2
+        - AbbrCode: 0
+        - AbbrCode: 4
+          Values:
+            - CStr: int
+        - AbbrCode: 5
+          Values:
+            - Value:  0x0000007b
+        - AbbrCode: 6
+          Values:
+            - CStr: var3
+            - Value:  0x00000000
+            - Value:  0x00000085
+        - AbbrCode: 6
+          Values:
+            - CStr: var4
+            - Value:  0x00000000
+            - Value:  0x00000085
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types2.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types2.test
new file mode 100644
index 000000000000000..35d3261e591cb3b
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-nested-types2.test
@@ -0,0 +1,374 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o %t1.out
+# RUN: llvm-dwarfdump -a %t1.out | FileCheck %s
+
+## This test checks that nested structure containing field of type from other namespace
+## fully moved into the type table.
+##
+## CU1:
+##
+## struct s1 { struct s2; }
+##
+## namespace namespace1 {
+##   struct s3 {};
+## }
+##
+## struct s1::s2 { s3 m; };
+##
+## struct s1::s2 *var1;
+## struct s1::s2::s3 *var2;
+##
+## CU2:
+##
+## struct s1 { struct s2; }
+##
+## struct s1::s2 *var3;
+##
+##
+## Final type table should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("__type_table")
+##
+##   DW_TAG_namespace
+##     DW_AT_name      ("namespace1")
+##
+##     DW_TAG_structure_type
+##       DW_AT_name    ("s3")
+##
+##   DW_TAG_structure_type
+##     DW_AT_name      ("s1")
+##
+##     DW_TAG_structure_type
+##       DW_AT_name    ("s2")
+##
+##       DW_TAG_member
+##         DW_AT_name  ("m")
+##         DW_AT_type  ("namespace1::s3")
+##
+## CU1 should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("CU1")
+##
+##   DW_TAG_variable
+##     DW_AT_name      ("var1")
+##     DW_AT_type      ("s1::s2 *")
+##
+##   DW_TAG_variable
+##     DW_AT_name      ("var2")
+##     DW_AT_type      ("s1::s2::m *")
+##
+## CU2 should contain:
+##
+## DW_TAG_compile_unit
+##   DW_AT_name        ("CU2")
+##
+##   DW_TAG_variable
+##     DW_AT_name      ("var1")
+##     DW_AT_type      ("s1::s2 *")
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+# CHECK: DW_TAG_namespace
+# CHECK: DW_AT_name{{.*}}"namespace1"
+# CHECK: 0x[[NAMESPACE_STRUCT:[0-9a-f]*]]: DW_TAG_structure_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"s3"
+
+# CHECK: 0x[[PTR_INNER_STRUCT:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_STRUCT:[0-9a-f]*]] "s1::s2")
+
+# CHECK: 0x[[PTR_STRUCT_MEMBER:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_STRUCT_MEMBER:[0-9a-f]*]] "m"
+
+# CHECK: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"s1"
+
+# CHECK: 0x[[INNER_STRUCT]]: DW_TAG_structure_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"s2"
+# CHECK-NOT: DW_AT_declaration
+
+# CHECK: 0x[[INNER_STRUCT_MEMBER]]: DW_TAG_member{{.*[[:space:]].*}}DW_AT_name{{.*}}"m"
+# CHECK: DW_AT_type{{.*}}0x[[NAMESPACE_STRUCT]] "namespace1::s3"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_INNER_STRUCT]] "s1::s2 *"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_STRUCT_MEMBER]] "m *"
+
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU2"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var3"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_INNER_STRUCT]] "s1::s2 *"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var4"
+# CHECK: DW_AT_type{{.*}}0x00000000[[PTR_INNER_STRUCT]] "s1::s2 *"
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x78
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0xb2
+        offset:    0x000003F8
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x0
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          true
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           2
+    stroff:          0x720
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_namespace
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_declaration
+            Form:      DW_FORM_flag_present
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 2
+          Values:
+            - CStr: s1
+        - AbbrCode: 2
+          Values:
+            - CStr: s2
+        - AbbrCode: 4
+          Values:
+            - CStr: m
+            - Value:  0x00000037
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 7
+          Values:
+            - CStr: namespace1
+        - AbbrCode: 3
+          Values:
+            - CStr: s3
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: int
+        - AbbrCode: 6
+          Values:
+            - Value:  0x0000001e
+        - AbbrCode: 6
+          Values:
+            - Value:  0x00000022
+        - AbbrCode: 8
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x00000041
+        - AbbrCode: 8
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x00000046
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - CStr: s1
+        - AbbrCode: 3
+          Values:
+            - CStr: s2
+        - AbbrCode: 0
+        - AbbrCode: 4
+          Values:
+            - CStr: int
+        - AbbrCode: 5
+          Values:
+            - Value:  0x00000086
+        - AbbrCode: 6
+          Values:
+            - CStr: var3
+            - Value:  0x00000000
+            - Value:  0x00000090
+        - AbbrCode: 6
+          Values:
+            - CStr: var4
+            - Value:  0x00000000
+            - Value:  0x00000090
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-parents.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-parents.test
new file mode 100644
index 000000000000000..7c1c0d1b52e0eec
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-parents.test
@@ -0,0 +1,238 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o - | llvm-dwarfdump -a - | FileCheck %s
+
+## This test checks debug info for the equally named structures from
+## different namespaces. The result should contain two variables which
+## reference different types("A::C1::I1 *const" and "B::C1::I1 *const")
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+# CHECK: 0x[[INT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"int"
+
+# CHECK: DW_TAG_namespace{{.*[[:space:]].*}}DW_AT_name{{.*}}"A"
+
+# CHECK: 0x[[A_C1:[0-9a-f]*]]: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"C1"
+# CHECK: DW_TAG_member
+# CHECK: DW_AT_type{{.*}}0x[[INT]] "int"
+# CHECK: DW_AT_name{{.*}}"I1"
+
+# CHECK: DW_TAG_namespace{{.*[[:space:]].*}}DW_AT_name{{.*}}"B"
+
+# CHECK: 0x[[B_C1:[0-9a-f]*]]: DW_TAG_structure_type
+# CHECK: DW_AT_name{{.*}}"C1"
+# CHECK: DW_TAG_member
+# CHECK: DW_AT_type{{.*}}0x[[INT]] "int"
+# CHECK: DW_AT_name{{.*}}"I1"
+
+# CHECK: 0x[[PTR_A_C1:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[A_C1:[0-9a-f]*]] "A::C1"
+
+# CHECK: 0x[[PTR_B_C1:[0-9a-f]*]]: DW_TAG_pointer_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[B_C1:[0-9a-f]*]] "B::C1"
+
+# CHECK: 0x[[CONST_A_C1:[0-9a-f]*]]: DW_TAG_const_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[PTR_A_C1]] "A::C1 *"
+
+# CHECK: 0x[[CONST_B_C1:[0-9a-f]*]]: DW_TAG_const_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[PTR_B_C1]] "B::C1 *"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[CONST_A_C1]] "A::C1 *const"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x00000000[[CONST_B_C1]] "B::C1 *const"
+
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x41
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x6e
+        offset:    0x000003C1
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x000001FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          false
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           1
+    stroff:          0x710
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+      - Tag:      DW_TAG_namespace
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_structure_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_const_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+        - AbbrCode: 2
+          Values:
+            - CStr: A
+        - AbbrCode: 3
+          Values:
+            - CStr: C1
+        - AbbrCode: 4
+          Values:
+            - Value:  0x00000038
+            - CStr: I1
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 2
+          Values:
+            - CStr: B
+        - AbbrCode: 3
+          Values:
+            - CStr: C1
+        - AbbrCode: 4
+          Values:
+            - Value:  0x00000038
+            - CStr: I1
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: int
+        - AbbrCode: 6
+          Values:
+            - Value:  0x00000019
+        - AbbrCode: 6
+          Values:
+            - Value:  0x0000002a
+        - AbbrCode: 7
+          Values:
+            - Value:  0x0000003D
+        - AbbrCode: 7
+          Values:
+            - Value:  0x00000042
+        - AbbrCode: 8
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x00000047
+        - AbbrCode: 8
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x0000004C
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output.test
new file mode 100644
index 000000000000000..187a2ea9ecffdcd
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output.test
@@ -0,0 +1,117 @@
+# RUN: dsymutil --linker=llvm -f -o %t1.o -oso-prepend-path=%p/ -y %s
+# RUN: llvm-dwarfdump --verify %t1.o | FileCheck -check-prefixes=VERIFY %s
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/ -y %s --num-threads 1 | llvm-dwarfdump -a - -o %t1
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/ -y %s --num-threads 3 | llvm-dwarfdump -a - -o %t2
+# RUN: diff %t1 %t2
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/ -y %s --num-threads 4 | llvm-dwarfdump -a - -o %t3
+# RUN: diff %t1 %t3
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/ -y %s | llvm-dwarfdump -a - -o %t4
+# RUN: diff %t1 %t4
+
+# This test checks that generated output does not differ between runs.
+#
+# To recreate a test compile following example:
+#
+# main.cpp:
+#
+# include <string>
+#
+# void PrintSize ( const std::string& String );
+# void PrintNewString ( const std::string& String );
+# void PrintNewString2 ( const char* String );
+#
+# int main ( void ) {
+#
+#   PrintSize("hello");
+#   PrintNewString("hello");
+#   PrintNewString2("hello");
+#   printf("\n");
+#
+#   return 0;
+# }
+#
+# foo1.cpp:
+#
+# #include <string>
+#
+# void PrintSize ( const std::string& String ) {
+#   printf("\n String size %lu", String.size() );
+# };
+#
+# foo2.cpp:
+#
+# #include <string>
+#
+# void PrintNewString ( const std::string& String ) {
+#  std::string NewString(String);
+#  NewString += "++";
+#  printf("\n String %s", NewString.c_str());
+#};
+#
+# foo3.cpp:
+# #include <string>
+#
+# void PrintNewString2 ( const char* String ) {
+#   std::string NewString(String);
+#   NewString += "++";
+#   printf("\n String2 %s", NewString.c_str());
+# };
+#
+# with clang++ -O -fno-inline -g -std=c++11
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename:        'Inputs/String/foo1.o'
+    timestamp:       1638904719
+    symbols:
+      - { sym: __ZNKSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EE5__getEv, objAddr: 0x00000000000000A0, binAddr: 0x0000000100000B10, size: 0x00000009 }
+      - { sym: __ZNKSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_E5firstEv, objAddr: 0x0000000000000090, binAddr: 0x0000000100000B00, size: 0x00000010 }
+      - { sym: __Z9PrintSizeRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000A70, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE15__get_long_sizeEv, objAddr: 0x0000000000000060, binAddr: 0x0000000100000AD0, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4sizeEv, objAddr: 0x0000000000000020, binAddr: 0x0000000100000A90, size: 0x00000030 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16__get_short_sizeEv, objAddr: 0x0000000000000070, binAddr: 0x0000000100000AE0, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__is_longEv, objAddr: 0x0000000000000050, binAddr: 0x0000000100000AC0, size: 0x00000010 }
+  - filename:        'Inputs/String/foo2.o'
+    timestamp:       1638904723
+    symbols:
+      - { sym: __ZNSt3__112__to_addressIKcEEPT_S3_, objAddr: 0x00000000000000E0, binAddr: 0x0000000100000BD0, size: 0x00000010 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000016C, binAddr: 0x0000000100000F24, size: 0x00000000 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE18__get_long_pointerEv, objAddr: 0x0000000000000120, binAddr: 0x0000000100000C10, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE19__get_short_pointerEv, objAddr: 0x0000000000000130, binAddr: 0x0000000100000C20, size: 0x00000020 }
+      - { sym: __ZNSt3__114pointer_traitsIPKcE10pointer_toERS1_, objAddr: 0x0000000000000150, binAddr: 0x0000000100000C40, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEpLEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000B90, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4dataEv, objAddr: 0x00000000000000C0, binAddr: 0x0000000100000BB0, size: 0x00000020 }
+      - { sym: __Z14PrintNewStringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000B20, size: 0x00000070 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5c_strEv, objAddr: 0x0000000000000080, binAddr: 0x0000000100000BA1, size: 0x00000010 }
+      - { sym: __ZNSt3__19addressofIKcEEPT_RS2_, objAddr: 0x0000000000000160, binAddr: 0x0000000100000C50, size: 0x00000009 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13__get_pointerEv, objAddr: 0x00000000000000F0, binAddr: 0x0000000100000BE0, size: 0x00000030 }
+  - filename:        'Inputs/String/foo3.o'
+    timestamp:       1638904727
+    symbols:
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC2INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000130, binAddr: 0x0000000100000D50, size: 0x00000040 }
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC1INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000110, binAddr: 0x0000000100000D20, size: 0x00000010 }
+      - { sym: __ZNSt3__111char_traitsIcE6lengthEPKc, objAddr: 0x0000000000000120, binAddr: 0x0000000100000D40, size: 0x00000010 }
+      - { sym: __ZNSt3__116__non_trivial_ifILb1ENS_9allocatorIcEEEC2Ev, objAddr: 0x00000000000001B0, binAddr: 0x0000000100000DC0, size: 0x00000010 }
+      - { sym: __ZNSt3__17forwardINS_18__default_init_tagEEEOT_RNS_16remove_referenceIS2_E4typeE, objAddr: 0x0000000000000170, binAddr: 0x0000000100000D80, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000180, binAddr: 0x0000000100000D90, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_9allocatorIcEELi1ELb1EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000190, binAddr: 0x0000000100000DA0, size: 0x00000010 }
+      - { sym: __ZNSt3__19allocatorIcEC2Ev, objAddr: 0x00000000000001A0, binAddr: 0x0000000100000DB0, size: 0x00000010 }
+      - { sym: __Z15PrintNewString2PKc, objAddr: 0x0000000000000000, binAddr: 0x0000000100000C60, size: 0x00000070 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000026C, binAddr: 0x0000000100000F34, size: 0x00000000 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1IDnEEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000CD0, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc, objAddr: 0x00000000000000D0, binAddr: 0x0000000100000CE0, size: 0x00000040 }
+  - filename:        'Inputs/String/main.o'
+    timestamp:       1638904734
+    symbols:
+      - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000DD0, size: 0x00000090 }
+      - { sym: GCC_except_table0, objAddr: 0x0000000000000188, binAddr: 0x0000000100000F44, size: 0x00000000 }
+...
+
+VERIFY: Verifying .debug_abbrev...
+VERIFY: Verifying .debug_info Unit Header Chain...
+VERIFY: Verifying .apple_names...
+VERIFY: Verifying .apple_types...
+VERIFY: Verifying .apple_namespaces...
+VERIFY: Verifying .apple_objc...
+VERIFY: No errors.
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output2.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output2.test
new file mode 100644
index 000000000000000..93925c61c46b8b4
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-predictable-output2.test
@@ -0,0 +1,120 @@
+# RUN: dsymutil --linker=llvm -f -o %t1.o -oso-prepend-path=%p/../ -y %s
+# RUN: llvm-dwarfdump --verify %t1.o | FileCheck -check-prefixes=VERIFY %s
+# RUN: dsymutil --linker=llvm -f -o %t2.o -oso-prepend-path=%p/../ -y %s
+# RUN: dsymutil --linker=llvm -f -o %t3.o -oso-prepend-path=%p/../ -y %s \
+# RUN:   --num-threads 1
+# RUN: dsymutil --linker=llvm -f -o %t4.o -oso-prepend-path=%p/../ -y %s \
+# RUN:   --num-threads 3
+# ### Following comparision will fail if files do not match
+# RUN: diff %t1.o %t2.o
+# RUN: diff %t1.o %t3.o
+# RUN: diff %t1.o %t4.o
+
+# This test checks that generated output does not differ between runs.
+#
+# To recreate a test compile following example:
+#
+# main.cpp:
+#
+# include <string>
+#
+# void PrintSize ( const std::string& String );
+# void PrintNewString ( const std::string& String );
+# void PrintNewString2 ( const char* String );
+#
+# int main ( void ) {
+#
+#   PrintSize("hello");
+#   PrintNewString("hello");
+#   PrintNewString2("hello");
+#   printf("\n");
+#
+#   return 0;
+# }
+#
+# foo1.cpp:
+#
+# #include <string>
+#
+# void PrintSize ( const std::string& String ) {
+#   printf("\n String size %lu", String.size() );
+# };
+#
+# foo2.cpp:
+#
+# #include <string>
+#
+# void PrintNewString ( const std::string& String ) {
+#  std::string NewString(String);
+#  NewString += "++";
+#  printf("\n String %s", NewString.c_str());
+#};
+#
+# foo3.cpp:
+# #include <string>
+#
+# void PrintNewString2 ( const char* String ) {
+#   std::string NewString(String);
+#   NewString += "++";
+#   printf("\n String2 %s", NewString.c_str());
+# };
+#
+# with clang++ -O -fno-inline -g -std=c++11
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename:        'Inputs/String/foo1.o'
+    timestamp:       1638904719
+    symbols:
+      - { sym: __ZNKSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EE5__getEv, objAddr: 0x00000000000000A0, binAddr: 0x0000000100000B10, size: 0x00000009 }
+      - { sym: __ZNKSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_E5firstEv, objAddr: 0x0000000000000090, binAddr: 0x0000000100000B00, size: 0x00000010 }
+      - { sym: __Z9PrintSizeRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000A70, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE15__get_long_sizeEv, objAddr: 0x0000000000000060, binAddr: 0x0000000100000AD0, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4sizeEv, objAddr: 0x0000000000000020, binAddr: 0x0000000100000A90, size: 0x00000030 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16__get_short_sizeEv, objAddr: 0x0000000000000070, binAddr: 0x0000000100000AE0, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__is_longEv, objAddr: 0x0000000000000050, binAddr: 0x0000000100000AC0, size: 0x00000010 }
+  - filename:        'Inputs/String/foo2.o'
+    timestamp:       1638904723
+    symbols:
+      - { sym: __ZNSt3__112__to_addressIKcEEPT_S3_, objAddr: 0x00000000000000E0, binAddr: 0x0000000100000BD0, size: 0x00000010 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000016C, binAddr: 0x0000000100000F24, size: 0x00000000 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE18__get_long_pointerEv, objAddr: 0x0000000000000120, binAddr: 0x0000000100000C10, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE19__get_short_pointerEv, objAddr: 0x0000000000000130, binAddr: 0x0000000100000C20, size: 0x00000020 }
+      - { sym: __ZNSt3__114pointer_traitsIPKcE10pointer_toERS1_, objAddr: 0x0000000000000150, binAddr: 0x0000000100000C40, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEpLEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000B90, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4dataEv, objAddr: 0x00000000000000C0, binAddr: 0x0000000100000BB0, size: 0x00000020 }
+      - { sym: __Z14PrintNewStringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000B20, size: 0x00000070 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5c_strEv, objAddr: 0x0000000000000080, binAddr: 0x0000000100000BA1, size: 0x00000010 }
+      - { sym: __ZNSt3__19addressofIKcEEPT_RS2_, objAddr: 0x0000000000000160, binAddr: 0x0000000100000C50, size: 0x00000009 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13__get_pointerEv, objAddr: 0x00000000000000F0, binAddr: 0x0000000100000BE0, size: 0x00000030 }
+  - filename:        'Inputs/String/foo3.o'
+    timestamp:       1638904727
+    symbols:
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC2INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000130, binAddr: 0x0000000100000D40, size: 0x00000040 }
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC1INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000110, binAddr: 0x0000000100000D20, size: 0x00000010 }
+      - { sym: __ZNSt3__111char_traitsIcE6lengthEPKc, objAddr: 0x0000000000000120, binAddr: 0x0000000100000D50, size: 0x00000010 }
+      - { sym: __ZNSt3__116__non_trivial_ifILb1ENS_9allocatorIcEEEC2Ev, objAddr: 0x00000000000001B0, binAddr: 0x0000000100000DC0, size: 0x00000010 }
+      - { sym: __ZNSt3__17forwardINS_18__default_init_tagEEEOT_RNS_16remove_referenceIS2_E4typeE, objAddr: 0x0000000000000170, binAddr: 0x0000000100000D80, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000180, binAddr: 0x0000000100000D90, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_9allocatorIcEELi1ELb1EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000190, binAddr: 0x0000000100000DA0, size: 0x00000010 }
+      - { sym: __ZNSt3__19allocatorIcEC2Ev, objAddr: 0x00000000000001A0, binAddr: 0x0000000100000DB0, size: 0x00000010 }
+      - { sym: __Z15PrintNewString2PKc, objAddr: 0x0000000000000000, binAddr: 0x0000000100000C60, size: 0x00000070 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000026C, binAddr: 0x0000000100000F34, size: 0x00000000 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1IDnEEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000CD0, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc, objAddr: 0x00000000000000D0, binAddr: 0x0000000100000CE0, size: 0x00000040 }
+  - filename:        'Inputs/String/main.o'
+    timestamp:       1638904734
+    symbols:
+      - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000DD0, size: 0x00000090 }
+      - { sym: GCC_except_table0, objAddr: 0x0000000000000188, binAddr: 0x0000000100000F44, size: 0x00000000 }
+...
+
+VERIFY: Verifying .debug_abbrev...
+VERIFY: Verifying .debug_info Unit Header Chain...
+VERIFY: Verifying .debug_types Unit Header Chain...
+VERIFY: Verifying .apple_names...
+VERIFY: Verifying .apple_types...
+VERIFY: Verifying .apple_namespaces...
+VERIFY: Verifying .apple_objc...
+VERIFY: No errors.
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-recursive-dependence.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-recursive-dependence.test
new file mode 100644
index 000000000000000..619bc8c15b8229c
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-recursive-dependence.test
@@ -0,0 +1,245 @@
+## This test checks output of dsymutil for the incorrect DWARF.
+## CU1 has a type which references type in CU2. This referenced
+## type references the same type in CU1 back. There is a recursive
+## dependence between these two types. dsymutil should report a error,
+## remove CU1 and CU2, put only CU3 into the output.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker llvm -y %t2.map --num-threads 1 -f -o %t1.out 2>&1 \
+# RUN:   | FileCheck --check-prefix ERROR %s
+# RUN: llvm-dwarfdump -a %t1.out | FileCheck %s
+
+# ERROR: error: Cann't parse input DWARF. Recursive dependence.
+# ERROR: while processing CU1
+# ERROR: error: Cann't resolve DIE reference
+# ERROR: while processing CU2
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+# CHECK: 0x[[CLASS1:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"class1"
+
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK-NOT: "CU1"
+# CHECK-NOT: "CU2"
+# CHECK: DW_AT_name{{.*}}"CU3"
+# CHECK-NOT: DW_TAG_class_type
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var3"
+# CHECK: DW_AT_const_value
+# CHECK: DW_AT_type (0x00000000[[CLASS1]]
+
+# CHECK-NOT: Compile Unit:
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x5a
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x8d
+        offset:    0x00000410
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x1FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          true
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           2
+    stroff:          0x720
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref4
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref4
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref4
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 2
+          Values:
+            - Value:  0x48
+        - AbbrCode: 3
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x0000001a
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - Value: 0x1a
+        - AbbrCode: 3
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x0000001a
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU3
+        - AbbrCode: 2
+          Values:
+            - CStr: class1
+        - AbbrCode: 3
+          Values:
+            - CStr: var3
+            - Value:  0x00000000
+            - Value:  0x0000001a
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-string.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-string.test
new file mode 100644
index 000000000000000..a8fc3e82311ca50
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-string.test
@@ -0,0 +1,180 @@
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/../ -y %s | llvm-dwarfdump --verify - | FileCheck -check-prefixes=VERIFY %s
+# RUN: dsymutil --linker=llvm -f -o - -oso-prepend-path=%p/../ -y %s | llvm-dwarfdump -a - | FileCheck %s
+
+# This test checks that types from several object files are
+# uniqued(moved into the artificial compile unit for types).
+# It also checks that information between different debug
+# tables is consistent.
+#
+# To recreate a test compile following example:
+#
+# main.cpp:
+#
+# include <string>
+#
+# void PrintSize ( const std::string& String );
+# void PrintNewString ( const std::string& String );
+# void PrintNewString2 ( const char* String );
+#
+# int main ( void ) {
+#
+#   PrintSize("hello");
+#   PrintNewString("hello");
+#   PrintNewString2("hello");
+#   printf("\n");
+#
+#   return 0;
+# }
+#
+# foo1.cpp:
+#
+# #include <string>
+#
+# void PrintSize ( const std::string& String ) {
+#   printf("\n String size %lu", String.size() );
+# };
+#
+# foo2.cpp:
+#
+# #include <string>
+#
+# void PrintNewString ( const std::string& String ) {
+#  std::string NewString(String);
+#  NewString += "++";
+#  printf("\n String %s", NewString.c_str());
+#};
+#
+# foo3.cpp:
+# #include <string>
+#
+# void PrintNewString2 ( const char* String ) {
+#   std::string NewString(String);
+#   NewString += "++";
+#   printf("\n String2 %s", NewString.c_str());
+# };
+#
+# with clang++ -O -fno-inline -g -std=c++11
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename:        'Inputs/String/foo1.o'
+    timestamp:       1638904719
+    symbols:
+      - { sym: __ZNKSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EE5__getEv, objAddr: 0x00000000000000A0, binAddr: 0x0000000100000B10, size: 0x00000009 }
+      - { sym: __ZNKSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_E5firstEv, objAddr: 0x0000000000000090, binAddr: 0x0000000100000B00, size: 0x00000010 }
+      - { sym: __Z9PrintSizeRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000A70, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE15__get_long_sizeEv, objAddr: 0x0000000000000060, binAddr: 0x0000000100000AD0, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4sizeEv, objAddr: 0x0000000000000020, binAddr: 0x0000000100000A90, size: 0x00000030 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16__get_short_sizeEv, objAddr: 0x0000000000000070, binAddr: 0x0000000100000AE0, size: 0x00000020 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__is_longEv, objAddr: 0x0000000000000050, binAddr: 0x0000000100000AC0, size: 0x00000010 }
+  - filename:        'Inputs/String/foo2.o'
+    timestamp:       1638904723
+    symbols:
+      - { sym: __ZNSt3__112__to_addressIKcEEPT_S3_, objAddr: 0x00000000000000E0, binAddr: 0x0000000100000BD0, size: 0x00000010 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000016C, binAddr: 0x0000000100000F24, size: 0x00000000 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE18__get_long_pointerEv, objAddr: 0x0000000000000120, binAddr: 0x0000000100000C10, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE19__get_short_pointerEv, objAddr: 0x0000000000000130, binAddr: 0x0000000100000C20, size: 0x00000020 }
+      - { sym: __ZNSt3__114pointer_traitsIPKcE10pointer_toERS1_, objAddr: 0x0000000000000150, binAddr: 0x0000000100000C40, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEpLEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000B90, size: 0x00000010 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4dataEv, objAddr: 0x00000000000000C0, binAddr: 0x0000000100000BB0, size: 0x00000020 }
+      - { sym: __Z14PrintNewStringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE, objAddr: 0x0000000000000000, binAddr: 0x0000000100000B20, size: 0x00000070 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5c_strEv, objAddr: 0x0000000000000080, binAddr: 0x0000000100000BA1, size: 0x00000010 }
+      - { sym: __ZNSt3__19addressofIKcEEPT_RS2_, objAddr: 0x0000000000000160, binAddr: 0x0000000100000C50, size: 0x00000009 }
+      - { sym: __ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13__get_pointerEv, objAddr: 0x00000000000000F0, binAddr: 0x0000000100000BE0, size: 0x00000030 }
+  - filename:        'Inputs/String/foo3.o'
+    timestamp:       1638904727
+    symbols:
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC2INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000130, binAddr: 0x0000000100000D40, size: 0x00000040 }
+      - { sym: __ZNSt3__117__compressed_pairINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repES5_EC1INS_18__default_init_tagESA_EEOT_OT0_, objAddr: 0x0000000000000110, binAddr: 0x0000000100000D20, size: 0x00000010 }
+      - { sym: __ZNSt3__111char_traitsIcE6lengthEPKc, objAddr: 0x0000000000000120, binAddr: 0x0000000100000D50, size: 0x00000010 }
+      - { sym: __ZNSt3__116__non_trivial_ifILb1ENS_9allocatorIcEEEC2Ev, objAddr: 0x00000000000001B0, binAddr: 0x0000000100000DC0, size: 0x00000010 }
+      - { sym: __ZNSt3__17forwardINS_18__default_init_tagEEEOT_RNS_16remove_referenceIS2_E4typeE, objAddr: 0x0000000000000170, binAddr: 0x0000000100000D80, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5__repELi0ELb0EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000180, binAddr: 0x0000000100000D90, size: 0x00000010 }
+      - { sym: __ZNSt3__122__compressed_pair_elemINS_9allocatorIcEELi1ELb1EEC2ENS_18__default_init_tagE, objAddr: 0x0000000000000190, binAddr: 0x0000000100000DA0, size: 0x00000010 }
+      - { sym: __ZNSt3__19allocatorIcEC2Ev, objAddr: 0x00000000000001A0, binAddr: 0x0000000100000DB0, size: 0x00000010 }
+      - { sym: __Z15PrintNewString2PKc, objAddr: 0x0000000000000000, binAddr: 0x0000000100000C60, size: 0x00000070 }
+      - { sym: GCC_except_table0, objAddr: 0x000000000000026C, binAddr: 0x0000000100000F34, size: 0x00000000 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1IDnEEPKc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000CD0, size: 0x00000010 }
+      - { sym: __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2IDnEEPKc, objAddr: 0x00000000000000D0, binAddr: 0x0000000100000CE0, size: 0x00000040 }
+  - filename:        'Inputs/String/main.o'
+    timestamp:       1638904734
+    symbols:
+      - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000DD0, size: 0x00000090 }
+      - { sym: GCC_except_table0, objAddr: 0x0000000000000188, binAddr: 0x0000000100000F44, size: 0x00000000 }
+...
+
+VERIFY: Verifying .debug_abbrev...
+VERIFY: Verifying .debug_info Unit Header Chain...
+VERIFY: Verifying .debug_types Unit Header Chain...
+VERIFY: Verifying .apple_names...
+VERIFY: Verifying .apple_types...
+VERIFY: Verifying .apple_namespaces...
+VERIFY: Verifying .apple_objc...
+VERIFY: No errors.
+
+CHECK: .debug_info contents:
+CHECK: Compile Unit:
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+CHECK:DW_TAG_base_type
+
+CHECK: 0x[[BASE_INT:[0-9a-f]*]]: DW_TAG_base_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"int"
+
+CHECK:DW_TAG_class_type
+
+CHECK: 0x[[BASIC_STRING:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_calling_convention{{.*}}{{.*[[:space:]].*}}DW_AT_name{{.*}}"basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"
+
+CHECK:DW_TAG_typedef
+
+CHECK: 0x[[STRING:[0-9a-f]*]]: DW_TAG_typedef{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[BASIC_STRING]] "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"){{.*[[:space:]].*}}DW_AT_name{{.*}}"string"
+
+CHECK:DW_TAG_reference_type
+
+CHECK: 0x[[CONST_STR_REF:[0-9a-f]*]]: DW_TAG_reference_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[CONST_STRING:[0-9a-f]*]] "const string"
+
+CHECK:DW_TAG_const_type
+
+CHECK: 0x[[CONST_STRING]]: DW_TAG_const_type{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[STRING]] "string"
+
+
+CHECK: Compile Unit:
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name{{.*}}"foo1.cpp"
+CHECK: DW_TAG_subprogram
+CHECK: DW_AT_low_pc
+CHECK: DW_AT_high_pc
+CHECK: DW_AT_name{{.*}}"PrintSize"
+CHECK: DW_TAG_formal_parameter
+CHECK: DW_AT_name{{.*}}"String"
+CHECK: DW_AT_type{{.*}}0x00000000[[CONST_STR_REF]] "const string &"
+
+CHECK: Compile Unit:
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name{{.*}}"foo2.cpp"
+CHECK: DW_TAG_subprogram
+CHECK: DW_AT_low_pc
+CHECK: DW_AT_high_pc
+CHECK: DW_AT_name{{.*}}"PrintNewString"
+CHECK: DW_TAG_formal_parameter
+CHECK: DW_AT_name{{.*}}"String"
+
+CHECK: Compile Unit:
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name{{.*}}"foo3.cpp"
+CHECK: DW_TAG_subprogram
+CHECK: DW_AT_low_pc
+CHECK: DW_AT_high_pc
+CHECK: DW_AT_name{{.*}}"PrintNewString2"
+CHECK: DW_TAG_formal_parameter
+CHECK: DW_AT_name{{.*}}"String"
+
+CHECK: Compile Unit:
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name{{.*}}"main.cpp"
+CHECK: DW_TAG_subprogram
+CHECK: DW_AT_low_pc
+CHECK: DW_AT_high_pc
+CHECK: DW_AT_name{{.*}}"main"
+CHECK: DW_AT_type{{.*}}0x00000000[[BASE_INT]] "int"
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-template-parameters.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-template-parameters.test
new file mode 100644
index 000000000000000..67b5616ebd5922e
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-template-parameters.test
@@ -0,0 +1,201 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o - | llvm-dwarfdump -a - | FileCheck %s
+
+## This test checks debug info for the template parameters of the class.
+## (i.e. number of the parameters is correct, names of the parameters
+## are correct, types of the parameters are correct)
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: 0x0000000b: DW_TAG_compile_unit
+# CHECK: DW_AT_producer{{.*}}"llvm DWARFLinkerParallel library version
+# CHECK: DW_AT_language{{.*}}DW_LANG_C_plus_plus
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+# CHECK: 0x[[CHAR:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"char"
+# CHECK: 0x[[FLOAT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"float"
+# CHECK: 0x[[INT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"int"
+# CHECK: 0x[[CLASS:[0-9a-f]*]]: DW_TAG_class_type
+# CHECK: DW_AT_name{{.*}}"parametrized-class"
+# CHECK: DW_TAG_template_type_parameter
+# CHECK: DW_AT_type{{.*}}(0x[[INT]] "int"
+# CHECK: DW_AT_name{{.*}}"Type1"
+# CHECK: DW_AT_type{{.*}}(0x[[CHAR]] "char"
+# CHECK: DW_AT_name{{.*}}"Type2"
+# CHECK: DW_AT_type{{.*}}(0x[[FLOAT]] "float"
+# CHECK: DW_AT_name{{.*}}"Type3"
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_type      (0x00000000[[CLASS]]
+
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x37
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x7B
+        offset:    0x000003B7
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x000001FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          false
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           1
+    stroff:          0x710
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_template_type_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_template_value_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+        - AbbrCode: 2
+          Values:
+            - CStr: parametrized-class
+        - AbbrCode: 3
+          Values:
+            - Value:  0x0000005B
+            - CStr: Type1
+        - AbbrCode: 3
+          Values:
+            - Value:  0x00000060
+            - CStr: Type2
+        - AbbrCode: 4
+          Values:
+            - Value:  0x0000005B
+            - CStr: Type1
+            - Value:  0x0FE
+        - AbbrCode: 3
+          Values:
+            - Value:  0x00000066
+            - CStr: Type3
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: int
+        - AbbrCode: 5
+          Values:
+            - CStr: char
+        - AbbrCode: 5
+          Values:
+            - CStr: float
+        - AbbrCode: 6
+          Values:
+            - CStr: var
+            - Value:  0x000000FF
+            - Value:  0x00000016
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-two-units-in-single-file.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-two-units-in-single-file.test
new file mode 100644
index 000000000000000..5bc034b54df8300
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-two-units-in-single-file.test
@@ -0,0 +1,205 @@
+## This test checks debug info for the types located into the
+## different compilation units from the single object file.
+## Type definition for the "class1" should be moved to the
+## artificial type unit from the first and second compilation unit.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker llvm -y %t2.map -f -o - | llvm-dwarfdump -a - | FileCheck %s
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+# CHECK: 0x[[CLASS1:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"class1"
+
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+# CHECK-NOT: DW_TAG_class_type
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_const_value
+# CHECK: DW_AT_type (0x00000000[[CLASS1]]
+
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU2"
+# CHECK-NOT: DW_TAG_class_type
+# CHECK-NOT: "class1"
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_const_value
+# CHECK: DW_AT_type (0x00000000[[CLASS1]]
+
+
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x3c
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x62
+        offset:    0x00000410
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x1FC
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          true
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           2
+    stroff:          0x720
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref4
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref4
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 2
+          Values:
+            - CStr: class1
+        - AbbrCode: 3
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x0000001a
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - CStr: class1
+        - AbbrCode: 3
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x0000001a
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-types-in-subprogram1.test b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-types-in-subprogram1.test
new file mode 100644
index 000000000000000..1af38080c705fb7
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-types-in-subprogram1.test
@@ -0,0 +1,431 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: echo '---' > %t2.map
+# RUN: echo "triple:          'x86_64-apple-darwin'" >> %t2.map
+# RUN: echo 'objects:'  >> %t2.map
+# RUN: echo " -  filename: '%t.o'" >> %t2.map
+# RUN: echo '    symbols:' >> %t2.map
+# RUN: echo '      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }' >> %t2.map
+# RUN: echo '...' >> %t2.map
+# RUN: dsymutil --linker=llvm -y %t2.map -f -o - | llvm-dwarfdump -a - | FileCheck %s
+
+## This test checks debug info for the types located into the subprograms.
+## Subprogram "float foo(int)" contains type "clas1". First compile unit
+## contains partially defined class "Container" which has parametrized
+## subprogram "ParametrizedFunc" which template parameter is the type
+## "clas1" defined in the subprogram "foo". The second compilation unit
+## contains partially defined class "Container" which has parametrized
+## subprogram "ParametrizedFunc" which template parameter is the type
+## "int". The type table in the final debug info should contain class
+## "Container" which has two "ParametrizedFunc"(one has template parameter
+## "clas1" and another has template parameter "int").
+
+## class Container {
+##   template<T> void ParametrizedFunc ();
+## };
+##
+## CU1:
+##
+## int foo (float) {
+##   class clas1 {
+##     char first;
+##     float second;
+##   } clas1;
+## };
+##
+## class Container {
+##   template<foo:clas1> void ParametrizedFunc ();
+## };
+##
+## CU2:
+##
+## class Container {
+##   template<int> void ParametrizedFunc ();
+## };
+##
+##
+## The final type table :
+##
+## class Container {
+##   template<int> void ParametrizedFunc ();
+## };
+##
+## CU1:
+##
+## int foo (float) {
+##   class clas1 {
+##     char first;
+##     float second;
+##   } clas1;
+## };
+##
+## class Container {
+##   template<foo:clas1> void ParametrizedFunc ();
+## };
+##
+##
+
+
+# CHECK: file format Mach-O 64-bit x86-64
+# CHECK: .debug_info contents:
+# CHECK: Compile Unit:
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"__artificial_type_unit"
+
+# CHECK: 0x[[CHAR:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"char"
+
+# CHECK: 0x[[FLOAT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"float"
+
+# CHECK: 0x[[INT:[0-9a-f]*]]: DW_TAG_base_type
+# CHECK: DW_AT_name{{.*}}"int"
+
+# CHECK: 0x[[CONTAINER:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"Container"
+
+# CHECK: DW_TAG_subprogram{{.*[[:space:]].*}}DW_AT_name{{.*}}"ParametrizedFunc"
+# CHECK: DW_AT_type{{.*}}[[INT]] "int"
+# CHECK: DW_TAG_template_type_parameter{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INT]] "int"
+
+# CHECK: DW_TAG_subprogram{{.*[[:space:]].*}}DW_AT_name{{.*}}"ParametrizedFunc"
+# CHECK: DW_AT_type{{.*}}[[INT]] "int"
+# CHECK: DW_TAG_template_type_parameter{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INNER_CLASS:[0-9a-f]*]] "clas1"
+
+# CHECK: 0x[[GLOBAL_CLASS:[0-9a-f]*]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"clas1"
+
+# CHECK: DW_TAG_member{{.*[[:space:]].*}}DW_AT_name{{.*}}"first"
+
+# CHECK: DW_AT_type{{.*}}[[FLOAT]] "float"
+
+# CHECK: DW_TAG_subprogram{{.*[[:space:]].*}}DW_AT_name{{.*}}"foo"
+# CHECK: DW_AT_type{{.*}}[[FLOAT]] "float"
+# CHECK: DW_TAG_formal_parameter{{.*[[:space:]].*}}DW_AT_type{{.*}}0x[[INT]] "int"
+
+# CHECK: 0x[[INNER_CLASS]]: DW_TAG_class_type{{.*[[:space:]].*}}DW_AT_name{{.*}}"clas1"
+# CHECK: DW_TAG_member{{.*[[:space:]].*}}DW_AT_name{{.*}}"first"
+# CHECK: DW_AT_type{{.*}}[[CHAR]] "char"
+# CHECK: DW_TAG_member{{.*[[:space:]].*}}DW_AT_name{{.*}}"second"
+# CHECK: DW_AT_type{{.*}}[[FLOAT]] "float"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU1"
+
+# CHECK: DW_TAG_subprogram{{.*[[:space:]].*}}DW_AT_name{{.*}}"foo"
+# CHECK: DW_AT_type{{.*}}[[FLOAT]] "float"
+# CHECK: DW_AT_low_pc
+# CHECK: DW_AT_high_pc
+# CHECK: DW_TAG_formal_parameter{{.*[[:space:]].*}}DW_AT_type{{.*}}[[INT]] "int"
+
+# CHECK-NOT: DW_TAG_class_type
+# CHECK-NOT: DW_TAG_member
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[GLOBAL_CLASS]] "clas1"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var2"
+# CHECK: DW_AT_type{{.*}}0x00000000[[CONTAINER]] "Container"
+
+# CHECK: DW_TAG_compile_unit
+# CHECK: DW_AT_name{{.*}}"CU2"
+
+# CHECK: DW_TAG_variable
+# CHECK: DW_AT_name{{.*}}"var1"
+# CHECK: DW_AT_type{{.*}}0x00000000[[CONTAINER]] "Container"
+
+
+--- !mach-o
+FileHeader:
+  magic:      0xFEEDFACF
+  cputype:    0x01000007
+  cpusubtype: 0x00000003
+  filetype:   0x00000001
+  ncmds:      2
+  sizeofcmds: 376
+  flags:      0x00002000
+  reserved:   0x00000000
+LoadCommands:
+  - cmd:      LC_SEGMENT_64
+    cmdsize:  232
+    segname:  ''
+    vmaddr:   0x00
+    vmsize:   0x300
+    fileoff:  0x300
+    filesize: 0x300
+    maxprot:  7
+    initprot: 7
+    nsects:   2
+    flags:    0
+    Sections:
+      - sectname:  __debug_abbrev
+        segname:   __DWARF
+        addr:      0x000000000000000F
+        size:      0x90
+        offset:    0x00000380
+        align:     0
+        reloff:    0x00000000
+        nreloc:    0
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+      - sectname:  __debug_info
+        segname:   __DWARF
+        addr:      0x000000000000100
+        size:      0x124
+        offset:    0x00000410
+        align:     0
+        reloff:    0x00000600
+        nreloc:    1
+        flags:     0x02000000
+        reserved1: 0x00000000
+        reserved2: 0x00000000
+        reserved3: 0x00000000
+        relocations:
+          - address:         0x2C
+            symbolnum:       1
+            pcrel:           true
+            length:          3
+            extern:          true
+            type:            0
+            scattered:       false
+            value:           0
+  - cmd:             LC_SYMTAB
+    cmdsize:         24
+    symoff:          0x700
+    nsyms:           2
+    stroff:          0x720
+    strsize:         10
+LinkEditData:
+  NameList:
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+    - n_strx:          1
+      n_type:          0x0F
+      n_sect:          1
+      n_desc:          0
+      n_value:         0
+  StringTable:
+    - ''
+    - '__Z3foov'
+    - ''
+DWARF:
+  debug_abbrev:
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_subprogram
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_linkage_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+          - Attribute: DW_AT_low_pc
+            Form:      DW_FORM_addr
+          - Attribute: DW_AT_high_pc
+            Form:      DW_FORM_data4
+      - Tag:      DW_TAG_formal_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_member
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_subprogram
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_template_type_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_pointer_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+    - Table:
+      - Tag:      DW_TAG_compile_unit
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_producer
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_language
+            Form:      DW_FORM_data2
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_class_type
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_subprogram
+        Children: DW_CHILDREN_yes
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_template_type_parameter
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+      - Tag:      DW_TAG_base_type
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+      - Tag:      DW_TAG_variable
+        Children: DW_CHILDREN_no
+        Attributes:
+          - Attribute: DW_AT_name
+            Form:      DW_FORM_string
+          - Attribute: DW_AT_const_value
+            Form:      DW_FORM_data4
+          - Attribute: DW_AT_type
+            Form:      DW_FORM_ref_addr
+  debug_info:
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU1
+        - AbbrCode: 2
+          Values:
+            - CStr: foo
+            - CStr: __Z3foov
+            - Value:  0x000000a3
+            - Value:  0x00010000
+            - Value:  0x00000010
+        - AbbrCode: 3
+          Values:
+            - Value:  0x00000098
+        - AbbrCode: 4
+          Values:
+            - CStr: clas1
+        - AbbrCode: 5
+          Values:
+            - CStr: first
+            - Value:  0x0000009d
+        - AbbrCode: 5
+          Values:
+            - CStr: second
+            - Value:  0x000000a3
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 4
+          Values:
+            - CStr: clas1
+        - AbbrCode: 5
+          Values:
+            - CStr: first
+            - Value:  0x000000a3
+        - AbbrCode: 0
+        - AbbrCode: 4
+          Values:
+            - CStr: Container
+        - AbbrCode: 6
+          Values:
+            - CStr: ParametrizedFunc
+            - Value:  0x00000098
+        - AbbrCode: 7
+          Values:
+            - Value:  0x0000003d
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 8
+          Values:
+            - CStr: int
+        - AbbrCode: 8
+          Values:
+            - CStr: char
+        - AbbrCode: 8
+          Values:
+            - CStr: float
+        - AbbrCode: 10
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x0000005d
+        - AbbrCode: 10
+          Values:
+            - CStr: var2
+            - Value:  0x00000000
+            - Value:  0x00000070
+        - AbbrCode: 0
+    - Version: 4
+      Entries:
+        - AbbrCode: 1
+          Values:
+            - CStr: by_hand
+            - Value:  0x04
+            - CStr: CU2
+        - AbbrCode: 2
+          Values:
+            - CStr: Container
+        - AbbrCode: 3
+          Values:
+            - CStr: ParametrizedFunc
+            - Value:  0x00000109
+        - AbbrCode: 4
+          Values:
+            - Value:  0x00000109
+        - AbbrCode: 0
+        - AbbrCode: 0
+        - AbbrCode: 5
+          Values:
+            - CStr: int
+        - AbbrCode: 5
+          Values:
+            - CStr: float
+        - AbbrCode: 6
+          Values:
+            - CStr: var1
+            - Value:  0x00000000
+            - Value:  0x000000e1
+        - AbbrCode: 0
+...
diff --git a/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-uniquing.cpp b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-uniquing.cpp
new file mode 100644
index 000000000000000..c7cb663d42febb9
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/DWARFLinkerParallel/odr-uniquing.cpp
@@ -0,0 +1,475 @@
+/* Compile with:
+   clang -g -c  odr-uniquing.cpp -o odr-uniquing/1.o
+   cp odr-uniquing/1.o odr-uniquing/2.o
+   The aim of these test is to check that all the 'type types' that
+   should be uniqued through the ODR really are.
+
+   The resulting object file is linked against itself using a fake
+   debug map. The end result is:
+    - with ODR uniquing: all types in second and third CUs should point back
+   to the types of the first CU(except types from anonymous namespace).
+    - without ODR uniquing: all types are re-emited in the second CU.
+ */
+
+/* Check by llvm-dwarfdump --verify */
+// RUN: dsymutil --linker=llvm -f -oso-prepend-path=%p/../../Inputs/odr-uniquing \
+// RUN: -y %p/../dummy-debug-map.map -o - | llvm-dwarfdump --verify - | \
+// RUN: FileCheck -check-prefixes=VERIFY %s
+// RUN: dsymutil --linker=llvm -f -oso-prepend-path=%p/../../Inputs/odr-uniquing \
+// RUN: -y %p/../dummy-debug-map.map -no-odr -o - | llvm-dwarfdump --verify - | \
+// RUN: FileCheck -check-prefixes=VERIFY %s
+
+/* Check for llvm-dwarfdump -a output */
+// RUN: dsymutil --linker=llvm -f -oso-prepend-path=%p/../../Inputs/odr-uniquing \
+// RUN: -y %p/../dummy-debug-map.map -o - | llvm-dwarfdump -v -a - | \
+// RUN: FileCheck -check-prefixes=CHECK %s
+// RUN: dsymutil --linker=llvm -f -oso-prepend-path=%p/../../Inputs/odr-uniquing \
+// RUN: -y %p/../dummy-debug-map.map -no-odr -o - | llvm-dwarfdump -v -a - | \
+// RUN: FileCheck -check-prefixes=CHECK-NOODR %s
+
+struct S {
+  struct Nested {};
+};
+
+namespace N {
+class C {};
+} // namespace N
+
+union U {
+  class C {
+  } C;
+  struct S {
+  } S;
+};
+
+typedef S AliasForS;
+
+namespace {
+class AnonC {};
+} // namespace
+
+// This function is only here to hold objects that refer to the above types.
+void foo() {
+  AliasForS s;
+  S::Nested n;
+  N::C nc;
+  AnonC ac;
+  U u;
+}
+
+// VERIFY: Verifying .debug_abbrev...
+// VERIFY: Verifying .debug_info Unit Header Chain...
+// VERIFY: Verifying .debug_types Unit Header Chain...
+// VERIFY: Verifying .apple_names...
+// VERIFY: Verifying .apple_types...
+// VERIFY: Verifying .apple_namespaces...
+// VERIFY: Verifying .apple_objc...
+// VERIFY: No errors.
+
+// The first compile unit contains all the types:
+// CHECK: .debug_info contents
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_language{{.*}} (DW_LANG_C_plus_plus)
+// CHECK: DW_AT_name{{.*}}"__artificial_type_unit")
+// CHECK: DW_AT_stmt_list{{.*}}(0x[[LINE_TABLE_OFF1:[0-9a-f]*]])
+
+// CHECK:0x[[N_NAMESPACE:[0-9a-f]*]]:{{.*}}DW_TAG_namespace
+// CHECK:DW_AT_name{{.*}}"N"
+
+// CHECK:0x[[C_CLASS:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
+// CHECK:DW_AT_name{{.*}}"C"
+// CHECK:DW_AT_byte_size [DW_FORM_data1] (0x01)
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (35)
+
+// CHECK:0x[[S_STRUCTURE:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
+// CHECK:DW_AT_name{{.*}}"S"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (22)
+
+// CHECK:0x[[S_STRUCTURE_NESTED:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
+// CHECK:DW_AT_name{{.*}}"Nested"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp")
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1]       (23)
+
+// CHECK:0x[[TYPEDEF_ALIASFORS:[0-9a-f]*]]:{{.*}}DW_TAG_typedef
+// CHECK:DW_AT_name{{.*}}"AliasForS"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (58)
+
+// CHECK:0x[[U_UNION:[0-9a-f]*]]:{{.*}}DW_TAG_union_type
+// CHECK:DW_AT_name{{.*}}"U"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (45)
+
+// CHECK:0x[[U_C_CLASS:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
+// CHECK:DW_AT_name{{.*}}"C"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (46)
+
+// CHECK:0x[[U_C_MEMBER:[0-9a-f]*]]:{{.*}}DW_TAG_member
+// CHECK:DW_AT_name{{.*}}"C"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (46)
+
+// CHECK:0x[[U_S_MEMBER:[0-9a-f]*]]:{{.*}}DW_TAG_member
+// CHECK:DW_AT_name{{.*}}"S"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (47)
+
+// CHECK:0x[[U_S_STRUCT:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
+// CHECK:DW_AT_name{{.*}}"S"
+// CHECK-DAG:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK-DAG:DW_AT_decl_line [DW_FORM_data1] (47)
+
+// The second compile unit contains subprogram and its variables:
+// CHECK:DW_TAG_compile_unit
+// CHECK:DW_AT_name{{.*}}"odr-uniquing.cpp"
+// CHECK-NEXT: DW_AT_stmt_list{{.*}}(0x[[LINE_TABLE_OFF2:[0-9a-f]*]])
+
+// CHECK:DW_TAG_subprogram
+// CHECK:DW_AT_low_pc
+// CHECK:DW_AT_high_pc
+// CHECK:DW_AT_frame_base
+// CHECK:DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK:DW_AT_name{{.*}}"foo"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (74)
+// CHECK:DW_AT_external
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"s"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (75)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[TYPEDEF_ALIASFORS]] "AliasForS
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"n"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (76)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[S_STRUCTURE_NESTED]] "S::Neste
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"nc"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (77)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[C_CLASS]] "N::C"
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"ac"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (78)
+// CHECK:DW_AT_type [DW_FORM_ref4]{{.*}} {0x[[ANON_CLASS1:[0-9a-f]*]]} "(anonymous namespace)::AnonC")
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"u"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (79)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[U_UNION]] "U"
+
+// CHECK:0x[[ANON_NAMESPACE1:[0-9a-f]*]]:{{.*}}DW_TAG_namespace
+// CHECK-NEXT:DW_AT_decl_file{{.*}}"{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp"
+
+// CHECK:0x[[ANON_CLASS1]]:{{.*}}DW_TAG_class_type
+// CHECK:DW_AT_name{{.*}}"AnonC"
+// CHECK:DW_AT_byte_size [DW_FORM_data1] (0x01)
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (65)
+
+// The third compile unit contains subprogram and its variables:
+// CHECK:DW_TAG_compile_unit
+// CHECK:DW_AT_name{{.*}}"odr-uniquing.cpp"
+// CHECK-NEXT:DW_AT_stmt_list{{.*}}(0x[[LINE_TABLE_OFF3:[0-9a-f]*]])
+
+// CHECK:DW_TAG_subprogram
+// CHECK:DW_AT_low_pc
+// CHECK:DW_AT_high_pc
+// CHECK:DW_AT_frame_base
+// CHECK:DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK:DW_AT_name{{.*}}"foo"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (74)
+// CHECK:DW_AT_external
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"s"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (75)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[TYPEDEF_ALIASFORS]] "AliasForS
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"n"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (76)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[S_STRUCTURE_NESTED]] "S::Neste
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"nc"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (77)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[C_CLASS]] "N::C"
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"ac"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (78)
+// CHECK:DW_AT_type [DW_FORM_ref4]{{.*}} {0x[[ANON_CLASS2:[0-9a-f]*]]} "(anonymous namespace)::AnonC")
+
+// CHECK:DW_TAG_variable
+// CHECK:DW_AT_name{{.*}}"u"
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (79)
+// CHECK:DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[U_UNION]] "U"
+
+// CHECK:0x[[ANON_NAMESPACE2:[0-9a-f]*]]:{{.*}}DW_TAG_namespace
+// CHECK-NEXT:DW_AT_decl_file{{.*}}"{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp"
+
+// CHECK:0x[[ANON_CLASS2]]:{{.*}}DW_TAG_class_type
+// CHECK:DW_AT_name{{.*}}"AnonC"
+// CHECK:DW_AT_byte_size [DW_FORM_data1] (0x01)
+// CHECK:DW_AT_decl_file [DW_FORM_data1] ("{{[\\/]}}tmp{{[\\/]}}odr-uniquing.cpp
+// CHECK:DW_AT_decl_line [DW_FORM_data1] (65)
+
+// CHECK:.debug_aranges contents
+
+// CHECK:debug_line[0x[[LINE_TABLE_OFF1]]]
+
+// CHECK:debug_line[0x[[LINE_TABLE_OFF2]]]
+
+// CHECK:debug_line[0x[[LINE_TABLE_OFF3]]]
+
+// CHECK:.debug_str contents:
+// CHECK:0x00000000: ""
+// CHECK:0x00000001: "clang version 3.8.0 (trunk 244290) (llvm/trunk 244270)"
+// CHECK:0x00000038: "odr-uniquing.cpp"
+// CHECK:0x00000049: "/tmp"
+// CHECK:0x0000004e: "_Z3foov"
+// CHECK:0x00000056: "foo"
+// CHECK:0x0000005a: "s"
+// CHECK:0x0000005c: "n"
+// CHECK:0x0000005e: "nc"
+// CHECK:0x00000061: "ac"
+// CHECK:0x00000064: "u"
+// CHECK:0x00000066: "AnonC"
+// CHECK:0x0000006c: "(anonymous namespace)"
+// CHECK:0x00000082: "llvm DWARFLinkerParallel library version "
+// CHECK:0x000000ac: "__artificial_type_unit"
+// CHECK:0x000000c3: ""
+// CHECK:0x000000c4: "AliasForS"
+// CHECK:0x000000ce: "C"
+// CHECK:0x000000d0: "N"
+// CHECK:0x000000d2: "Nested"
+// CHECK:0x000000d9: "S"
+// CHECK:0x000000db: "U"
+
+
+// CHECK:.apple_names
+// CHECK: Bucket count: 2
+// CHECK: String: {{.*}} "foo"
+// CHECK: String: {{.*}} "_Z3foov"
+
+// CHECK:.apple_types
+// CHECK: Bucket count: 6
+// CHECK: String: {{.*}} "AnonC"
+// CHECK: String: {{.*}} "Nested"
+// CHECK: String: {{.*}} "S"
+// CHECK: String: {{.*}} "C"
+// CHECK: String: {{.*}} "U"
+// CHECK: String: {{.*}} "AliasForS"
+
+// CHECK:.apple_namespaces
+// CHECK: Bucket count: 2
+// CHECK: String: {{.*}} "(anonymous namespace)"
+// CHECK: String: {{.*}} "N"
+
+// CHECK:.apple_objc
+// CHECK:Bucket count: 1
+
+// CHECK-NOODR: .debug_info contents
+
+// CHECK-NOODR: DW_TAG_compile_unit
+// CHECK-NOODR: DW_AT_name{{.*}}"odr-uniquing.cpp"
+// CHECK-NOODR-NEXT: DW_AT_stmt_list{{.*}}(0x[[LINE_TABLE_OFF1:[0-9a-f]*]])
+// CHECK-NOODR: DW_AT_low_pc{{.*}}(0x{{0*}}[[LOW_PC1:[0-9a-f]*]])
+// CHECK-NOODR-NEXT: DW_AT_high_pc{{.*}}(0x{{0*}}[[HIGH_PC1:[0-9a-f]*]])
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"S"
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"Nested"
+
+// CHECK-NOODR: DW_TAG_namespace
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"N"
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"C"
+
+// CHECK-NOODR: DW_TAG_union_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"U"
+
+// CHECK-NOODR: DW_TAG_member
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"C"
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"C"
+
+// CHECK-NOODR: DW_TAG_member
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"S"
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"S"
+
+// CHECK-NOODR: DW_TAG_subprogram
+// CHECK-NOODR-NEXT: DW_AT_low_pc
+// CHECK-NOODR-NEXT: DW_AT_high_pc
+// CHECK-NOODR: DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK-NOODR-NEXT: DW_AT_name{{.*}}"foo"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"s"
+// CHECK-NOODR: DW_AT_type{{.*}}"AliasForS"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"n"
+// CHECK-NOODR: DW_AT_type{{.*}}"S::Nested"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"nc"
+// CHECK-NOODR: DW_AT_type{{.*}}"N::C"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"ac"
+// CHECK-NOODR: DW_AT_type{{.*}}"(anonymous namespace)::AnonC"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"u"
+// CHECK-NOODR: DW_AT_type{{.*}}"U"
+
+// CHECK-NOODR: DW_TAG_typedef
+// CHECK-NOODR: DW_AT_type{{.*}}"S"
+// CHECK-NOODR: DW_AT_name{{.*}}"AliasForS"
+
+// CHECK-NOODR: DW_TAG_namespace
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR: DW_AT_name{{.*}}"AnonC"
+
+// CHECK-NOODR: DW_TAG_compile_unit
+// CHECK-NOODR: DW_AT_name{{.*}}"odr-uniquing.cpp"
+// CHECK-NOODR-NEXT: DW_AT_stmt_list{{.*}}(0x[[LINE_TABLE_OFF2:[0-9a-f]*]])
+// CHECK-NOODR: DW_AT_low_pc
+// CHECK-NOODR: DW_AT_high_pc
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR: DW_AT_name{{.*}}"S"
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR: DW_AT_name{{.*}}"Nested"
+
+// CHECK-NOODR: DW_TAG_namespace
+// CHECK-NOODR: DW_AT_name{{.*}}"N"
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR: DW_AT_name{{.*}}"C"
+
+// CHECK-NOODR: DW_TAG_union_type
+// CHECK-NOODR: DW_AT_name{{.*}}"U"
+
+// CHECK-NOODR: DW_TAG_member
+// CHECK-NOODR: DW_AT_name{{.*}}"C"
+// CHECK-NOODR: DW_AT_type{{.*}}"U::C"
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR: DW_AT_name{{.*}}"C"
+
+// CHECK-NOODR: DW_TAG_member
+// CHECK-NOODR: DW_AT_name{{.*}}"S"
+// CHECK-NOODR: DW_AT_type{{.*}}"U::S"
+
+// CHECK-NOODR: DW_TAG_structure_type
+// CHECK-NOODR: DW_AT_name{{.*}}"S"
+
+// CHECK-NOODR: DW_TAG_subprogram
+// CHECK-NOODR: DW_AT_low_pc
+// CHECK-NOODR: DW_AT_high_pc
+// CHECK-NOODR: DW_AT_MIPS_linkage_name{{.*}}"_Z3foov"
+// CHECK-NOODR: DW_AT_name{{.*}}"foo"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"s"
+// CHECK-NOODR: DW_AT_type{{.*}}"AliasForS"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"n"
+// CHECK-NOODR: DW_AT_type{{.*}}"S::Nested"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"nc"
+// CHECK-NOODR: DW_AT_type{{.*}} "N::C"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"ac"
+// CHECK-NOODR: DW_AT_type{{.*}}"(anonymous namespace)::AnonC"
+
+// CHECK-NOODR: DW_TAG_variable
+// CHECK-NOODR: DW_AT_name{{.*}}"u"
+// CHECK-NOODR: DW_AT_type{{.*}}"U"
+
+// CHECK-NOODR: DW_TAG_typedef
+// CHECK-NOODR: DW_AT_type{{.*}}"S"
+// CHECK-NOODR: DW_AT_name{{.*}}"AliasForS"
+
+// CHECK-NOODR: DW_TAG_namespace
+
+// CHECK-NOODR: DW_TAG_class_type
+// CHECK-NOODR: DW_AT_name{{.*}}"AnonC"
+
+// CHECK-NOODR:.debug_aranges contents
+
+// CHECK-NOODR:debug_line[0x[[LINE_TABLE_OFF1]]]
+
+// CHECK-NOODR:debug_line[0x[[LINE_TABLE_OFF2]]]
+
+// CHECK-NOODR:.debug_str contents:
+// CHECK-NOODR:0x00000000: ""
+// CHECK-NOODR:0x00000001: "clang version 3.8.0 (trunk 244290) (llvm/trunk 244270)"
+// CHECK-NOODR:0x00000038: "odr-uniquing.cpp"
+// CHECK-NOODR:0x00000049: "/tmp"
+// CHECK-NOODR:0x0000004e: "S"
+// CHECK-NOODR:0x00000050: "Nested"
+// CHECK-NOODR:0x00000057: "N"
+// CHECK-NOODR:0x00000059: "C"
+// CHECK-NOODR:0x0000005b: "U"
+// CHECK-NOODR:0x0000005d: "_Z3foov"
+// CHECK-NOODR:0x00000065: "foo"
+// CHECK-NOODR:0x00000069: "s"
+// CHECK-NOODR:0x0000006b: "n"
+// CHECK-NOODR:0x0000006d: "nc"
+// CHECK-NOODR:0x00000070: "ac"
+// CHECK-NOODR:0x00000073: "u"
+// CHECK-NOODR:0x00000075: "AliasForS"
+// CHECK-NOODR:0x0000007f: "AnonC"
+// CHECK-NOODR:0x00000085: "(anonymous namespace)"
+
+// CHECK-NOODR: .apple_names
+// CHECK-NOODR: Bucket count: 2
+// CHECK-NOODR: String: {{.*}} "foo"
+// CHECK-NOODR: String: {{.*}} "_Z3foov"
+
+// CHECK-NOODR: .apple_types
+// CHECK-NOODR: Bucket count: 6
+// CHECK-NOODR: String: {{.*}} "AnonC"
+// CHECK-NOODR: String: {{.*}} "Nested"
+// CHECK-NOODR: String: {{.*}} "S"
+// CHECK-NOODR: String: {{.*}} "C"
+// CHECK-NOODR: String: {{.*}} "U"
+// CHECK-NOODR: String: {{.*}} "AliasForS"
+
+// CHECK-NOODR: .apple_namespaces
+// CHECK-NOODR: Bucket count: 2
+// CHECK-NOODR: String: {{.*}} "(anonymous namespace)"
+// CHECK-NOODR: String: {{.*}} "N"
+
+// CHECK-NOODR: .apple_objc
+// CHECK-NOODR:Bucket count: 1
diff --git a/llvm/test/tools/dsymutil/X86/Inputs/String/foo1.o b/llvm/test/tools/dsymutil/X86/Inputs/String/foo1.o
new file mode 100644
index 0000000000000000000000000000000000000000..a837de81a4f295dc6f3d8d625bfc7f508f311b3d
GIT binary patch
literal 47448
zcmcg#34B!5^}aL7z(9~>hJ-~BVgey-lVsQtku3_c$f}6aagt16AjyQ8NdidKx+^HC
zxZr}gW8L?yF0K9Bs at 1yGYOS?eE!Dczy49tv|L;5ZzBg|siQB}^FZZ2uzjN-n=dSO*
z_wIZ7?HBL;x4TlV9EAfyE<(8nhhhZ$1|aMq*vW79ty(aLY4Ee+u&Ee&6T~kRN=7y$
zHLv5#s#h#a#Vzi7!_XeH-FlZ&J&EP26G*IIC{&wB#-mNE4G;>Y+q3NWjr^a+KP$c4
zV(j#Fk(!p(As7`T6q<d+j3o!#S`Qem|8mXbbhAYklV&m$()Jo+wIa{7_q?$aV5Q?X
z at F-0k#}4g<Yii<=R at P^_f372R$_v?$_{}|9Q^&DGd(o!)7<Dr3U9?iCTzH_SuZ1*y
z1?}P0Y=`z5!?j{E)85_-bs|$-6}U{t9mfoN;pXOsNT?~?7)d}W)85~Vy*<WY#kaH<
zt63`zl4)<-PVLE1<Isz{9G+>mbN`ydwVC$rF!ro2|K+!|m)zLgVR?sNtex1nkEXH9
zzsbMaSR?#OhFY51qD^(7(EQoX6uYm}vDXav){RQB>kPVEk6W-A<&CTf)yL5qIzi at m
zJ7JH;D@}X+`X+5pqe|r|wZ`H}?eP(95{sGjcdHq|JIpxy>}H*M8T>O at r1=+wxIco(
z at _VXW1pcT*{Ai?OzkLOCGeG#G79sG*EEt%UbC$6W?%V&C&pG3-Z&7{DSqHM|=bZ6a
z)g!CkCXzn{HBb4{MRU&hQY)SD=Q$_+(tGkF$?ivKB}3}-hn&nbqA#jvs-dn`k8V%d
z-!k3njOX92<~;k>sz>VsR#H1ZZ5bv_{&UXwY}KPZi<ip0S)7P&iWCoPXi+mb(28pt
z!cD7-TO;vAG}csHRTZcVj4dt~bWBxM<ygjpf$@_^sQOr}Dp1?ptSXi#pk7ha5^bnU
zG=y6t72(zf%=3w41rMA{IYHONVht*htV5eushV&iT5BXzYuAM1ql+P$G6k|JQy32=
z<KbvBA+l*sVYmTvX*d~+Yf<qu*mGJ7p~E-Enx-b>EfL68E}XYCITmJvRUPWhonKQ`
zT^+2%iD^wd))s1rG_6jq2}R=ZSiHIww%fzs-Ds>O8H&}1;;7n)!>AKRPKh<Kcrw%&
zPOMXGlo00tWf#|~kW at 9<qEt<+T&N3MHNh5|baNLj4NbPexwX~R)ssv#QoUqpFw|&e
z6;aKxXj3v0hf9VNSK2j`ZOzV~4W~lOnk`dSBc<Ywx=ZtBVz{m at 9!Vssm((i5s(7S6
z5|1?1M!q at GyjoQoYeHYMT-UKQ3%X{~a!u7h<Dz-3rq)$M3?rbWDG^=W6saplRixaX
z+8T at 2Nw4a_T2*CT#IDjswT&tj?W_co8p9hxY;5!ji=}P{)+g3sEX89Rs~6S6u&^pL
zyIDyuNpGo8w6Xa+Hs0uBJznfK)x8g$(&~v*JMDO*i&<lqh0qKRP+f_vyU^@tef=_a
zWxHJ8r+2b_bfdBf>~_ZbPukrHN_Q+C`8AWq=;HctLxR)8BCPZ5PM(@^ibpycxoTXx
z#@t1<)m4=?7Gs}H#pq>SG>O?W+%Q$LaXMn_rRBwWuPK}yUCaT5oM*E60I1O1dW@$v
zktPg=8l1kTN@<HTdf~UK&$Qmj0nZ-#9h=1JqSZ_0!N7M+J$7Ou(h$K)B-X at 6ONMdE
zkArL8sM|2!Qp;L1w!f9`cl4kNv%Eb(WzIvd!n{~Dk at MZ^c(_4(5^hS)t&#IWHQK>S
zp*TYHuxO_~l_xiA1hj at 5TAXuM=jLl$YcTL*&5<}yXvK1dl+ at Pf!wJZm48CO}r~K8k
z`q!4Q5@!J=ee~<gWsMg5WZFrQU{4q6yL)YSt*>tn)A4YY)br-|s2?k7b>}&;UcOfs
zpNt9fTXpiz^Tuk#%KO{d`i at mFwhMf8)K7?Wzh1P2LUGIq7($KBJe5Z<ONXOz$9coK
zOl!BA_->0n&Y1B?vvX>-PhIwMq at 6Dzv`ym=>`-Ou<Py?j8Fd0zacp2fb+MAd&8#aq
zyMoq*lVOPy<1$d$>kqxA3N>tiXvUHyGmZ=`ox8F+wCu=5)gdO~GA$l%!?7(EuS<Yt
zG=LO3)k%WEjy1SItO`1tXl^Z`Do4X`*$6Cc4OLw|UdmTJKU!HmzXn|c at zs%}taCw`
zv$X{O-(@W;kGXZIv{~V%nUU(o=H$ki;RL4T4y(t}Co;Ox=;A7CUbiQ;udBlJx|tuX
zLY-hpr|RTe)yB85Vix)n+Z8D5hFm&6R6V{v8c(ndg*w`>>W9wIuH_#prwNG&muM)P
zX8s3-OJ(_kmu_65E!>P#|D=#2ht*>hLQpj|#}a8*-74CIRcg2a>-%`9A(}|)X;U5N
zoC2J6^S$PVTD`t<+6=WuBW-hQv4F&x&bj(=+!7ESj8&XW>owob!Z)8lcx%93J$*0l
z!%KN89v`xoXa{zI#lvVYd&ib0t0rVNA?D{Uu)GLY)7kr%wT<yLk=4;A^bnyciaQcq
zCG$iV$Jvu{=>z6k&75Pt=PAs}ORlfPcKf_|p($5r=~su}t7nak$P9!dt2!&+jj1eK
zY(m_s0?puplQ#h)sk+Dn9OujqnnVx2tO}NLNw-R-1MOVw%p+&RWj`s5!#ydUJxH={
zJj+<NonS(()qI-C-mzL;N|LONO{}$hm*KKDIlk63gV3zajWajlNU}CILEl71AJI(K
z2A#JFv+XI9aOr`EbIFZx&tmDISx<hi*=z!?_jnVtu@<Aks=_WYn5}0M;ZG#q3fJfv
zxoj=+If5=E9_`kLTN;ufo`#V at hj_Nx*#&Uk3i at 7+R5doS1`lG^g_5yQJsigR*BQ^&
z(ebqnkuV>b2&J{GCjapfUb4ZQ(5%fxH=u#68*N9e%C at j#F54mo!|XM@%bVTk({{2n
z(mX$7sXHp`wJuC{!BP at dvR+EU#t*byo`CHMJW=Y)1Rcq?J=1J9I&ac{uW at ggLtAvE
zt*$C1&KX&DUCzk5=G)K69pKq!XVvEq)T1Uhw<Ol!iFWNe^n07n*6B&jv1V<w70;?P
zo2||9^>IAL!4xf&*0P)NEpu6RhjCJOxNJlfX6=+^EK8pzgcE$6Y)umq$+r3}n_Y1~
z!LlXOSXWFry0~34<=D2ms>ZUPa;*CLf#v|**uh#As{?&n(Xp&cpJucR8ribfC9Ui*
z)@23lf_64;$%7EbU5>dZGoE#Jm8Tt>|DoOgfjaMa+^0+6f~!#plWiRta~)UF4{Chr
z<gD-0;_9urAzaJa&_mh8v-LaEZuX<uVX-U5bGo at MEN=FL!gj6WE`?UtO_k*-|C_VH
zGn%Xy<licnF01}dYwUl~Dqk~QWwq`c$1O<MRfjP|j+K>_y$Oky8f?$w1gN=etKWL0
zrym<-<=c4KbIY4F@`gjUMIFa|3$R9#b-h)M#cly>x0P(ZO^au3e_TB_(CHO;BOYsa
z!EJ4Ak<+D&<E&aHWvhz{sxS7l@@ahBS!EK*+BsvhYbwoQtg9UBf at -T8%WA_tR_vg_
zwr^*bv%#$0&CH~0Dzqc3UG8dERB=$MxFOuWh7Fdz*XdbwQT?_z+SQJBMeR;>bl|2~
zC!JUevUk6O%(|$uJF)zOxZD-hJ|WeqJE(Q(*j-iW?X&8lI`7zU_Ep~AZWq+}M0q(b
zju&8Lmyd~M?W}Fqy6Vezot0^@3)UO9Nwj-c7P#xpWxuwn!oJgJQ)@UL#m at c&)~n7a
z3!lxS>Z(cDfyqaop)gMR`jM(+kqKs9%h<RbO~?jfT?EZ%>p%8$%9dBLDO}c$I!$I-
zxf8et5U&u*t8sddfouzOLRtG;g<N>8;mC!3Bpu4Oo~y70m_?EO@@XZpk?aeiw;4O~
zu*#8^M^@b(@6bq#$bJv2EzGW&tPGEH)DJeM$c75L!T at AnJIH};Ds{me(kjQ~kW~>d
z71$n|H@*0}UVAj_&V-!oqF6bl6~}<tS6XK|={<QS8?zaguL^v_i+A>Gxmi^-roz<d
z%q+hi#$8qco#mC~%!YT8S%ggIyUgwO_Oo*sb0l_($7Ilu$+`>6J}NA^8o7T0Cwc6u
zGO=t;!&TXmWtOxO=}MbjWh?u;rtF)1YrSS8Za4DB)0PIZb&|U(j44^!q at H9jA6e#g
zB+oY6DooPy+=$!Mte)Wnvd#c?CNG`pNAhOzV{ZAkm;8X)@oxIpy?L75c&+NZoSkRP
z7yGg<F=n2|SZgF??Rmia4&RicGr|8hf4**+b&jZNM~SU2CGUB(7yNL!bzaLqY$-d>
zw=4QnP^NRdN*Tpt2K1_i2K$|a)U{kk!fY!#i0c?$HX7U33n&S^){0l-IMsG4#cPLH
z3N2HPcPGv3RjI4Zj2A1dEhS58m+)&ANN!#Nx2J)O1i{Gq>e^ZrS??%krb<JSDh<vp
zrWq>E`v6PFrah3%(6n~7n=5>?e#=lwJ;vbs^__b*j^hPuW1gZF`L9tm&*wz-8><h`
z at toT-GTfWU`)3i{laDIH;WfDAH&k?05T_!$L6FoL?cDFGD(G3(u~)<q`?^Gt^{GVB
zD4N%fcAjc1i-fJxF at 7yVzAT~iXE@{~rsib44&UGiCFK(%=+3K~!1F4oxGvUG(-2XO
zk;Ym)`2>-sz|%`cL7EK32X}N7l*;(N2$eKxvZApDe&8p*p+3%gHuEP?b4`4CcygpE
zjBG;D`nfCgXB8H;M$zmd7EK!KM6)(3S*?i+Ni;Vx!9*lzu8FVf&^9|2m8oDUe}j37
znZ%f%KsMR2=azNInIaim$AaLpPw|ned^d==&EORf_OVH*a`QzQb|pf%?Ep;P_C{=M
z5HZjR<E+M!76PJLaA0~;No2nqu2U12<Th at l$}pBDhYr4WgsF_C?TFa7W0q4|QLHhu
zRJv45J7x>DKXz1-GFI=%ki4BABX)L-q;j*;NM?2-JC at 4IPKKP&>rpPgS|7)U&p3!Q
z!ep8Q!*4<8devNAv=#C7EwLnC7im-tI^JL?MpL~qLk4^ld-w54D<1G>zx0JV-6inG
zltk-wv|iOW#PkS)uF;X9B1uKH#l%}+3*U)?k{oOG9l82=1fx{*as81Y6|UiT0&q&)
z5KSsMgsREnsxs1qdjW}!i6qKkNKFE_C~McK^$DiJ5E>h<No;_Tgldq39EqdM8#X8$
zrT9t;uNpCan{Z6V+G<sso(w^gvBnyp3Bn1)!62p%o;x3ls!&2x+_}M9oA^ROeM5LP
zK2T5}#gr4O!CVze)U<%$-Ch9ty`hGhdd<|vV(X%SYa3#eqSUO_NMxO=$E(cFrj5zm
z#<Q{RGk8A~=V}#dsZk+(Y%-3m3EGtvz~D)XWZERh2I$l at tkYS-5XW)7&a%F~0Xwnr
zl6aDuAg!eJ&3K0<37V)4Hvw)k at q|S+-fHQE at DT`ky*iW(uU4y@@jzH-Vskk8#nC_7
zLgDyogh&`&4<De!chq#O)nwJ0FsAK1Tdhp%(dM;^#{?W~0UsjKkpz1Lx02(~f)9{U
zQ`cs_t|*H@#Fxb39xE9ImRK^v9vR`s1NEytnAuc4Pc`^D7e11v at bwy!P(5C+X~I|G
zc*G|HBRXm*MiWo+cxR8F4oo&SOD6zDT>RslDE?c8l<GB=O5dp<Wok8GXywFcBHYl_
z(il~SLBAHPc}-YjU^G^P&)TgcCXB{vo09PcV!~*wF1i|T#RC&YWB4#o^BQ8pXbkNY
zi4zk>W8xPvVGP#Ngs&PABcrhd-oJ|w6Gme#c#TBt2?K0WG_k>UMsw7}grRdbjK)mr
zWK5?<TVYL;n)^%~!xeK%+R#Zs;P8#Ev{WgCbEeF);#Zqp>6+8tf;ZK!IfL32-)7Z3
zO4epqz2=OrUEVgU_Ni-Ezvhgt-2iP?3sBc?0?ip+se4v<o7D=`wVOe6M%QkLHmfBj
zLpRkFhBew!MbWi1Ei9)*{i(A_m=f)#O8E%XZY+}n=T2!DCT0W4gvv`DM-y_6wV)38
zNh)N}`50XI!%T at 4XJe=_+C;J at hKY~Sy6{G!F at ZPYoWN+Cfj1h8?w?3fu(}bayn1q*
zV)#I3y{=Xa{WdfGSwO2TYBjBZxzQ*=W({h?aHhg}M2McG7{lmpL#!=Y7vWR at h=`fA
zK;`sOr%AmgIGGCCV2GhOnF`F4DHtwdL1Zz at C{D!^)s(AOqCATWtmF17ma<OPrfqGK
z5^G1UNuk*3nzU`vJkhn+q)_g3O{&exniO^?Kov`b4wt%?S;(~uU$f+HYim?(X3fnq
zajgr=^Ez|TF)n9CiIqTQRvoC!-eh=!3_-s>8O20yGuFZ&8I$z at Z@;1&$MvECi)3j&
zP`z9bK-LQa$r(x(6{^+r5JRK`aOQ8dI+{fn at ie?tKX;mJN0!XX>RE2JTB^TQiu&Xy
zOOtD&{OGX$^)S?>%r~1Yfl|eW9g$M8*eN!&bh=?@q#(oD#QGHNk+w>^ypA!VXy+=;
zMzpbWmF-4kJ|~QC-L}hUw^1=)2&Rg~UT+(=95w(xn(K27>)pqb)4QPGz}~MPKfvem
z<D0tfp(>~Mw7figZZ~JLD+gZ#&m}p-H9#qk+chCCr*~f7l)MA*b?$D1)Z9LkpxAvM
zq?y}?=s^Rf4j7b=FZcF^ET^|t?2(dFy=R{^GkN<!m5P-0>Ia#X!9J;Uv>VK$<=z3f
zL-nZx4jKTrgGiO{fr)YOu%Ml=7O0P6rThU`Q*WJiZXZYLJ}KOR7N$^JTdATHYIK$A
zTOnmts$V4-`q;k$6 at pK(_W_v-2lk~Pr#D3dQ)QZzN8bl!xUAHEMjIcF9;~aFdPCgC
zSh1t}fbVa6lxKTXV%I(tN>d7sf(#8PQyF;<beLD6YV-P|w#xFQ(uS7_DK8K*q72<<
zq|3$X9JN27iO66yyG&l*G_Yf4idw*w$!WR*g;$m7zM%P(s$zMh$zdR9S5F?h!`J{!
z(<6tE<1FKLamQO)204wLbwUyHo0y?1l1WA4|73n;dWu#1jtma4Dp;wh+8w%bpxrYO
znHIq4 at pqfvf71Y~7Ns*Pb&yB7`&m9KHGPgczR!>Ged-xjin>0V1{{Lwo2eCbznw+3
z6X~`(6yI;p1;rSW&syiIN{J~o*-#RWYxglcxN`V8?p#hXp4>(p`@8;B(CyMfaNUoG
zg=<SO)c@{wc?(b>TLHMPc6T3-Z*7a<9k;8;3`Eu<Yga*z>gidD;`MiR%gH+j7F^yO
z)yvZ#q{lJ9A0gB;NA)-nk^eH1hsa%s%%|aA{2qBvPn}r!v%AMSFe|9_x?A;#TamxG
zy*)M|@*yQ}xC at l`GdSB5pZIp|arg9`DyjeJ&hydaM{eZr0+IB=p at 2Stu}h&eo$^nS
zOsq|&=rgxVd2c|0Ps3NiU01-`ePYd()8k<<^Qn^qC--?3ol(l)C&%@b^>g)p1F)+o
z$Cdw6XsQB<_BT=AEyTQA`m&y(cBNaZ53%I;QLeFKC#Dl>!B9)^Xi9ms6LTt0vjk6~
zL_SueF+aVXz;{~8-b_o%6h795NjAq4&{MIe5013++N(IEwU+dPl+lP2Gj4P*K>e&S
z0_874w2jcZoVVD@`M;*K-hzQjolE#~xBqvbgM8o{bDn}wH-JxS)L#Z%WGzmaRG`1n
zl5KFx#6AD7EZHWf>^bJ`-v|F?LTn!El(9!C|6<5?BDl8ZT!_A6I)k?e?p{v#9=HEz
zmdduA`$a{UXkVy!FtlCwy8QvrB>8ilR{R?*_<Uzd|HFX27zM7KIeEDtx&wNLz+gV%
z``!M<prUeVPC!(2o<pH>2~{3&``-qw#3*-N?zG|`4 at lrEohki42K*~(Uz_I2(}4P-
zle?}@g9ietCwya?ktRU*5WXc1eh`qSAK=?_WCGAl?(Yd`8R0wA;G+PYz<RtZ4ZaTW
zN7TOC3HSLopo9AZzTfJ4($S^y`YeDzgbz4{s?P<$Ut^*N)A6@}&EVYkP&$4DFwy_H
z!Bw9t0DVZ+M{P*$i~k#d;QBuc at -Ia6LPEdF8HwIxI=lZeKz||pcn<%uiH7x<_P&BH
z`4k7nb#DKAmfjON1F#x117QU$DevphJBNDLy8TsX_BI69Z`#@OZ?a at hwX@-W7_#nz
zknXq6j;{xrAGpZ=;FReBv%-?S?3C#NbEzeJ#VON+ at KeZU?T7qcbINpnhXNPb-!o;Y
z$w~QlT3R1Fwdj?uKL1}Wg-<dSl)rMY$>LL|jMeGW{bdsro=0$fp4R^Ux2=Q&a~%_s
zl&R00AxiB)a1G8i?W1k&0`@lXVuLIHhloxo2DE=}syUT^Iv{~da#OuQ`Og6S47E$s
zv|q5`p=sLt?T^zof~&&mqORKYmMrL$={fU3OE$qNV>)NG_bM^g4{~Zbs(po}Fg;U2
z`LD8MGn}$iwfo<*6b^SP=q at uKCzp#6Tq~V2NvsQZg{9Ecp at Op%|Fl$N?Nl8_nTE1U
zj?EovDgT+4!uoa!jzYa)X~lC>Ck`J^5W2JZ#|<<2B-<%C%<QnV&S<BlE2sw+;Y$!)
zXLaa}@~^NIwq;sS{<|#MIhiu?6ld$<N<|P{J36#(PRfmz)~?RAoDK1?rGH(=`i|D<
zU2YuM)48hhA8lz}-?5gXLa(<}Z*ZzgyU0QJs)7+F+j~0Ja(LKksovMQs`CHQ(t4m{
zEr*8(;Zz}Y{#eJVy4~-ER?aB2%oDjxYtA8iGX|~~8cV75o7 at 9ZT9O$Ls?SOYpXEaL
zx7PH<8BY1H2L2uszLd+dT4%10039$I at t4!!>4459{Ce&#S4w*~p!W#B>GaW_TreYA
z3hz4=?8-HB`m`~|%m*E6VXCwg{^?ZUJZvmH2ZiDQ9QoL(;Bcf2LQ(jyQz6rlgr%iC
zjykusl>cE%!R1tNIMSm+sbdgaxlRR#BTbe<Z>NHtg(=T3Ev<qMwUmEArOC(dRB$-b
z0EJ&5xQd(#4o7}#DGYHcWI8gm%9z=|LoMasU at 4S36&#K{0fk{fI8x?Ra5yp%LQ$x6
zDr7oxj-?gsP)qs$ZYhj&DmWaOF&1lQ1lL5Tg2Ry;Erl6Qg-l00<BXYE9cn56Dodf-
zso-$r4k)<C!;v|jR(t4~nYJfzk*#vd?D1^0j<U3V)VY>(KEBz~U*ptg$&~*~OBQv?
zQaNg^Lnj!&)^@IC`tHS0eFwpHs>iV=?(-R-g%bgv?lBiU{xG696WZd`EW8(xdlKNC
zo_FA)zB(%G2}ICKJ-jy8*BC|1fnHDDJ3XSOeJH#iQ2u1VKa(~v%EdquL?262J_*o^
zgdcY*{|(6aDL{YYR4$qh=v>0jIN`!80DVmOd8dsW%*iVeTrV2s4>>0nHUfH- at XH<o
zrhvb<&_8*K{Z;|J%lj(zup7G9y9*npA{~P3HD|gPE%XgXy26SBag~MO+UwLk+d|)V
z=oY;Obi_31zNg((g_VdMPvi?Jj;__BEkIr(n%hlRcE;E!`m?3bEmJ`ijXKCA_8Qp=
z6kRWsidrCh48b+XDHDYb4yx!G=vGaK{@`z;?~^WEbO;jcWTH|>B2}~pP|gg%Wd`Pq
zpo;nd5_psY_TAf`vh9{^wo~RCKv|EON*#;fnrmb{-TJib3`;iODbqH;glzdNq&wUp
zQ$<lg0{_SX8#i9JWD%!KXLaOkT&W|tqFSbko<ppv8pv9s&6-txdB<o0;J)F3XoEw*
z at SfMxV3fymAC4~9I(MHJz!c$h>pIfy&c75%RG*QEt|he6g8IpD$1TAN2)qC0DST8I
zjN2aFc-PPOU!?T$&ZP1lhg^6U(EYB*zRTu*+v9bkhI!x8{h_BYoJ%|4du1f|O%)qe
z(7h5m?tgfSZu4N7oCDt1O=lw+N?wH at L&iG}?rGf!`0|IsgTi1prOrlh&+3+Iqy9UA
z^z9DxddV{<<+Eg}tKNSBG(_vBj<uu_{PVp^-GJbJQS!}^#5#BX-InZSBV!UHE9!wu
ze+2iR#j~_ at _gS(xj4YK-TJ8|khj$s;l9Pt}JrA1056<Pz&6T#EgNP{JfeP_H*ALx<
zHPbB@%{^ZfKknB1Xr}dacjez+ikkA*BYFm*yzY;n*<ATQ1MK?^SmnJ3thD3j-Mo*1
z=Pe8Om)-oASZVg@{&6aeLVn82JDlR)7u~!sfamQH_rJUO{{$-SU10KI_P&>S*u{i>
zM&+1B?q_`S(I3&kc^5)y<pJH9M0=_FoB{X-1osMO8r|_(8Q#56mLB)7Zm5HSP<6Q<
zbN3h7XOM}fPvCjX&mijQ`K>5?n$x~Eb^rI$C8^WTM88lv@%CK1b^7L@`yBz)=$~k{
z!MV9Gf0w9N=k{gAevF8nPSllm13JB!pF{P}Mg7T~!UFX10}<SR%=r;Cd_9MzwGM6$
zoeimN)ytCYqW*Jy48VWq>&m^~wJ(S8nTV*qYhh&vlW>N(2#nlnXU@=5-d{qzKSn|B
zXxw)n1;&+I=<Yrj%mCz^+t=+XJPeVIRN2 at 4PiW^47MGX<Z`kMdbN40BdX{X at 1qj3Y
zVH|u$`4||^!6?ZztO`qj8pDS|JHPy!4Rba-xF?=<xUckf>%K4Y?Y50a|Bd^gh`mt{
zd%d#&xbiQcG5;Vy0>9&p2z-garvd(u+8=m->Cpb%f<N)@O=<Uu<m+oM_ZMDm*LMxA
z^gRxT-$N!%`!X1`z;oi<a__*!c}h{i-R4y}gMNjW`zUYz3MMRk6|p6~fW*aFje1u>
zCd2LsZ{Z3^MI$MG=Ql8&w+2TUWGlRqIqQ5su05ZHx~~1-lY<|7L0#@+y at PogupBti
zoBv}PD%>BnCFXZZ`8Dc25i)V$$KJwvOXCu$iu|oi=jCGsao{+w6gtfT-RtOpOAXmo
zfQO%Zu>KiR*awGVoHmBsjzdq+7_NNWKF2iH at epx&IpN3<>65F9J<F<*&hxAN>p^)3
z&GU@!1GwY+gr1eKcb^4`=kd}DLGB^@Ec>PJ1WclGP^I?+eVLNyGbMil%JsVEMOLTp
zEBnA%MU{3xSl<Ho{DE;1tJ2W`dDZOsW4gNbsB{^`n-Dy&<PJj`If$Y*c|1hCFW`B#
zL-92bODW$-i6w6qN0mMa at jqyM@5zH;oCj4x*Z)QEiBfe4p7<ho-jd>rymTUfV+j6T
z5@|~f04^Z-uGC4&+|Vn5{(_SC3EC?RHLP1z50q$Fw;&xF)@@=TW8T>k^H!Hh?BJO~
z4p}8+PD04svxOXbwUBua3z`42kOdzIS(sNwV~6c8WYJV1i;ohrq(#WmEkc%EBV_r*
zLJogH$cldmS?L*0D at PRzIeI)vuZs>AvU7!yi`NRdq(#VOrwQ40u8_;G7P9+pAy at ud
z$W_k^x%yQh*Ssy{x{rnI`AW$3J<FNVPm6 at ySS;kGQ9^E>Amo-ALT;Nc<n|+k+)*Rs
z&PE}3ZxC|N*+TByDdhgEN%pOkO5V5b7Kue(60+Kbn^wd2jgAzucBYVZONBJn35m4`
zY2G1Z{ar%hPYOxy71HWL2N<^RhCxDpJW<GTGld*~n2-}9LVgk#a^gusPTeWw%-uq^
z+#_V`FNK`VAvkQ`ZGRE6<6lC~uR^yUw(kWCgj`r7WM at LiB_|8HbeE7_cM944gpey<
z6LMvDjJaX^UbUZ)t0$2ZH?9)W^b~F&4J(dGEfudH8DK0vT}WcFkYufpmXn0EUM!^T
zHX$3H7P9fLLN@(d$g%Tr6K7cQ<~2foe6o<^t`TzlBSKDiR>)7 at 6>_2*w`7JDpEO9w
z$zz0^GE2y*M+!M at qma`t6LQAALe6|%$d-?UY|Z5jm*TU0Le3s6WLt%h?bC&vw?N2_
z)k4lcRmcSw3c2tmAs5{%<kH85?E0OM-G3Ew#lM7H(>utFt}PaFU6qhMGf7HUuMo1P
zQAqSeA!{!bvhGG94L=vs_<JEu?+A%0+=Cfb+T2&j`q4t-Gle8p2uU`P44Zbckb^E3
zGW}K|GoBSPbFYwDUkaIBfcq`OhE)#}a_|%(ha4tkPMwgs8-*Ntwvc&O37LPdkOfZ(
zS@<_0hkYhw(LR{-hYed?B4o)VlF==5g|td18r`--VjINI(Ho_ojowr;fttro7P5Jf
zkRLY)Iqoze$6qJpgolLu<PSnl{8-3Io{3C;a<Pz8CI~rozL3*ugq)rba>f}#&b(a6
zmivWleMZPxdxdOsO`@@L1_?QDqLA~K2)SU5kPA-|a?ws9JMR>7 at e@KWc}>WrUkbUb
z?_?U=RVn21Lxt?F6LQ6ILaw|_$W?a;x%!tvu6bF=wVw#Nu3!qS>=`BG`h$i1G%VzX
zZ9;C`E##)#gxvfaA-B9M<knsXF!^o6h1@=0$X)A&+`U=IJ?9E};A$a1yGzJ}PlA*n
zs9wu)k^Gz*@<Bc#Wmn)dHJp2EhOa=>JqxR*Zmu#ejLNudDEm3(jFwCE8Ai#KlXG5I
zl<>)vI|nE3fV&4scW>E$fQ%^Tg{OOAF3y$S@*DaiWg$+*!-)>Zl&8u{8Rb&DYz#TB
zjooMG!MJNAZzztc2HH=JzJgHqk at Qla9970OZaLSH<*S*JT-kbZ6u6)2g)DQ+xCAbj
z0<b7$=TJ_pj2nc?b~8$@T%xR>@;iy~5kUDv<cN*op^VXT;a;SG-j$OpCs!s>Nyf!P
z`4?0nS4OUkTnVp={%{DYsI+7V&ggG|?Ox#i2S{!~;7gDmb7lbd$$?idK8`b05pd6e
zY;H%gKu?Me<1*1FhbNgL;3K*`9o5DH11Or8E>eMFqD#|Jlc1cULuBnIKBXKBR8X`)
zM9kNxGoL_oSvqQLO`~XGx<~~MCVCXhnks`%P`MDI^$0y{Ql*#VQZtnsAi9|11u54l
zR)H&k_E;n~Q?6BB5A<p3FH7l*)0Mvm`Z*;>r6k&tYc4FU$h71IIvSy8G^MYLKbHC{
zGtntT5ACQBr86L!NAY4wq;p+HV2PcpDp@>SsiOeq4R+UnbaR!|0%-!f&tP{eh{r9f
z+|6Kn4=y<Y!jr+~4|Z>*&|4Bjy<7~oU`WYj5MBw^H^hAdNOyP1EkN!E>mTBNlt^yL
z&w)Gxw$BjvABcEMxJLW{Y~g+-TqpjA?BEiv74r at SJEVl`#Q|iCOSonnPImtit{cab
zEh*vJaW>h~60RSYk{v2`Ysi+1-6pal#O|?VM~dCk$&M1c=aU^RcCREmM(o~7HXwE%
zB3n^%Qn^yU0o%7&M&1ixi>hRv`Wx7Og9ZI3*#5<WegSqsamoEimOBp{TMw`Dcn2;G
z_5{y18MsUZ^DTaPt}1y0ihZbfRF$V-;0jUX5FdD?Ruq1vSC#Y{fh$ldhN<`?QDplJ
z3~5E-kMXKN36)Mg0P1=uxrYPD^#%gOPoooNh>az1Ix{f9Bm!G#NCTzQ031y48rz(2
z8w{&5cCyk15G|+p+MBK1wAg(#(A?ZW4TaZpni7Lr7+6d6Iy+xMeY(T0r|3r81E**s
zMYr$-k+Nk{{e+_1+1D~fW6z}MN*W)xjqKGvc2X5MACW;LWF*P(;6aVMl;}vAIx+Ye
zDYsQrU=M*&snI8C#@`Bb;7NhINlua4y=^3G=x!V*Oni{=Ioi*OzhLAs<Mgi?IZp<w
z4EfUE0(g<&Lyk6jmB3k&XZpM;Q=4zlC}y=kj*}#jt)s^6Wy;<9G+-A|C#ZZEvQH59
zYnH0!K?Oc%f*sN<JgC5b30#!YsLY*@Spi|c7G4nfQj&ll=)m)Nwd8Xc=tp#CrtW at 3
zFSW~PCiPOHy9E7ml+}<@!)0nT&cq`j_v8kGRC`p^r0OVBfyqQKlTv0R4$P$J7b21b
zOOZflS+)Y~a2hCCgTuV}*jRp9v1bwJMT3tEt^lpU)z0AKRq!bA%yaMw-r$cc{wKYH
zVep(l2cK9FTx0Pk`GZa1S2OL&{e!1i`lpl!&j!!79DI6Z at B;9BUO)JZNx{p&?<9Zb
z^x#$C?;yWrPVjN??~~uUDEJI`vAJzU at OR+7xOf`8eNFI9 at Z#G!&B3?8`-$&J2Hyui
znEd%|!H>a9+KV;>KeO~NIX&oFfZI*9f9ZBr#;Lv76Nk89 at X^7Ipi=x*DtNq=<VRjr
zb~f~NXJbiJ*{-y>KKIfeRdz2WG_O0Ma3U#r3E=fGI(Tu(8(?n*JLC{K+dK at mC{Xqh
zlTueFm6NYFx(|vp;E&K6Nq@~MF2%c4pvMB-aor|~4}h{N<0VC)fatj?bX-3IxBI9f
zPOHFRB6rv-siK%JT1NRLDLK8GtO5bTS7gFd#uHxX5?p$o^g)wm8ijYJWClK%@Ld8+
zkqx|nu$~pfU6J*}wXiB1gyR98!=ccBY8{R;yG?B}T<+8j;Mh*ysb?ClKux&_?EZ&o
z*D?%F*-hCJEwg>_NoG^_P`0?EB58%d?NoRqy;w%{07d7CNLnTEa{}i}&B(za`V~cb
zhDf2MPXYZMC6@^(&S_IG6TLR28u&AT8w7BmZxVel6Mcv1E@>Q at W`&c37%%-N<eyXL
z8UgKvtDb<h18O1UJM64{ci;|#Dr1Kacqx(-knU<SJyKHzdQ)^&D%IPP>U|uCOVYlS
zUo8nFn{k5(+$wg|xKc*W){($yMz-6gRG^B$IVoV=Bm&o)^ZG%E986#*4eOI8>r<7^
z2fCb+%hM$$pH&pyEM`SNP)Fbv8_ at R0t|NLkEd&x|e`Ytc8oP<WbxaXBk?fw7EN~iu
z+iYu-)s(Y{EOK;5>4||Ign#N#3|vCwMnQN`fvX7IWUJuxP2gc0(EYOXR-ivaDEVC~
zZRsxoJVWqh2lx_zHwnJx0N(}h8Ns~{P#uOVWQ3CU9AF`UVuBwzz;XcN2!8GWrvjKm
z at T(M9xCp?}1U<SkC{l%WK$?l>InfP3PA2MeqFaINB--DJUJ2x8qC=hN-9Uapbfg0<
z*@pW>PXHZSEEfsSf-Pz;xd!O#V25k;9k691N*)0EU$EuHC69saz6j_jxk4BKwrEW0
zP>?Ew5o4v4y#1p}rvNyF;A9852*4_YkwFJo4<JF!gB;*y0A~=K=K#+Ia5=%n4sZ{E
zy9gfP03QPIB*9e<@OJ=SCs^wM{|?|^1fvd6EyiUO!ibmy><eHh!4?M?05FwcwGH}s
zXHEsGiC#wD4AuDnjwE<2YsjaosRlrd;7?LuU;}`W8*RYHJAN2rM2{t}4VEm!?Y1)k
zjw&t*f!zVNXmQC}u-B12>_E>6Me~DqfIl5r(E=5G2t3z%Md;@vZ@@GmXWbL9Sok$0
zlg7*oJ_*W_jG3>3&sqF}+~6N9exWz`y2T&XEBLm>FDeLrVDXC!gP&RalKw%p#MoRq
zDCo8LWyL`sc+QDqmX`+yg6H%x=I}}tC`BZ&S}IiLF0S-&dLB)9O*?oT;e^1lWR%I>
zBsq|>*7PLiG<FC at 8#+j4<cld!ik!xL#^RBL^?YUfW>VBpq$e&rg%Pczs76|psZ=0N
zpjP~qgYBXUY^118bh)H8^YsZtBPn;ZnbU~Y+lkEu$yr3Bj at -^8us+k|PNFS>I&`lf
zx?Qdkr4)DJ)~PC^lYu=H-6B_rDN*1SqPNMVp#!~#=y`I=vr*&TLloU9*BqIm$0#~q
zE)6q9Pg8WaTpDJIUZm)RRAo}G0<RK1Egd!Mzr7S~P8X at bdqhu3M@@oHC^{}x`#Ohz
z6Foi?&0Pxg)O6IC=|$1m(m^E~DF~ygvJj#P2o+mX4#*`@<$*wJC^;`Bk^C#y0zHe8
zi&GMv=6s;{QF28}qSHJA^i4|kq$JYK#Erna5Cwi>4<YIGD)2GUlWkN5z9g{K28^0}
z8PIc5cBOdIe*!%yy0F7a at lkY9Mk?*i0E%{YC at P^SqujcdOGiR9j^Y!=K}nu+^^_^>
z&u8K|oX;x)2U0UE1Ay+Sz$^m#s)MKs%q7qyzW+iJ|B8wE=p(S0qIF_iR<XkUO_W5w
zg7Sux8yQN0V<<mX<g$2 at mXP#;H5AF?IiHl^5Zr2(0{XOlnhM~<ekyQgDt$wS5?f&G
zW-6^^Spuh!)vG>f9K8lRi>O|u6U9`!gGgK|MLJaAG6I`Y?WYr7OH^M+>4eizU-HBK
zZRI-rUdV4osLa9kMO^hSCp!*%FQ at mx)`lLUiNlOy!}0Eg>+q3~{W2GC5OZMkL7Hhy
zaTw6vMsL<n5Seuc4r&I at -SW%F(RFw|uzwdIZ3Ciq+P?x#<#vqd<6fwwxCpY7d`Pja
z^Ayb{1=Nto6G(A5Q{3KpitQ#vPf77_q__}|6=uF*Qp`e$X656cX6(j+Kl<l7ybRc3
z`$F?GMCtz=DwR*harl|24|(b!&ne{D2INa;%)#>psTx*KF9iOGxl}jd at f1hpAn-+C
z)T>bP9`MwllT1g9zkR^J_TFWiZ$EX<`)AE-&fj!)bNO#B|MTu)??3d)ojo60xP8mq
z!_R(Y`*B-WwtaEcNAL6=lYDPP at tep0v}(|wzW6oLzJ%}=0?WXcy!#`RBTPb|vnvqR
zAZ$Q59pNGbd7BdY>=^v<4NJgwoLiF^XH)XW?MlwL?0p6<odT3Qttn@>;g8#d7?(;1
z<rZkh*^~H_UD=?PzHE<1+>$TJNY8G~^nb#L<Bwh48Rvd%#w~xWb|S`KW;?OoEgiNM
zLq|GH%l1qzJw31ahST$&xcXfGY{ZehszZn(Fb_OEm0tu$#;bHxaZ4ZLH}unhl_%U)
z?B<0Umi*a&a+F8qsyyi%6frIHxB3qKX4hpOV!z>_@*@->FpEJ5gAu4#3|fLP6oEq>
zHyIV~ttzZ76t1x4Ljd%Xv+g(q`h;du90HtKW+Jexv{h~B!JvmA%r)@^pobyg1SNH{
z0`zEvRS02(T7-H8*3&wKCWIKmjL`3&KCx=imN!0G<G$qeWuEi4Y&jwKK-aXEaeWWE
z=Jt~}-*oH?U;e6~@9S&+GOWH}(cPCU`uV5-nOyhpts{<|dd0qf>37iDi>^Io<lA#D
z|FV33{&^ohGcd7s^+O;3xn<<lm)tt;g<D=7xoYc0!Kcofdi#UtKl#yvo5z1S_=BY@
zU!A=A?OP7|bYlL&drtZJMK8 at b=Z#-)Svh^kuuZF88(CX?{^mc{oO;&M51QZI9BBD$
z)muw_|Jn5Z|6TCvS0hhbJRt9$(M1PUo^X0zLFrjL7v28iOFbTcV5|Fr<-Wg{gf<U+
z>iOJ%-*Vod8 at FF`%GM?KT~#=%=(_jzf4BFw8;?|n7Y2L_53QbFHsaX_`tAACNbk~$
z0UwO;R}}PWy|ehJ13$0&d7gXm+9!wqeO~b1y4Rnc`RVI}j=B7`CBETn%lF*+_?wHT
zPhPymyK&96dydV!ZEeZBz0bY(mZN4p{!`Z_udmO)Vbkp7QHiauT)O(QjW3-4#-InU
zoHXLEdzWk(v*(=qr=5R)|G~H9PXGPu$8Eaycizjo_kSQzaL at yNiwC~D?X3^yUcURf
zCqI97<yZThbH|R&U#z-m#O<M)arf_desyBZxtk7{v*wgOiyGg3WykhQe{;lVm%s4A
z%7U|Y&AWX3SIz&bAM{8;_Xl at vK0OzA9}yl!coX4Y2tCnB_d}>en1ygSLKI;$!Zw5}
z5$;0xHNqbe-bZj at LM%iWjxYsb0m3l|34~J-b|Tz}@G!!22!BQR3?Z*O`Z+=s!fb>i
z5Y{667-2iYRS0(@JdW at R!aoq)UW^lja)bjA79xZZk_e|ET#RrN!V3uhK`6jLD at B-q
zFc)Dx!pR61BK#ELL4;=z-az;ip$7)#AcP8pnFvQC#1KwII3HmT!UG6TBfO6AF+%q|
zJe)!pgD at RoDMCHMMue>hmm}Pc at P7y|A-sd|Uj!c}tDy)J5e`L&Bb<V85yA}!4<T^x
z<(mlqLg<OfVn2jRgjopOkBlah?`dG_=dN`S?i2>$?q(4F_?VG%5Vx2ah<j@}T}}rM
zh&yjVxKGw7$PQyD<U`U26hA(HqZvNZFj}%{98eA7MvD(8sm0A|MvD&@2=P|5f%rU>
z5U)*!g5q~BmLP=Q!c=Lr_(+owx4IdKkNOGm+Q}s3y>vpnZD_Rk%#slIx*13|h5{Oa
zWtMT34^OGZ4RuC~k3b1=%bbDue3%d)*cyn>HVJW`oPoG+gAmu12I7NWLfqhIAl?%q
z#9JH&;<i#k+}>ayKC>mnJ$(k^16xAe*k>R<WG2L$-lit5L~kI(7axokH<A$I^`X&{
z4g7$(rGuv>{A7bT=(JR8%XcjRT?hll79R at J7B><aNVZ-B;+_*ztK1_>E!oxyiXU&A
z36v@}A4U`6hDBqGJ7);-CW~>E51a|{IkeH at BN{?{qGNL8tvEuwLua)3Af6B(mmBCl
zL<w=Ljwv?p%Ms%3I-|v>(S-Ok&p_ji6WoPqAnuHz78m!%RX&9v#Ag!5FL?<7(5)De
z2I8}FYH{18vBez%g!nk$K=OSLK>Y59fw*shTHHZkAZ|k<#5Jyg_%NRkH+~w3FDAf@
z;@e_?_@)^CxcM1>d|?8FKW@#Y9=}Ndi0^ISkGtJLxQ!izKYl%jS at 7#Vrck^QMu^vj
z25Ll<5LbGpvbke`5I3G0TYM#id47lhh%e)SJc58fzMufYANMmbDfhY>h&v+)afhsd
zxHE$gH%=Ic`!)#i#>r4n{J0;05bxF)NcMgM;>%6Of4*BlExtEnZ1G+pA>KkXkh~B9
z=#<p3k(V3*aXXf=b)|8FyEsfjel3XA!p%;AxRuLD`1%2J;btmRaoie0h+Bh=7H?q^
z;svvT-Z(@<+%9dPm8PkVgQoFCUR*(R8yeo2m%aRi(8flK8yIMwx2;Sa at zEq9KCv|B
zxu1*>x0e|$-u@=UyW&R61Dk~STD^g4Ooebij!DQpFVy0`XQRbu-h_BDZM69M10n8C
zGp=&S2_bG^HVGG*gnX`Tw0LuuTD<3Lw783m5I36}NWPf^h~LsN5O>{Ci#O$r6Wkp{
zh`V--7B|}w;zL=ZC2zL at dLDh+IB^W3)EbFkwD`6|E~5P62W{!$$ahH)+nXA6++xI}
z+;wD<@}UDE-rP2B at H1J2{)=Gp<l_cHd<tQ-_$e+zkEFEZ?IT2AOHEX};1RX>B9TeR
z9a4n&%-=Y{?NNldZOLfeYHFWPxec^`cdf;D7!AZ1FEG(4zTk&HzF`K!*ZM&C#vTZ_
zI)d;uH4x_y2!G5u?N at AK@CHIxJ2@&te)*cTlOLmTxgZ1EPTp+fK26)nw;MUSDSz$c
zy9L(wEjp5;ugK4}X^C=eC~y_@>h9eRE39o^6drQ~FXO)Y%9I~x&)x;6x at Yafn&gjq
zvk_JpJ=TN#EWMd0q29G#1E^)s)JKQ*c0g~AvG;X)KZ9PS(KGeap}jYuS8nu7J$0zp
z3*{~_dOeUvepWe5bUO;3tK2xcT&^#B??b{$M{rflXl`zZ)`pYOSW}{6MQyAu5(qap
zSImkv;S1}@M8)h#Yor06xsF#Xi^Ur7h3crKH#<@vZfQscHsA~CMpDs|h*#7^n<@f<
zifB`9LrYzxqIT4%iq<Oi17y??t*NNRH?LP$R8<8k17oc$ze`?=8p6r?SiCV&u^?P~
z*wPh&W&=11zI66HTb!s{CxtYn`yXaifsfo*$ba!j{4aC;-{%+|J88oIvV`Ve4t$3W
znq{Y9OX9L$e|{H(5MLaQ#W!*|CX#h^k@~<IE;{t5%Jn}wfe4 at Xw-exB5KxaP2$K)-
ze><3ed!o}rNxttZX2}7 at w5Cz;OpMP9;~!%nl8f^d3?Xje{GSzCKrMb4Jr(1BtuQfu
zHC>y)nJ~ndNoYk)N-JuTBC4~4891do8F<W5_J6T(<RJgc!o-n<{2vQMEu)S&OM!X8
zR3<p6F$3Mmh~OlvRlu_f=tj&avC0$Ry{0x|#*D2XA3oR0wfZCIG@(B|516%RK8{Y@
zGROSQXV0bH=(bkNh-%APq<QO$=T?2gJiinT>-;per4J~bg}go%s|wUM%egojOVqd3
zF_p@#R6Wd!7I&jO!+Xy2<aAq+>++~>Ik$B8)_Z(Cw|mBRTjB8~Jwp!lj7?JThnx>R
z1A89o84kQ6;OQA4IBlw at FR&6|AOKoZz{shdo>Oz(L~rQk^?L%yM&+D-{QaIWJ(F%X
zPCysH7u3U;7WxDlF?6}1vp`XAydA;8Fovr^_&)|KAU5HcUK%fg4gSUy;7%^&-S#2@
z>79n2Xy_tC3k`ks0IfF|iK+jHp}P$|!O&w2oo;Bcp&*jZ$FnNZzk)+=1j_k)1A%dC
zEp?iaA44I2RVHq&l at JwuYi-0UL#E#i%HJ4NLOzwuZy4f^D0-CR|8L`edhy?U$0LbE
zqz?bdD;l56e_s~F{~(Fhnt5byEuoBm9aRl%vit`Y{KJ>{+*<tKIQ+L={8z+k{GYe#
z@%2&s#~}O<CP!XD{M+e_yh4$NNMqI+&W~1B&#%G%R at 49PH$B(yR}}mQJLmtFUb%2y
nR{x*1<A11}t<?_yyK$CA$MIjkum<H{NAQ2rtn9+i$*cbdMgbzU

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/X86/Inputs/String/foo2.o b/llvm/test/tools/dsymutil/X86/Inputs/String/foo2.o
new file mode 100644
index 0000000000000000000000000000000000000000..a0d093389d424092c62a7871992d286cfa68e8cd
GIT binary patch
literal 56860
zcmcg#349bq_O6*^hJ<j04B-%j5I`f4W5O|jC}%VrDgq*cIOLeXK#~cWNdkD`eJd)s
zC?0s<>xK8R9=oot>v~_i-uiddbzK&9*K76veXpu}dL|QAGjZoP)vxM%uU@@6ySlo%
z`?+ub{zEsVTp0=nxJ<Zp9vlkb at EZvCHNg&kmp!i;TNwvGD-4~At~Wvag27m5T}=CR
zcu~cYMe(rZTTdhKqdq1(@l~bz5y(^<NvvNmxU!}u7+O~oYKjG8Rn@^@qP}B{o?H{5
zFN|?pkyFrMuqGO74mYkeykvc68+}%OMlf at ZU$X9Cur^fPvN8yzA{7kII(+(q1MC>v
zjJ}U*H8eI!AJ7DqmcIH(O-g+y)M-6Onpgwtb=YxCsjsTKx;fO!`bo6!tyMZ^iK+XR
zMu#TtO{p*3SQjBXSzk_rj+A|%rdR7?Q6Hmzdub at 8zJ{tAQJJi-?+zWw6r;N3ejRok
zlk`<JHPwfLja3byD1?&r<r{s!HL-5}iTWbdtEEDc^}TVAwq%4cXzfD|%e1#+`<kk1
zlJ)(^=(D=emY=9Ew!SH4e%IcsjTmDJKl|bTW?xOD0d~cLEsbsA#@b+T-YjQ~?Z4BZ
z?WRH|KBE-JlqIj(V?a`VL#u*y&8Q6>FS)->`@P01O{~}dsP#P$eM}-pDbqr&_`1K<
zhZ{v>a`~P9w3f>^{jA_Q9e&;DLny(%asUJ1Bs;ykt4uilC`9~S#On)M at P<;~qmRHI
zH6M<@p2jgQi`NVHbAN|bp7DPRD^L1tK;;=fRGzc^-O4lG`ItIv>cr03??|LodB&6e
zM-zok`t5*a%b%z`<B7_1j(s<Q)jOxIr1#L1#jM^#rzxgadCvGg(6js#qE0qynta3P
zJ=BCn;hAcLYxxtKQt>O#_<H#hy at zh3I`WMHzi*#_Nk2(`;rz-ozO$^ZJn6StCqEkN
zwoJ!1q|VAiT>n|qa*aJY>N)FN?GsFyAF&s<{`jM-2P=6%);v`(L#ffDRri90a&{;f
z8CBCckQCI^S2eCIXbm+-!;!`UzrUocWNbl^pv8WF*;t0lOU6&yN7Y3l<s~&uO{(;;
zD8x&vTf+6V(fX>^P-#_bJ<f~KSSb%YSMUT>9f{PdXsi}vlwVa>MZ-0QGo at x#Rr8nv
zuqICiZ}Mb at gR$nSa4agk{hiFJdYmh&Vv%OeD%c<ToZ5ou&<&BsDY5335O_-up1UwM
z7HZ4=DdlF*tM*q^l$YT|zN$IW7OW37u8ge;hMJor%@wWC-5&n=N+T_?V5BbCjG_%W
zlsaLg6kQc*js+X4qH9z%ydf0i7^m#)S_Kj>CYu#6iKPeY%=#zTOcQVR!3%?vY;bl>
zMMcF#6AV=>SXdrxu#yU?rbxIk7HWn`#wVt<t0r5Uojxm01s640s;o+ihaF{?U`?Q^
zwzfGGjaDqEQO2v9Lv^9%P-9K#zek!|qiQ0JXls_~I+UP6mrO#c at e*j5KeyGCx~h+$
z2edRs!z&v at wFM}OxcO6BBjH+URVlRj%W6Y*k<PDaQ1M_#Ihfc`wJylYMys&Alue;M
zP>a6Q99ds6zXpoMtAewdl(dq>nhJ&+nto>GjVaLm#jaD``p_t?mN=!uhBu~wC1z;|
zPG<+zg~+lC&I;GnEn-u)^VONw$@<Zi$||ty8S`7IcPA*#v0&7028}TVbyf9I4iED&
zkF^_le8edj<)~!;xI~HB^J^;nWi}RJn~jHPWo<Zy(X*<4iX`JS#Fk4)i{oBnRcuTF
zI}lQy!RiB`g0t(;pH_t$(HW{SJ((i8El6sGKdC$uS|>X^Tj<ZM603<;ESL)gKQs2&
zKr~bz!b~gD$V!V<VM@~sU(<SBhs`ZDEH$J1C&~Uy3;Y=6?G7qq9$FQ~MSp<f-OA>w
zdTmKnV{CS{oEIuk4^|At9-_NNJMk$zxmi7+wW_|wIc9aNzNWPr9Y4|(YUT;8K+cd7
z+v<Hd0a=5=Ppss)y?RvNZ4S$D7Esbgcb_k-x7a7s4zdJ&I!iy_YP)IezCKLD!&y>~
zo1G{hD{4i at DY0BS)x;-Z!2C&#yyLVn8?n;<X}W%95sd8u8y)2n<k+t#Ex}+j#sqYs
zh9;iMLl~v2!p)BJhI5+MZZ`4rCVd<+n?p^`q18Th+0&7Bwggc(4ZpBKW$}|sQ1 at k&
z2~5SYo({#uLaJ(FS;^TIw6-c%C1GNm1}c00q32Y=`gLGUU$9{M5y6GCmsSK99WlQm
z$S9nqHCMIa*cNH7je;gsfMhz}NXpAoOK^hdFLzea>>5ITN5yd32rOX^RZ%fs@>el0
zTvjo!8chS?m7$o-b3vK1H3k3QB`q_L*|jLNnN^K5LKO{7vGp^mq8OG_7LTJ%BsHTk
z1%7K>w+FS|6=7o8%nSQbCg{@fGWkiR at e{O|iGHA6hSILch2w)2<LkoBQP!bQM;-cq
z=>+Xk{-siy5DjsPhP-Ld{~&YmB!BVTjf=KbHR04hF{tRn?9mTbt{R&n(S)mR6>h{V
zwW=QT`{rPMI2zN#COSxUXl1xD*p6??$v+`EB1VOA<{E}%cXH!JH;P{9?j*;Cq>6A<
z!HOnzoO57u)>x-TtQtM*bLtGXhC^+$YcQ?F`PVrob1YPd3<?OR_&V)xr{TY!)?~qg
z<2 at CzxZ3Gp_N?CBj+uH;uBckbNyFHnJ(=9kSxAAOs>ZG#xy}fNu?oPMX{U6V8boHy
z at bCZ0W=yED+KKjbD*bUax(ShVO2LF?%L?r=*PpnrfaR`Gyl|2MbCJgLrn!#%*#$5T
z>mD4TNIGSEpvE at d_&TL#e2p<gXs1+ILqn(9fnJS6L1<5>3~;WobjFDBAx<7(gV0Wy
z5MEc&VE4>r%R8l`yebAITodR-hZ<kkj4N*BL1?E`jH|AySpy9uom0R;4+`|y_w$E1
z|JdeGL!>nn#MMQelxRYjHvQaD(^eU6sY_6)!<|uSoqsVDcc!AoaXkb}d<_j4ZJO41
zO2>p~OEuO9E1*OBI;ABbH^!Pn6+EjLe|m}<8mOu>rDEG6Dv+<Vl+4F!aasx*uv**|
zDms^sadlV-WUVw{a^A_)gVv!J0Du0;Nen;{bh09J;*8&^Y8c-fF97kTqa{5XI$s7R
z6P+#u|5z46P_E8!Ybo9wY^YPElB~9q#gnY2^W~IEQ|EG4E(KO!g_}eP<z<krP}<qj
zN;EBv!fLOmbJ+?w8dqZ^slarb({Pum?`+Yfur!VG>p)xQaycR1;M$d;G`e((u)Xrm
zmSB5LX%t{;Wmts6wa_BvSV^=N8|*n-(lX<OswnTj;?~*%oN9Hz#814Hm=v!(w6>zA
zMupb0&dhW$S)@Kjk$Ra)rxvm28z>4n(RQe8g1JJ0V8<!OPk6lPv>Q22Z!!5}1t|J=
zBWmV}BHFQarW7%s+>LnwHpCDH#jr9yto>m3;cg4sUmlADb%jC>QJuk#?e_a2XKAmf
zVJs`OyGWt6wpc|tjOw+69mg8WEa9px!ds|vyVW7vsbwR*$THqpgPqlL2o_npz?_A#
zl*@5lpgFNYcQ%{OR at W&V_JUM=DJt03jGHG6%OH}p#FAbrxQP;1&W#0fM?P^kK&Mh@
zzZjOL8Z&TpN{eG*>%XpL#dm!ql#O27;#y{WHKL1caom$hNZMH~+JJP*!dhudHy>T4
zC%*KVwnb+BGhIE7rNneq*~^LPDoU}a*tyncFEFNSQ3tDxow8~o?ha#rxGXwa-gJlb
z3AiPXyA2hX2xwoIDNI*U0QQ8MG4W}jW%Q-1ky|}=Ch at dFT~$kc4AX@$mrqmT=_Y4q
zz`0weQx)$Y8(oFHvTK5v7S+LE+ at f@b(=~K_O?{|}yIO@(o3-}SDQoS8 at pKi*VlI at V
zGmcw2(#nxuV^7nPE>Y4nkN5L1N3=GFjg}jF>68#ucEO|$TGF1>LB}sNah-stVR+|E
zmz at rz+iMbZ>Lt%~s=-p1bmi8m9_Y~3Rk=*KQ0$aZ9DQ}kw;z2|;9X_-FVvzYHMK-n
z;Q<5O`@$|?%b%{%6PqGUT4^h`4r_0^I_-OW=?=$EMd`G3>yBZ%_BiyUV~)L~B;#tD
zgS at 4zE3V@$T{38O#Q>w1&bnrRv2~@}Jgr=&KfqX;exV+Z{Y{vKVz#JHB07|I?h}-D
zK_y%Ix}=sJ%DOD0T~N=)EZK$XSOS=hJY%DIS6P}`{V#3)FVuL)W5ZSymr at N%Jn5E^
zQJ1=ieo^HMC#AhUitDnb`l=e1hVIHHoUYx;deiUC4vk&WpA*$}VRqB+6t-!pn-pqY
zS5=y)=l`AzHpt5MgLGyTKPi<iEB+2k?0-=!yBV(1y5e^1cS?7f=-Bp at X6v!`aOqn#
zY2|OcJmkzJ7kOnyx_KOD_RyuP$3GTNW>`<Q$%D=bVYb<{vaRoU>IrQZDdWJHuwkfE
z7pL)Cv0Y?V;%)a%*<|(tbx~<Kb{3^yTn=SvmzUAi1qGJ8DX5D|E?I5Yw767S(=N+o
zrCm{|iJOPIs!S8Lc2SYGSDJo_ChF{p0!^`-sH;jfh3YOU+72|QU%n|6cSRw$-*MDc
zW!zqK7Zq`8#p#!Dd%ayy!1h)sDb}=&wAESHWa-W{k`;Er9KlwJ`tHgMcfGpwPw;*`
zk{fPpt!fVAr3X>WQ=LI(KAr0$|3o~T%3F at XD(qF(w=yM(WH9Yg#xw2Vs61P(v!MOy
z+K)$F<!NBiDZaD~b*fCWa3}CVM7&)|-WsIu?aQ-?PAF}A{YZtE298wNMiQZP%h`{o
zqnQ<Xl|VvHY$W}R=qIopX;}G4NF%N0j at OGwjmSO=t1iqFv1utD=O`a+2$78pc7Xv%
zzjTlS>r~2uDI^q*Ng=H)U?{LHHZQ^9n~d6{X*VXMWM{=nDIq%sOux`NN=ZLFYmzZf
z1nZ|kck{lAc5fNz+{+mJ7z*RPGdcgd8+Ta&bd*+_BO6}V#w;Wo-(_aE*Pouj7$flz
zeMCA9J!v;#*}sHm?i#q40VjFvW-_64Rl`)-3T39U66i{uU8O7iHBGinzR<6FJ=XvE
z<7rC+=^Du$4n~#CY~uGBn2t>IQt{JG){jA2?&@%RnAI|zK-vkQ%;bGs`mq5s`7sm!
z_MBfZIj(i@?xkGm^;eFO9ptm)g!#^+v~!G+M;>9eo^HVoum6^!Gs6EieZGk*?G#be
zjvQM}N}hgb&-mq1>$sGE*<5y<ZdbIYav9F?mZ>oA3xrs>_FF09*K(<t=@xW3u48!F
zXmnc-XGHPFFT6E~Lv4p#rC$&!uN7&EHP_<pkinR|{1Vz$Hp0(IXhChHrMf<(8bS><
zcnlsyo`=F??F at o68j4rJ>L4hE@#aekY0_u~BlUdsZ1cLhW?nMSn?T7`&4*P at 3N=<C
znP9kX_7eTVzxl0UJbNW<k)*N?Bx}Nw)T(A7(WXX52p~dJb at Q5(y7^=mg(+YO{}=US
zGm23^f!<hZ%PsBTGe#`3h8e-ETk+nLywR4p?ZMu6KIk<OMQ+}8%1J6AT=fBy_mCkp
zwj3eQ3FEBFks1P`T5w=|Qi){0woJz+F41k=ij|}+fe#tHhZil0s_lU2w?mduT2Qnx
zv3R_ANE>D|wLNxFqB2zHNRWOzJqGOL7>K84#gWA9NOmZmlpPHzq17W_eCb;=UOA4Q
zVh~2tJb3t)LS3%fR~v3ccx_80hF$Uvs$Pfd4MlINQ>M$nAI5t^@Umqd at Xk4D3$?mQ
z;B7Jztkc0dRaYO;JqWT!M!Jeb710(GZh<bm!5BhvtkDZ1b<H94QtfZnufJ7Q)qH~;
zMx=G&n36-Vf?iDOLyfo;i>{BxkOxDmqgWxTS*6xS84F!#Y*lr19h5{>y&U979C=>1
zPT?roSCV<vfd1QvV=U5EquTTniJ-AaLp9JS;V8oJAfyhMJrC!!U{q6FIOE+$cz0f1
zebq|5I<GE_AtzXk2L^-D>J|{ZHwl2erYTroU8g-Yk;s}b;F|gfxyUt3H56K->hO{+
zXVpezY~x_4+YFvA!%(S$E!7I&c)%O3EmM{NgC#AJXrmnKAyZwyMkfhH?8kLF$-26F
zY(&ND%VLxSX(g>|!lMH*&}dCnBj838j#^aXt(II6uP2ljf8je5E7i&-JQlALv3+;~
zwHfWBEm+mO5-wDQriV{I;0 at n8)M}DyjT+T<nypr%b*S?i#bXo(w!j}G(Sayi1b5Zq
z(1KTEQ&N{^oh~SgfW_CB!8{f+GAyB3h%GY2*Y at it8Zfe{IzI1-_eSIO-3sqjB?;DH
z6MZAzSI#3|&L7f2L-k8!pogDOP_c$4X#}7Mi+vmu#eOT3QoN>6X*&fZPpt+FE)9gE
zRrQT64Pj+GXxD- at t*X)(JQ}OU3)j~W6OYDf8e`4%#Kfbq+VD!euML=ZG=^8!HmxEi
z9*v>CLe0d)qcO3In0O4<(unu%5~D|BQ9O1OA|@V<wO~iR=o1gHiQ(uv+ZgSmBnAwf
zvhirl#EwODY}6GVERK(TCXDWiF(skv#3A_bgmFTwIKnYgMp?0|%`SB9)7HXoie38*
zY8QN)Rr1JLn_cwUXJqaCwppc5S-beP&&b*p&}P*DW$h}^J|in-&jN3=YJswLHE5ra
zwJV~{s)<REjaP;78fht_ at M@|SFNZ|^K=(upiFQ at RZ3JppmPvtQr&J6hvw~zm<xJC2
zg&booD20Eb3L11CIv4&JDe>5ML$D#-NU|z|fseu3s`Wx60<Xt8fx$KduQwFUKN=%r
zWdlxmb at XkB;L{j&x>(Wm+syE10j)Nx)zkvUMk55C)v1k#BNfggLi8ZT5PEkTLT%yN
z5QhRlM9iQCDyNrPP3knk$yCsKLkz{qRA8P=;o&3}L?*Kg;#4d_O*wld%Coq at I&9Bk
z$?ITl+SVp9F?Zyg6oMVjN!#Yn6<K>u3gHgtq*|@aNuhTFL@`B3In}k)g0D^3&6K;X
ztwFV!IXCmfxh^Qr>r6q1IGq(C76OG?bf9uwKo3ulLCDv|!WhVHk2NufMPxp})h{&T
zW<6=ZBw4BtR8JQKkokf at a)y#gg=#e|#1Lr!9Qj+VhGx<EJPjWlYFns3dl6jfAD0L%
zn48vJwF(TMSOCI1f2|c##|sA?udSbl32c(!Y;K&MzbMG}aGBLq>$4KFW}V_`_jd2T
zhl<3P-!Js@{a`=io%hZMxZ`iWx6%Er4?slfI>^{0^M!~=os}VZuZAgbv^ailBwhot
zRbjpsnQvfT$8WaCuZN*7b(rPl_iy-fsYTioKQ<Zf35Ft8oT+_Bw-afnWs?!P#LyI4
zwj0)s9gEy<SPyh8@~B~%j}0M5hgn|py&yo=XMK#UQqLP7KK&!V6z1(TtbfNvEbliq
z)J`!HlV7%>P;7bku%U$o#yczy8I?9EGptFrNV{s7W>~X37Fl6ft2-8HGOV_^h~>4u
z<d&iUU42|5d-*&Wy>j~x>h<371N*r0 at Qoz*2$j)m|C}6rN-2Y%S<9T{%E0H7JS1nh
z2I4zPZr6mIj9xi8lXLdP=i#~yR<nH*A)VC|5oh~|P8~R9;9x|~?gw5*FD=+T&Zl^e
zFF{R at o)D!Vc|H4sXC=@p9*=s<bEvs at 3CyARlz~$R!uE2+%Jo3SI9S-H9kT{#9@$Fy
zN?eV-blllKN9?|F+=1rDQCk|H!i%FuR;m7_l2?4Ms0<$3IIt82qSPKfkSQ==5E&W0
z$Qm5a)5ILwzGsrjN)0j6_>9$1UBr|ta1=g*!)!e{@v<qjOC1u!jp7_frbgK2=h&H|
z@{w+1>0XYy0ls%!-p+1O9J6&OwNHsMg&Wtb)Tk_ls>&IF(jQ%dR+s0UHekcRcrBp*
zlp5nv?*3N2C{-NK8Cyh2QZ|$-?Jd<=wwDlpu8{J*&|=5BT&(DE!vF;kcRX8kPR{=D
zPM9HL0ZW_1^ofZX5}PKm9Hbp0?&K1vVLlv at _O&omE~l}BOv#54`&mgiIs4~}Wm7qH
zPcs4 at hq~!jxhpk8=bw3>Y4-*MX0<Co)Vvs5VHY4QRO*0n%00j`Sg8Xm)$zV#F+NmU
z3Tk~D1|A5(**c!?I&&y?B6Bg<lG9SkbD;hdBs#i`GMTCjx!`Y-CUWF(<6Z%;+m(^Y
zPr!M?ICwMp-N6B_w{p8(#?Q579S^a<7 at WI4b-S|rpuG5DN7ps(tnv81n=t<7c6FbQ
zz#5q1%FR$Yo~6kB0GBtT#|6;f%F0kZJp(|xuK at lSq3#)~`-uqr$UqJPcO!5R75Csb
z at Nzu0qTwBP_cibwL8<rLs(Z5)c;B7XeFFktkn at 2%S7m<#W4q&9bFLfQIi6D`_CMV{
z@~H9)H_~^3Nc<<5m#?7gQV2~a|6hnE+WtV+*KU`}o&w)#`0$<UN@%-Zw7D|6{|277
zD3bvrd%capLGtg*aQ$fgT)jU4?8?t@<?dSy<N8Q&fC=VJBbI%3KNL1Tf#<r)t;L60
z{5j-ntiXxsh?+6NVl0Xak8xs7;r%Vfk+3_D1!>ezYsbhN5Z5=u;xa}aOT$E~v>3Eh
z^yz~m?%ehw4sMOby=1hlG~~pL8JFdvd{!BT^4*MJ&pv?GWPHL}&fP&{v-=EEs)+Cv
zZr=xmN<B$`L&p7J>I%q{67`K9Zg?$Do)n<3+2XBp^29vfA1&SnC+`ua?aLcsbRO;G
zu|+B0V(=Q6gR?WXqOF+5ko_doT at IG(UbpW-OXR$a2Sr5Z=oyIg%!9~%Zr_lRN^PN*
z3!GYfwHCa^8Pj(&;6WH9To-5b$OO?1F#CBZ{1PnJ18(00jJYCmX-27t=rmt}NFifB
z==R+Uk<Ij9;nd>$!Gf=H#`GPqH!P&J*Cm*;3GnNLZ%lw+CrsV9Bq$kPgp(?|uj{r1
zxE}B<=KjtM831&Z`*r~4$mH6Q0RI4ZBg^sb1bEIqN?io!y2lCky#mlDgdeb)o-}l+
zyuLdv=7UbA>N{zaQYXQ=9!|v10`?*CM-uUGE&0a`uKLbGqu&DOdcuaTM(}TherG|x
ze<C;xBdzQA8Bk$0cHd-l!xe;|&e-L#VBM#)pF)#-mL21Ix9 at mM?hhGzcqzw`$jChl
z at A;Iw&h6t!crEq)v7J6&Hspl&Y&#vkgTcE9&h?zL;p>ierNw*0$<rO?uNLpmPM+>C
zqf3m=H=R7)2~Pp<ML5^HPM%Kh4U6|_GA}+jDPK{k(eR~HidN}j at x?5GuaX6n?>83j
zUrwH*y=0duRSoC*CZYa)>wt;fgEAchlH{rHYv2v{BhHXaQ$M=x6$4vGyujefcLIX{
z$7&ju8Lv*|d)k5vGvloRqf$90fjGaoh9^iLVZkF3q^|_LtpL)cP7`&}es1x~ojg5e
zP9AIGO>puU&spqeSW;7+QjTJO#S)m7ETDV^<4h9MoxFIl`&L^5i=6_x$vh2S|MAGz
zQYTL$>&y)SQv at 1Q3OIAoXo*JJi8`|Kpe5CmQcC%{O)x30Z71N!)B;PYIWvCZ$m0nj
zPj{3%EP+@%0f(AC0h8Dn?WA-8oeF{H;9TdVv_|<}u>{Ub)}Val6HVmvlX+sP@?8Ld
z_u*WdQ))LS<xefC%R82GR>YJ^M(g#d<sG$gmL+;a$D+#jh9z}lYAHv7?lsw at eX~<k
z>O~H^Rh?r=-J4p<Vc{2+==~jwD&LZQO|lQBmU3A5kR|$LYEfP9<EJRKsXuDw51EXs
z=TUhtCUxA6kb0R?f6Ro>l9I%DP<@{P`~oMs&soD4M>yrn-%qKd;9Rd~GOuQu=Bov?
zii6Uh6X06_|3K;YGOyr7+??Ti?61^a0}=kvX`?;3DBls5z~@c at yKv2zeyt_7Go_UB
z?X(2`=@ei$Ga4pMRcgl`Fyu?8fWwf}EP)@K0?CHFY)L7Pqs(n740Y2?IxeSx!;sYw
zcpOt*SEf_IVaQ{aKrg3&orK9x|LI0eZb~WTtG5L5oB|F*eglDBgJDR%Q@~+J{tP29
z)G3f`$ZAV!SV}47d&CkL?i6qsk~<UU&mk~mFQ<URkTsS-nNuLykl$HS<te3<Z^$f@
z&N!!l!;lsTtQ-nM0!{&kA<tO?)13mzh7?s8H8WF6Dc?p*pu#EOFyvJT3?2YODm~ro
zu4hKtkp~#wawpI3&qk`%k~*qmDd%|nv?agFDbJiKU%vxQieV=&o}!itSyHPzmNISk
zZisp-k-bwrjyZ8(AD}Sd(>>;b$9D{ZPZK)JDVhHgpgm^;zS#2`Ow?CL`6Gb{dZ~xk
z=6VF`*97#pl-=QROrG;!0W at k3;D at 9RjPSld&L#R}g7D>lb`gHsDeRuB)O<MCADzPe
zmI1nz at bgYM{~<uV=K+4nsbdI`7NV~i;V)3)D*tpqZxjBrhk(i8KP~hv&#*izgV~EQ
z82`o%*&E&YryYcNaISZq at pf702ab68a}LI&49 at kDQ}#v+{lp>L?>nHg4uS07wV5h^
zE<%?O`Bt){YqsBYK)xWF>D7gu)HnKlYYBLh1ysKS=9|b_h9^yo-9q)-1m1gauE9=T
zybUJ$RKLGLcHW_oAM#V=^P~y)t44$!j5OR4N%eaI(2xay_cAa?1l6w`kierIaNhms
zwyNLF7H^i5mp72S5esp71m~J<cs$+aY2Gy!Z=RE<b at p4NR1=(Qv4f}joovBJIbdVP
z_ZBbY<msehhvA9_&K1@?)$i{J&07p)wUK6_s{ULtT2=thzJ*Ht1+G8WyjDR_c|G^z
z=yI)b_k9JPd{mX|2)8 at 87*SN;Q3&$xiEF6^4H!jnED2sj*!@>e{uAQCx at ESPtA2Us
zA!Z&|CRO(FNQJ9_?$12-Dx3QgPj&`MnCq7AU7q|Zu6$6YM^f~>{X|DOWUqpZ`yZZu
zci=jEK?eMNygC_4P}0i(5<IRrxcB!G$lJ~g<d@@$`&>BpOs~gAeLH~k>jv~jNi!pE
zvm~mE-gglsMC#VmQc?-Nd09%`4Cj7L(#?>_I(6SY7Vpo7$0&xEpN&g at IQKhZSwg(~
zE#3!)7mp`3cOc3m+cQEB8t%V)P#t+FLYF%;Q|h`B0TH|l1(N*|rjGZrWW1TE?s+2k
zrMLHyEObvdSME%fl&=oKGYI8$dkod)$~}nn_$<6CyAoch$8WsZhr`b$3-@<k-!>~w
z&u(AE<G7HX%H|3u$29l1-t0Q~xg6sD-s^h{RO&m|q{HO%*6?rzBlaB)Q>Bvo8{6_|
zk4PxraxkTq2X<o=ZKdja2H=~S#U;)-y5X}hvfCgmE$-i5l))f~y4+8?2MX^D at Wj$T
zxK-vuVC8t86M=tav at cEF{<CS4l<C(Z-&Y#(rcAqb`frBP!+{$4ldL+pAQS5E7V(PA
z{w&xp5wPQlxXNCSMlb3sDgKR!Ka-J<`*dnQIQL&Nf{@7DhUkvk!Q#-l;M!WVnX}6&
z{~~V#RKn-Ve84q`UHD7{RR1;5vYAmhLTrUcmfD#z<W%<Wz#fKPkU0kH?xW#xW%hMv
z&4%YD$Y=I*yYde~U_C|laPNY2?rmZcQ{aMqW`B2o`dQAB>;(X!cnJEz*W?#NaRz!x
zvSO8A2-GN^3+deZ|GQ$2W(RafnY*vb>XwBo1=Vd6kG at -aq9^x4Iee5gix&{Ndvo~r
z4F)9e-?Hii9wYE+fOk=PXV&i=(%)F{S6P3JOZN at +*4JL{Z?m-Cyb09O|9Bi;1y8E>
z&+woIUKHaF%Nl%Wj#3nGw`Hk}J%5jods$ZQC(L60+XyY_0i;=s)oAwT;7PYTJS%?*
zxFQh~yL11;c-ddzD4lFcmL$$HAHuok3lP_(|0;d3<0DX)`{=BpJPlX|oS2o{i<al(
z)~Hs0vE*N)**@^ZfMc`r>nw?FQWUv+GF~=sD~JKdWl5$J4A8BP2Dns#XIvlDsQ2+<
zylJxv(Y!A>?%8x-4emOk7@`W<GTD^8Pj+7myn*;~ch>NA2zdYE$~_T)(xJC?DDN~v
zBhG{XZ$Nn8J0D>uOG|%fAP!V{RBN>S-GQqS&oj+jXxa55ulRDg(y9vIf}ghqyw4O`
z<DB=Y5rcv727&i0hwO;MiBk4!CweImuE~49bE0nn;T-|*57T&AXHuI`h$M+V>stcC
z`vG2;%OT;r7!a58y_pH{yMVZq at 9mZV4+q4hd~c46`8LV;f`GY{@9mWUUjv9kuD4GD
z{2^ejihKLI*uyO)djsOCxEFUA_q1SLyoJ_j!21W^8i;T~+dHV8nC}MQTw(PNckq<&
zZ-BUz>fI*+9s`Jr8QxMCYsJ{nw*k<dgmF(>+K9HH at 1wvx7>vF9CgMI|Tte~AuyD2-
z<vSEOS7^KkyWWrIhvT*=G&!?QFW%>TTOiEE8t)PpZ-;4n9J0Q at fXOREZ_vfwX#^;%
zd?SDhFYM&8lC%abwbGJ`bS&je at fJ(I)hW-0t9*aAc*i(- at f5XG8Af2S>%@+wbW!+X
z5an`__Y7x&(QqShpCxd<Q(%f!qRRJ`C9u^gKtr6F8jmqp(%GI;O8H_C;Bt}oMyG(o
zkOwS*JDdUzL%y~I?sEzx8!`!5lXM<UDW!btA;9G#@6%2Jhat~f0xviP9ESAAU?3V^
zaS9|GQe{cKl~PLiZh`=pi at YB>1ssO_XbF7o6mS?)fi55#b~y!-4LR46`ZlGM^1TWH
zE*E(-+>TD=Fl0QKB9P-0a2T at D63BB3BpdQ4OKOjlQpz_7OGR8R@(y<jI1E{535<3M
zI1G8*5-4{HBpcGZz@#%drBsS5G&OP(2JgK*)rjfp_WQkKpxfZOJ)gIY!@+irPI7X*
zis;itw}AYS-WNC==PkuKLk_CwIiUX_=cQ!ME}-nz-CpBJly{ST;CQBr1`pFGgl=yz
zENoRY9U%K%x4$HcYm17)V4nxq?akY$O%5WcRc;20!)dp-Q?efbTXOk9oGocHJF4hi
zuruN7_R&$pp_~U*NYi@|{6kSb$W(eimh20^XdZwTf}ctxt?2{+Hxv9!$|SCCpL>D6
zM$YF1?Mr7h^7;|j=ao4U2hUzOY{UU`>Vr@{?mmvouGCX{S2iz at WJ>SL#I`Q~o3MIR
zRyi{_Dl70;hPuy^Q1^;&By>RE5`qVo3aP9RGJA!PIjutGo-btHEkX`@T*$$12|45o
zA at h5cQp=&mLKYk-WZ`lli`s-7cD|6s*9%$ln2 at Ef30byF$dTR3przMV?9c<bc$AP!
zrU=<~ppeUs5OR5~kSkh+Y(HJdRhJ04`dT5^+%DwW2Zdb!q>vk45OU+2LT>u2kXv>M
zx%EFnex2oK>bLoX+%ZJRo%;y6Yn+fBQ-$0!N65V^gxtSI$OEk;gKMOa2iNjG?x?|`
zn}n=<Nl5s6A*=hAlecE1kcJ6DA_od-suQyIG$GBG35ne&r1d2s>v*en)Zk;Y$C4b^
zSIF_hglr55IboKN6Au$|>KY+uHVZk6_i0BBKKmje=Uy%3yd6R|KP_ZS#yE;xG*rm1
z#tFH&LddqoLN09*a`~x3wqGjb$~%Qz^@fnE{~_d>?&G1Xu%T2);}sJaibyFHuKiv@
z&3OTW(cwa3<At;wCZx4qNZUz5)@>KE{$3#){v_n+Arl$>n8`wpT`c6dHX+CJ=H#ft
zjaLgf;SnJxzAWUV&xM@)qmWbbCsFd$(Lzp}E9CTukTcE{a^|%{&ib8 at vtJc*&Idxy
z-6`Ze*JNthlqclEp+YuK60&89kc+}Xes#Q%t!E0kbeoXNuM at KUULjXLE#%sFg<Q8w
z$n_cfGKCxZl8jtAO313ILc)uLtPTrVbDWU+3xzb?Af)kOA(0n_G<_^&?GHkl`%a<G
z=qMqvX(W5^zgWoBdLh$J6f*s4Av5k1GV at s>v)&g{@oymq^w^Kl4;&_>a)OZAbA`-V
zA!Kfgka=ecIp_)@2j4H`kUt2S|BjGDzZ9~d`~J{b(lSU$t2CmLwmJ!|6FW=ROFJvs
z at TGu9=S*dUV+w^FyT6d*ju3MEdLbJ(2|3|rAtyd5<fPYxoV-iODOuB~<<ucUP8%oW
z^a>$oEE96(S|MkhE#&O0gq(Aqkn>&=a{lK+F3g at zWm`rFxoEPGUmYf7>lz^!pDN^%
zONDH^Q^=*y3c2iKA(y*nP|FpAg>1+6S%j{fFXXC-kgHD-a?M3TuDwObb-x#K{rf_0
z_>Yhq2h3#jo5l*cxk|__%|dQHNyx7+7joMpLT-Os$Q|DZxs$ieMwQ$>Q^-9B3%R#e
z$b+py9y(3P!<T`K-l_BttB_c#{(TLWd*IxMW^!6HW`7rMP}JJt{#5{ZsgJYaKOp9E
zW1*@C_-3IhYc$T(4;=u$ED6doqP0*(eO&%R)G3IOv^dolF=cUzDahg!J=WsXXlv`f
zwsJe-p9z=wf=jI23l_bv!@TT_TUm(4ubu*D?2A~4*x4Hk5uVA#-Ex&;JkJzW%x$e~
zxt{&9N^*gFrsp1kGjbmJd1R>J0?&5|u0{-l5U-~_i^z559tCMNVm1)29C(&6qJ>6*
zaE-uoqyv>%#>GIfIlCOfWxNb8I|4!XOytAsD&;~==@hU^7m&}OUxF->GWz`VIoCN0
zPXyr3!1_*!I~$~1R_VDw%KcmjcORSy8?yYoH1uB!xQu8SCqtz>806Al=_B-Ut<HTe
z$|TD*mUnW-y$ZCy8h<6BZewYsKpCo(Yi|DI0r<aWO!`XQD2y^P+|Twvl9{DklJiRj
zn3d8(@`;sl!*Z#gLHhg>WM%m)h;d7T{}B3!P2i!Fn<z?ah|yQZtJXqR0atpx&y^la
z&VGX+!x_E*YzD>0Ln(uP&IbM0l0jc7eWl`KN`6V?338cnKYf1sN+n2(3c1c3U5r8=
zUbqYFW8uxtb)Nx}nH$&wl2eH}h02oy*JE`H3S3Io?3Ao)$T~!p805f)q5?M)JuDG5
zy6z%tZX!zs9w53f5j7DWC+k3&^NUFiyPhWNAYn0GY4j at aJkdposL}O0SqCSwRN!5r
z%UBnAb{=$ui64`7IOgot@!U&v=~@%>z#2#PL2=W`R)Kwi=FAtJanmNw1iFgyi{kQ9
zViTKyUP#WeI7e&R1~g|$vZkwmK1um-Twa&`vy at +&jJ`~iGfh*w at k|u`1+4!g`%sCb
zQ~jL40y|YzIJ``$uK at NO;{G1Q>na=%Bx?!oG7oX*f_U6=b<+>t+#!Vvz#IZ^pCRtO
z$jmC_meFzW<_#^3fH?(T-%xi2NH=%k2|yOX+jppYIg!l53xTYLH-D%*N+he0^Z7I3
z?YCzk=k&j#cSs at U_1Drnw2*WAyXY+_<oy0IdWRKqj{h9Jg at v5wzfJG(LeBO7PVWfO
z`#rryqBjeJM8ADRZ$7=FL~kLzqeX8iy<<f06ncwA?;LtdMDG%MOA8M}Y1hF!pg=la
z1m6CB8R$-cci<2~&w_W40zo&!JE)-WY(%>p-aQvj@?`C~u=pDIStolgQpGn~{=+g=
z;oT6tm4eGAd2;t$B7*GUdmf<$#lJL56}}C at 9Tcph;87yT`q?w61;xK2O9dXH(5XFf
zMWDNq`!N8SS%IgBpC(Plv at rswGXc}*UL<f96=|U8bpY=Yyw+BiR|UnYl#Q(DuVDRy
z?CUmKscE+RUqCZ61K*Q*BS$GwsF{Jxr9iK@(-kyNH`pAqZm}(JvV3IS#xqP at mx(oq
ztUKA(l39~SkaZQ6m+V9DHF<2LDo~2R5MIdX(NPZ+B@>8_l93agpMfG<L<MFL7%e~?
z-FFVqJx>bECpkq*_as~~snXMNoU-5HgwNM@?sp^uPa31E8Msh7t5io(7{FSBk2vaR
z9f5Nsxx{f(EYAB}lKKM2{Uwquqe?b1=5~D+kP$!*5 at F)0;GG9Iv`LDZ2Nk%G5jIP;
z at Sp-)32co^OuQVx4UE>pi`Tq3CvXczxA4j~&!ONBq8BI2-b?gSJCC~P0}m6uT+nB6
zk*F(@CacmH5qAF;d{1WJj}&`C#H8rRQ-PO=UM3k#iX3>8tjC2V5k}&gQzuzE3f?j*
zD4Y!6|3R?evb{W?f^IE1u6P&dxCy|HSH)k!&om1*W)**J`A_Ik{2lxpKnqUHEp{(6
z{*&^Gv*4e^xF-)N9tyw2J*B9)2!7UO!RckiW$-Vf%o!7l1Msh*|IBH{`@w$-{byAc
z*TDZM{b$cFUJbwKJa0*HBm93RzG+qQaqx@&^P7rKg#Sb0n`6bN!@raMEp5f;!Y^^R
zt}DL4lHYcE at izE*^<8l3CRNIzeJ at WBK)D4+7W+UY`^#1FKr6~oS*mme<aJ|XPE=`A
zLRg=BX^$#BlN_qojZl2TDZB~bOeiflwD4|t=fFGcKsnnS0dN13(%&&EWpz|`5Z!G`
z-vMWj7D$biQxRu|84kZo1+E5j_<0h!XMlF_ at -J``(F@{e$sGjl%%g}HtpfKExyu%b
zXT>zpN6Ft7=hLdGD)1EHE0f`A&k;UYZeD0j(gsbO*U8)=aqJNQs@^4hx4 at ERBmGyx
zk0hp$_le}~a~!98c0yplj3026(QQW7k=mCzBM&~-Q`U?T#+R$6mBTyy5N(>|UlJ3A
z(<YO*K=W)HbYjzHkauXRENOwjJPJITm at UIPjI0aoJgC4j0$U{aa&WM!$kHQ394%T2
zw2_?41Qg?>f&($4*TqEx>j~T}fCD{_=)=kADMT-q%3(q2aaDq%yyz_OFQm-10@@Q-
zEvOB+g#68RQhBFLV!LC54_rl-oPcywli`t)DsTf?SI1*LD6t;Ju}q at gPX09#L6RxC
zhrsQkN0mIxz_~gQc#?rlwkj2PhQRr8pyWjYH_EW8irzrrT>=+Vu^ww#o~r00p#LD}
zibRe{=ig-gTGWbs;0FS?*?`tR*|QwzJ=75BN$*2;HLJ;e30%(@fx-0N5a$Jk5xB$F
zHdRgAo5*}ebCgyZC?R~4LohI&$Ss2KpaT05xYZWH>6^fBY(TfmqB%ep!;N at 39=GTy
z0ILc9*#R~KIF8`E4)9a}7ZCi&0bT;&I)Z<9fWHRt0KqRD;Nt-PMDQC2_$q++3H}%d
z^FIafFM=Lj7-XsZAAoc}3TTcK%>y!oXdfrK7m%?;2RP9wKq`rjaH8{p97%MP11+qY
zqEs!=y$a+aVGX?fn+n^29u4n48a)NxqJ0X_0lF35Q3Zut;k}aRXt_eT3*P?4MUQ|y
z12=lC<dREus_10^?-88j06zurZ at 4k#4p0Sg6$3YVssro?U^v0K4sZ+reDP0>KGXru
z0B{Jw!yVuf03m|Q9bhAXqY2hHz>@)-PcZBNF9C2p!H5IA9l#?5TO8n10A3|nVS{;G
zMOA@!h+am&>8c+A_=4ckETKGIOy2{@UIFlgI2gzSFlN0C<Z*QteT?YQ^lOEMd+m>E
z1z22A=!dri-u{OcPJwqiy@$;7Z0tX;_#pU~0_%T}DqaFV=X(7QMgy9HVL}#PHu6>>
zI1@|f7KcEYlhS#rxZd&~lvy0L{0C<hA8q*$=}~-=<)5Ehe5U0;v~TeRmVd#3;!7<5
z!okH?S^h-@#W%yxF|qWpqT;*Z=kQUwxJ(5eMxbn^6sU|{oay15`Xu31?chHVjtVSO
zMj6~ql-I~>O^jkrWABl*E=4rM{~P%+;mb_ZX#9e(9<OZMOpNcz(gT+r!>~M6U{y<v
zGL{PTAW$Rr%E2~K1$<=HiY%wJX1v~mXee%uRx^xfogLX+knBw~>`1Mcz}jS$V~Ms1
z>X6-+=q9;Jlw6!P4fdAO$iNJ;Zj&p-I4dxl=pAxt=s*u8dZC>1Y}A;ygsdHM&5_Jn
zLDm+zG)!jURd}lG9=SA3X00V_W4tiQSAlgzPfJA2{BI*!$0V{;;54GAB%&t5d1M_I
zFMXZDMMRHJMlUCNY9eaXTu0Wq(m*8{$q0jL;;+Ga9?pMu+yJ>Gn)n*f at 5#9^&XM#d
zW>#ZY6P*8&I7i1R1-g)&E8`p;XDQI*$hjfTk!B`l1WpC3>;$_D<>`!`OY~$LRe>!8
z&b9#~b}7;G<9a1~(tZM0ll7~Vg>o}lTa#jGYwjZJ;*_k1$V$q$F6E-%g7qh|PZR?s
zdfe2*XR<vXiDMb>Ed^eqWR-LPnx_J95ztp1L{;De0*zw(W{G?;Bl9*@;BRED5#=(A
z72o|LB>Y|E*T>CB5(<1v{?Wph$&=KC#1FV at z>-_3d6I*HvoIDo^ix%!2Zhdz$KO9m
zh&3>|AB9#kFM*-->RF#uj-G?<O;pd)iDIZNA<`^`A`L1KAh01`e>&ncqWU^YM?~`a
zhkW7o&*9)#!j)%K5Pqzd-cNBq=K%NlE1qL0^IR;xAE>}Cpagygjz at r9LVlG^#?uGX
zwYWcc8 at zaX3MS<04Jh~$%Elal0AE4kdLu)g<fz<aB6XKYc$uqO-vg13F_FGOq&Y#L
zs`7awnJ1F1z&25GkV~tl<bnNh;Ef{w=G at NP9F^PY#}9XaVAZXN_Mcoty8=O4CDEP&
zYDH6(w^JNHZPGj7Z5 at ahj{{<iA867ppsMmw9Qb2g*Wzq2=I;T?|3i?H83)2ssbC;~
zd&9XFmp~|jEX<BM?Y;==dWjTtFJuCz;GinYOk8dJYG65x`>-=^qVdyA44<TSDPqiI
zjCVVVG3PNR<e!bYox8%s)fwM~;v19UR*G+lale_tn|pH>Lr(es0dE<bLn(V*DQ}|4
z9UZv~1hW at TucWG;a3~LjYLXu at m-31~14sI>{af)hE-XTp02>c$m{>k&f4Bi~+s_==
z`(yVLXOHcF?o(HP at wZ;zocH3Q^BTVY;MzGCHJ$tBrsIzPX3n_p`W{uXpzg{A7hLVG
z8#Hg`x{;qh^5%~2Paf<GZw&ou)6xIj<CL%0-T&YK&xUiGih}2FIp&<XO}!VK^tY=Y
zDx2*8VC|>t{^{xe%m^4c4sI6QBDh*OR at KRHo8hj3+X44mxR>ERg!>XM69v^5ZUo#o
zxLI(E;A-Jwa3{lUhPwuC2b?^wi+r&Q at yFY!P@|+eK=b$0VT;d=;N(lg1C>`nfU-aG
z#~Y*MO9g at Q=`e=bBlweN^FZ0s_~T7fr#x@}GAx}2RGw)AWn<(|o>c>tb_vQ`zm&J^
z<@0|GTl%?qongyfjx7w|HVX&*c&nLVE4^I@>9D1rPtcKXrO!?L470WKCl5A*%GdzP
z4gO9($1{el^!SPlhOP3F=jjl%%7+h2lW*y>+OWg{p4^7nJ}sFH at aa;?09L4O6<c_E
zPSee&=ltQC3-VY5i{Ma%Dh$UoIMw7Y1jleW1Nc1z#SGuVj)0$)=4AL|aD55l$Mo5^
zGL%Q*VG_ZZE^*r04V3+w9F8XJV~k6+gWv|kQEn(`0o-snj#%vPW8hGHssyeK&JV{m
zaGAS-V(~=c?hA at y6#rDvX~sVTl+`vH4$V^d^FbHDVKG-730Dor^jRh=jh|tb&l<RT
zxJI}L+*-J1xG3DW%WvIh)F+i!bQ|zsN$%7K`@MPnq~*74y7rW5lMX#==RSF*HyoXF
z$ES14 at 4Id4zXI-y4(rqW*+)b6c)$PDk9W?#V$icMWuAZ6=3{=J+wZ+0I~Oipz4f|N
zw!OEucmEsS8g=cRCm*x_mInsB`rdIHu6sG_vfLi6JGwo5`7vc1PtUn@<z?&p&dk65
zkB5JK#VfbHJ!(?z_h&~}uYBbD+b$e@@SKWix%2PYmbHG>b$=iBS+7 at iF3nwj_SSOW
z{D#jyEesy>%9alXU-b5mqyDqu^WQCtp8aO+dw-hoe;+M4YvInO&u)ME!$Tj~{L;#r
zf-T1s-*El|s|!EtwYYCdpK~ssd&R at YjQ?)m%2lWIKH!E^{`KDA74ska*MIH|R*!r5
zs)_rY|G`sdMT;-kaN${JZG85^DR<Tlel&N(@^?pN?&sS7n39&S{g36iuXuMsp9^<A
zKj_{u`BO($-}B7UX+uZ8J!$19d+qbWgY)lv?e%T%E%F??`kB2yDV{Vr`{@VI{!8_#
z=j^?@=!WURSO4_zmS?^ga$DxK?bko^%?nF^?795og?(Da^_%+G*4L-sykS=C)}vqf
z?wW14k1H7T*?HHkKSJdWKj-4J7u<jK2Vbpne^)fGch<tvfd$L<`)2%)P5=J#ot9B=
zZr*h1X@?HXS at r(Nx)c5L&zkx4O|A>>yKUJ%M^Cx(_DrSTf!hV=@!+-xTsa(G-lmqo
zt${lZ?tHjw;O>R{1KeA1JK-{LQt1b`58M>EL*T06THsEH+XnY*xX0jLhU<flF#;|C
z7ldnuI|Xhl+|6*0z`X$XA>6;=y5oekCtMlaOt{5xO>if{T?BU{+(U5B!MzXn6<iih
zZiC=T;HJYZf?El<0qz{Q?QnO&Jqh;)+-Gn+A?BgOj)a>CHy7?GxV3O6!~F{GCb);;
zo`?GY?q6`(=-_-O-dwn&;MT&O4EHOzo8W#6_bpsc3|0kjW8n^fI|8mA?s&Kh;I4(c
z5AGSbx8eQ?SAY|GCEPN&Mz|B;Hp5*H_W<0paPPu>0q4bdJP__#3__?D#kb}3!w`k>
z2BZ$t0uVl61;QstK=|WbaSnI9O>H1<yCB4^v<Bi+GSI8|IxRrcFnAdbH~LVR8$~FA
zAMZ31;*Ccm#k<~wxI@)IyuVI}x4#X<O&)~)8c(=ng@(AEW2EHGVvypCV+_Qb?~KSh
z<pz>{Pk at HQE>6wx<2`gyAD7||07ASoZz6Kz03qJOH_!?M35|jq0f%1^rcH$SmNp|L
z4}b#V793L&ywOf6ZlX0(yk|^^D+NXu at 8T2UZd@b9+jN9 at Q^!Dj#*GlS{Fn^!CLST)
z*fY at d6&m8Amx;(d4V2=df=Q8kz0kE3pCiVf53+*r>0uB)7!1N4Odxz37KGDP5dOH`
zi28WJWAt$~ln at t5jT9eg%LK%CIRWDHuK4pQK at dLv2f`m8qhwS*nQ0(yWgwIlFE#E>
zAjDlEMvB`j2yqLvfw=pO5GTq8;`RkX+_7vR?ja(?RT*Rdh!q;*b*Yi!+Yl+mw>6rw
z<<1d8yccRBa(@LO?wK|b`ASDZkHMLU@?JUw`Mx?M#fRM3NFLOUn9r&i4%d(wpG(V@
zEeI0g?lsf0xJir<?+hAS<S|r0r=lcH!rWm(Deee2x_IZ45O0(kDL&dsh#SL<daiU6
z;)<$?$PIIZxHM`~<lSmQybLxFUx`WRcsQfJ0bYp+YSeSL4I%D=G3vRKju6+kj4m#r
z6XMFck>Yk0LfnpSAbETi5I5GD6nWE?QoO%pq_}s75V!Lf_1qdnh`WUh)T2;Cd_uuQ
z<U2Mg^&^~7&;2Qcc+1~NaU&2R-k3DHhM|KI;u{K#6gTD&^2H;{<K=*AAY#<>h6AN|
zAHqbeF3=EPGhn2+Cy7$rGGwH<Cy@}BJPgFmM1=SdfPrK$DWH!rni*ZZ+d(O=X&5Pa
zG#b!USZ}1b!;~kMFW?}>R|J6Yfo=SQI+xs(iV%PDs5j^x7+j17c|03XZd at rJR%X(C
z5Z^@PGpvNTnb5Qs?mQyI2M&xBw<r<f&Lso!U89V^{eytG at zQW)-y%4OLx}G&0O7Oa
zAbe5^gpa+0aIYf>e|$Rvli>Rj48(m;g!ssVfw+T{5O36*s+U(d0D2ikWU|f;V-hi5
z5!~HHh)-r1UGl^>pdkb8h}<ebDefRJQru%ki0i#3#j6T5#4VOaiW^ZW#bstARlPz(
zT-!5t at t!)Rc!%9UzcKYZ3_}!j at f|Ao^D!Iz`6>YrJ`oDSpFEBZ%B`D#_^>+2T;u?R
zn?#Kq_lYqjJ|AKr?s_A{Csi!SNO6tbSj~MCl;U;@BgI>8gm?$ZK=P&lK<~wy8#kOu
z#CVF_J4a|&JVox!BgAKDj4pYM8xVKTnnD?5`WBzDGL2FmQG(Q;hucyJS-)y{T*@`w
z3LnEX at N3dUmR;aAr~yGX8860U{@U at k3#>0GQ}J&%{Ep&3YWSG#^4CuP^BR}S)l~eQ
zhTl<qOXJ=W+0{<JbAc_D{%IzLDff2qR~V$D{52VVNA{sh%Fnf7fpV?Ob>;TxmbD3S
z*w_Zc<xb*7 at Q*+C(PC)Vy>d@=&+Lh5jQl7!3ogsZ89P$S)kALQM6HiY0P;(rZ!;LL
z8 at b)-dkAum8ab1{l<9s5xf_feI<fwxNVf;_z5OTX8wa`5jU4M$ewMx&C!uTT@;ef8
zn~dD<^2?>Ybw<wAbIN?&0=Xt5x4UxTvfvUU*HO8!ZuxU<m_JWyzT37;1aqzW$0#Xn
zVEY7JU+lm9W#t&fR(>mVet8+2sYaq%xLmI9di5lM8EpQp(&<f2_2HVTSQy{rC|yz$
zsSTA>H8qvaj5Ol=ZLw(StWayH9v{(aE?pFf)Z_bCVM}gSsIID|K31|0-(NGF(w1m*
zX?3`<w4|go+*niJQX49*89llb=b&F8q55!jX$`)pwX)RjFDWY-YbE(}(wbji6|0Lh
zH$+Phs;W6;;gXUj12{6iaMoO#9j#p>nKZfkA0}0bPw15f`CX^z|1#D8eTw0+6DRyH
zb7($j_%j-4nvI4vi3Lji=^AvxhEPMKc|E&hG*(+1sw-K=^S1sFT60wxAJ7Af-!cm0
ztEu?rxO~V at i}UL@!Pao7jX`|K(AJ4>AX1eD(;wu=CCztNbrKMg&*w<W^Z~{QsZsc;
z6W=$&mpKu at 5JaU2TR1<OsTq{wm)YVWem2vD_}MnC0#ouJLnfjXG%>B9iHe|34r*YO
zZinz=7_&d4=}197rfI at RLO!I4przCiW-c&vFc;bfF(#nf0Rk8<Z3c^gW<-pT^gsBq
zawnw`F=}i9`SO|;uF+p%qYC})JHRYO^K~}jmO7?yzPl#nMzgh8Qc!EwEbX^Gxn`9&
z)bmqS(9UmTS at M7qz2MhHBIPADO-(#^gd@?qwpzwgndK_m%o}kVz|*_?7oMIcd5`ss
z at Xq&Scu(}WyjebP#`+JB&RD-B)8)Y%9Ny at b74t0XKF6anespEs;t7a%hwA~)Ao%w7
zF7cF>c)FKlx+(mQcZ#Q^`&`JLe*6QT;_fl($oOd8CeI-d4tSSnv9FKIs`Gfdw+Q!F
z8Jj$Px^MDKfT}(*&(JxZ2{G!5?eg?Pq(Z<<(mTU54Rl{h&CzPUIXbHZQRif4B9X6-
zet;_7Zkz#;(K;M@;O at mCptv$Bt^h^B7mqh|I4I8L#e+d{t}gBliux;l8*x$p#jk*(
ztrXt_idI>CEhyt(1d0kRJ{A;ni{dsN&OZ_qtDeP+Krv at 4o^I$QP|Pj(cs}Fh7l9(F
zVlxjY<~%SL;l~dU+<U5_iwqrL=ob~5|FogMGIWKZ6AX13diyLbe>kp$k)HRCQJN0X
z>3cT<B)-DXX@(XUN+$l^ca8j`hHf`>qoFGdon~l(p}73wK<7o?IEP2kXni>V5k6>~
zSBKZ4P<kODX{eC-0FL2JjDX)?Q7OF;$GUDg9)9wl*KFlC;q4|2mhf*kVXpd6{!tS?
z6 at G@9IsRPK5C2XbRBsr*b$w85!qbfWJR`rtgh!dMHQzrL;ogQvmHEh at BdA6uh3`uW
zKZX1_<zIk4XSipQJWdQt51zX)h7Z#F{rH%7O{AfzITVeCYVis0aPw?_x4ax*zYW)z
z6UgiuLVo>yT{#2I#<%2vO_Fc_;#0%T1S-Y{@j=|C3Vh(bVtic~->R;_2Y=&fm6x|m
zD;TN|HKd*3yl`2?ylQ+ at 9R}bNjftstGAokzuF&M4Bt`}0quAD0`?^Fi>JPc?Qk4_6
zN`B+JEA^rX!qFhLc16a=;e+>8Mv-a7oocSL{8S<zXXRI)4{PMtgo6u0(H49|lI=Df
z<r8q#6l$!k;8)+%)zvhwOVrHtS1g!|&grn{zkDY$Zuq<ozPlKg at c*>0MIyp4 at J-C%
p%6034xG0TA8Zo1dtq<ZE)B|VE#D}(PLQVMUa1}ljUdFNY{{dwE)z<(3

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/X86/Inputs/String/foo3.o b/llvm/test/tools/dsymutil/X86/Inputs/String/foo3.o
new file mode 100644
index 0000000000000000000000000000000000000000..9b3a9acd4a6cd0a47666d4f21cf647ed8fef2791
GIT binary patch
literal 61128
zcmcg#34Bz={h!@rH{lAqgiAmO5)eZU5+H}7z(SNu2!u-%mmC`s$whXP08+&p1Qook
z_l;LQiuYNywN|UxR;#UNJ!(B#>Q%45{=eVf%zOKGlUU7$zR%A7X1>4Q{N^{un>TOX
zym`-m{qc7xO1Y90{@{|~)_d at m0f%EhxGxEIaUA!$W?alTIIJ*qD!TpzaRh^r(E5n>
z>+q7&6-%OF%h$`TebmQfliyKle?rM>Gl_KsgKMg)f}!<Qq2@?1Qc)QU#_H>9^!QAK
z>tKw5EEO>{7_16MTIw3t7&Knrh&X+_nK{Q1uR9p54pp|U2|}qz1%tDe&sco89V6RB
zsHxS^lX3ch#;COP)i+gjs_)$6w4QcWB#x|RO&$N8>Z_=%Yzeioeq!zG)u>~BYU=*#
zutSsfcB-$gv8IXaczxgMVo-hO>B#4=*YqRQ??CPCR9{0ym8gu at m->i~#5T+0swXsc
z{Kx65Xl||#1sf|GLd;6MzFtP(9#ei-|44mJmB&>v&3JvU{7PGrsfk+ml<`DK*Y-76
zRK at H2Kcmk&g)aD!`XU>eJI(L9$F(7UNz=5~Z=;48Uz~kaO%1Rs5^Qa3uWPIh2ItRm
z#wdG1hgO?d at 4uuJi*ozBN)6JiIDMhoU`-2ZLo?&gw>$o*@nTaSvtQBrCcmfqsXj`X
zGslXr&$s%zM$s5wezb?j$>u!U{HhL5HTn>Wv9AEYP&jE{{d=oqI35%tJ`3 at NgMRjR
zrT*kq3ihZnI35Fxqb%FDNfN#ve=ME7_1*H>r+hSY_SWxapS9}E*<0UupRsM~#LhbO
zBiK26>u>TOixoQM$)QKDdSdq0CuX1Zvo~W{{rlA9_8)bs7}S5%bj9>m{e!`p{-aQ{
z49`Am%1-DtutVJN<K<^8E1$FVi`iShk(B0d{g0L6e4>vZJ>ys%qpS4d^~Hy0KXrt3
z=b)*yboNtHva6oxKT7PC<jz!?u2oO$=rliDzohJD#wFjF_moM;kwIM^v*YB;%dEVi
z7G|IFWa_DpMN*E|u?<1t=`xM#-!|Q6?9u6+wcgb+!OqK{>BH9VzjyUzqZ^t!Uu6W8
znlM52&M23wRYAtsu$sZ1Eu*TwqH#?|Tc{;m*VLGipPxH1cT&c9L38r+Cr)CxAa_d1
zL8_*yX;N-gbF<1 at 8isgYWouo1b-2EwEtFT$R*wsHIFiRdUc7ik3`eTbzvZjSif~<(
z0jE~gR<vYifOYV};2nH0!@)>PMO`E;yu+N#ih5kPDk4oSnw4=F^f|Q!(YZ7<HBODR
zw1&W2xnN#-WD?XC<aa7JXMSaVX=%Yk3 at U0{n%aZ)p~f|l+F+=qrKzQ~4Z1tRKV4~4
zYb4lI6Kp}Lh8#+ru&Qiosz-9++NPFBu%RNnR)y;}hJx&Lm7Qm+RH9{Nv!cbZa)Hiq
zexc1Y@#ZWj50=>AoT}2&(qa<~l`bwX2sT(rg;aA>U1KEF0+WnSOzBWpwl+I`)}9J3
zX|_~ZH5Cmz3NXf+qKfM3mQXlcy0}UiuWAX^gjzz4RiXbLX<n78YHCDVvrN~a7!A5)
zVp5HkKttKQHdE at Vz6obQYh$=>O=GA!14R)ve`;G(U9~i=PPFAutPa^lT2|GdqQS0m
zP~1?lKFG>O)3Cgh?L>P~HO{4$rVXWKRZuKm6`a+qq?N?hRIsk0`6pIhc7{G_>^jx0
z4~^1liBr35c-a{&F-t>m2G3Gmh%CF{th$<-C2Y!ezPi&oSwFf`Sp{}IW56x-?gXVd
zW at P<9&yk%`Q&AsgA5n&ZwcW_0-A+c9qmuI{$4bm8t18W(Xk$%mv(XT(tgefo_pGR&
zD#<tvvE^dYV&~Ub5y{Tr351jbtUdrLIHv~ZQ*EdbCqpI1OH(Dc8F8)fN0nzx>*NW~
z7Wxyb#A>3Yi|0YXPmDdOC>*K}Vd&S?$V!V;V2srQU-JfChb^sDEH$J1N6G#~3-Zy`
z+b5{>d1zJW7xRnQ->qq>sMnTMG)CrB%Eh4+^<c$NJVW$p(LsDFyKw6aXsf7ib at o|Z
ztFLOS#EIY39BScJEkmvY65Bfaa22vTgCAMRQG0c-{)0K3h^v5-Hu}T)vd$L!irPh%
zpigJ%r(10|tskxr)9`SW)cs~R%EyXY+I31Smu at xj5_Fh9s*!h{Hijft+CNU$Pb`8-
zJz%4we1h!z^`IpfY(bxZQ>dYtm+}yL>594*$92OwR_idD_-P|Q_Lwc9W at p!GU%Kq!
zNC#VjsGEj;Y|zB$#U-fEWt0g_#XkpmEG`yOMKjAvuCAcf6_E-F6XP&Y+2apArV7 at t
z2W!US#WRiymd{yP8eDQzS!s|_I81A)XvcqhQ%iLiG_C?9)6qs!P|&#q2Z;Fv&MKNy
zMJV4<F&s7miy1?emQIoUmCmo5SUSHFO#|UIp@<B2L7B2O4*%aJEhCRP)hM)?6^(&V
zX+v{lL!cszZn at LqakPoJW|W<gZ}sbTr}jfd7+W^;>+(@1IHjXy@}o-QM`$qv{h|&T
zO1L7+rvyu<)YP?vS%*R$b(p`e6SPZtU!_zS4snQvylKz>Aal_q_j&FnhubTfap^A(
zD*7;b%!eybjm=Hrm|JgE*N9PSMLov%Ey4P_a71^TI6*2yYw8+<9r&i4@(bf5qF0z~
z?qNuNNN$SgM$rrXA<0Q0sUrNVU}>{D!Pzl6Yph#6R+S$0Idulx>O$>vsxYj at _18Hj
zbIewV3<?OB_!{l+py9t?)@0U#{XG at 2xH{-y_N=qJ1GDo^xwN93gN8{#doX#Zvyh5@
ztQxz1<US)<hgkrQOuMDa)F3iry8rwiZAM|0)lRghTj@`((oKk at TM7zWEGx9f+<)Rh
z2d2A1(ZY!b%uO1vo8~_9Cl|nE%zLnhBI%axMOC)(#@8)1Q>u(1Lc68H>KeM$4)l~9
z3PO9jWq@;zr8`DU332cM8-#Ytgu3;m4fdIN^r~*@D5!`)3Fid5aY9Y0X~7*g@*uQZ
zDkfJ}RIP;ulI|&Brw0YP at B8UpT>hk%P(xE&D2Tg at 8Y$73Fm3v&y{4@)+*%W(Qir>v
z(z^blEACE3P3C+EruZ5f(AzX`=$4McaBC&z2TP$t`?{s2NS at TSgi3i;G5*99H8fCF
zcS^;!MN}YP2`MSVY;i&g8ZcYj6DqowkI6Nd2xP4^U~t~e%Y)XTCjfu?#Yqf65p=U6
zbmENPt!kLk5-kAnCZZ)V8 at gWxCKKH*g#1Y?grMA=;rUXuIoMFQN+n)xH;X4;P4~;G
zGfmygS%DN-eFYv8#gvypdO~S;ODop21PZI8qV8p@$kDhOo8k&gw>b^>nELJ(T_=_%
zP<~x#>s~GkqYbV at 8A_u|qzF4I?`{cp)RaI0cCHMQaJUy*q8u}c)?|Y{W{aC<EUXCg
z`70i+Eykr*2Tc6fM~QLq3PS5jtEyCJ9qY^t2jfNRBNVBZk#y%G_ILwDAs5;%l@*#h
z6bN>mV)TN?hfY5r$Kfpof2;sS{||_oaiWNJZJjAaj3<A<ydpNl5IV&=Wqg?X!E(qS
zEa?1#NK;T(DC7{;8SL8b{Cvn++Doe#%L at Haq|iEBthBBU)oTa4jx~u{!d+VvAEC<Q
zR)=i2rj7I@%M at n~c300rOtSWXIpvW~r{j7+b8Lg|ZZ at 5*u3I|n390B*RIt4T4^J4D
zP9$!MC9zcS5GAUd3k&3leC%p~Zl%z1GAuzgrsL|C7RSWaf1S&UuKI{68$Gwhxy<Nn
zL=W5IcqS8*w6j{Y0g04_HPe=8K6*+|bm}u<i_H9IqIw)tiHWMRrxO!Z)XAh`_gbGl
z!I-E;UCc6e%c^2L9maxnnRK+giFWCQcqEUf4W$?eXkU*hOjJ=3><P7C;L||M=u1>1
z*L&(r;`ND|iq`rFh6{C^KJ64wG&ws1&eb~Is`&g#;aaSfT^q!(s0Ie(5v4PnsG(D;
z>O&P=+A5UVtht|VS!+*>C#py$bD<=We%#WLP>%E*dxDnqh?3^{e4d9fqO~||f;`Ym
zq=cZd2L^S}lJKAoI`+}PwGgl8 at X47jI~_>$tclU7r#us>21{Msom;ogK!>iL%4N)r
zVz-Q9 at 2g9`WAEDu-cyF}qZU=t+#0UMTLyUcg;l<mKT)HLo12=o(l#s|*4{*Q+RykB
z?T(#_5^3qy6T?L9ap+0J9D7Ph`qczGc}rPO+{atGq|@q&4n|L%^-Kq2>q at kFTDeTT
zgRwO2qca}sn=lH+Xi;B8bSUB6$0+TAO1AX%NG&^*^;kxGpq`CcvI^BP1uzGB#zOO+
zvb1yc``Y|{)Oe?0!B!ZzQVmKxiI$O3*Le}`Q|09)3D1w>zO1>vqKc)VPh}HM)b4n_
ziJ#35jXiNb$ExeW>?VFv*rs*fq)_X+suH|B|Mz6DKvtF?Br>A-QK|G;@poBb|BG7r
zf$l1yJ8s8%r$mQ|j%7~?wjOH at mwrT(Q2wUKo6ekakv%*T&EsUVhAvS(`IGQwhV^Ef
zyzLwlW}8hY+xm&89?<rXGIoqH3x>LNa~gdV+e2o>K6dYxO=c}n50#c<Wl`eA<xrMz
zc^O?jP+;+kf_kXr;??#{i|b5l!etq+v?mHRcJWY8m1(Tj9xBp~N)s>9Se-plpq;EH
z>ZwxgM0F1pZ5NsoFW*iS_e3FgTyfM>W!zD74;69eiW4v4j(U5bfbFGFQmhFZX{)pD
z$r2rD#4GH9F at miU_1%*h?s;{IU*PlcN^V_aTSZG9Ha!SqoaziR^NHLa<rm}SR6cSH
zR$#5Nev~Om#DfW!GTv#g3(LFJIt$vLsQq}=Ro(^`o#IQ_P^ZcS3%8IjB4T$X*)>Q%
z+n09}olwH|<|7r}8aPs68;OMyE$4i^9nGxBRsu0Ov5~|xqTj%Fq+#VFCXIxeJGK{*
z8j*DtR$Z7kViQt4*-<`N5F!g1>;eOjc<CSo)~S>QQ-~=XlR`pSKv!T}Y&OB+PDUNk
zgc}o5va at 2P6q6kTCSGV=rKDe;HOZJag7w>=Kd at g#hg}A`w;4k|y29w$8J~ZB8uwTM
zbd^?uJsb9HV;16#?=iDG>QBsI^pSXpzDZ6RdJ=BJvVIBg+%<4511|Dd&16D}s)nhu
z6v_-`CD4;PdrDX0bDC_M+|{pg1LpsE at Uo?WM2+MM2ct?xHqqw{Oh<-!o$(V*HXog|
zJk{ayFso%afrJx4naO@!`n3Tw_%Q?jj+}j%9Ot@!Xj87l&R6!4UF5Utgt_NY!Z}9I
zBd;)9Z?|BD*MCdV8R37MK6j!@I7Jk-Bga;glD8i^GWK0+U6=B{&1Ki=_C$LsknSA2
zOx5AJK!}BF?@AH9m+Op~Xh9d?K8ClAMz{5HMi at JOVb>sbwOw+R-XK!86|pzDlI at y;
z4cK-@#+t|pUjD+>FJd-+(3`SiQ^_^hI#xDlReIBQY#6A5ZOxIEOh-7_7OAWc0 at Uv?
zo#0@}bBz)knA~2AZ57%S35{-$UAgM(DzUFEF1j^l>srSo1;%{wY~H at KhC^XSsA_7J
zeHP*nM|pRmK)+WsF{n=HsGKpaM=_m5wVy9VEybg{d`CfP<<RZGjM5l6t0+#;OX5u_
zqY$gHe`hcv+mlMQz|Y%+jOwP=%KDIM2sKn;qXH0lV-0pN2-0XMcI?$bPzqyjQVMC(
zXa$?<>j|%~Y2l>C{6b3Bwk)kE2{l$AnP6SboE3UY#<I3Lyd5WOk)*ONB&+HqsoEAH
z;bydzmGg at bp}DeUZKt~V?j40GU<v;h^<*=OQC~=Jq;tzH?cg&;q-iZPg8L%Hr-Qm(
zJ3XihzKU0jA~(Cy at -~7H?#qG6PH_lLDnJOdaI#f7QbRygEB+XtR3h2uoQ_RgqSF%>
z-xdW+UJ1lpPFS=7z;?+9h)O$T*`ax&jcRq!vceHD%Ct>zL}knxM}qX*=`mm@$3QeS
zD~@QlBiW&7Qg$??B)tW?fa;1CY)p^t%OH%VdGK)SNL`fLS6$bJ at VeHf2wq)iQ1v=o
zZz#IB8fDHB`0KEF3-)>DA2tG%>aW(V09*V>uto=KR84)8K4~CpWaR9Ss3O{G!mZGS
zy`>=}|5bXHs-`7`6I1(J^q$13qLSMR;xe(mE`rVzf5B4z<4!Boi2LL4hHwOVFr+e!
zX}hXgwJyw9IBO<VREF0>Nm$j(pZpU?p4YEe_?PS}$-HX7DcgwuNK<>2YS*ucf<~Ge
zDuIRxhY^McA$9ni`50&f!<u3?0~=0ZL&KW-iZ$5Ju%-^ZOt2DfaR$SctsvOU3V`gL
z6|AqU(VnWNrnPl|tLmG`MXp(@q0m}YgPqS%OLo;ZNq5F8lx{P4<qy{{6>P0k_!0>A
z9=A+c0SuP3N}`SOUk{ne`n5VqDB`JGqm!(usmJPI>?s$aBuE=+O*7u-h=7KxDjESd
znsC^n8gH}Yg4i=sc4NcWNY<z|&Dg6zCt~~XT5t>6M|-fMWer at Y0!<Ge2*I}NI at D&8
zY6~0HcA9NgqBW at VD#iaW3~YrzNTLH_wg at hD#$PKoEvKX|%^F=$76FTU%E3GqGBPZo
zNQf;m#E(1Z*G$l>sT#h7i_N^TvAV)$w<N(DyxGu*P2~BHPdJ2h&``az5A^Uu8!FP!
zER6sZVX=?hpxAF^Qi|6UDs88L<f+Yo!IedI;fngk)`mJ|JZRT~HP=>X3?7YDVi)|i
z#Kfbqs>Vo5Ju&fUth#OuHqiqn9*toi;pSRm;?WrDE7U?vJQ@?bh>6Ewt&P|OnHW79
z3*%j|5Hay+tQD_0h(7TEE3ON#w~f(0N}|KiDI1T*OzcRLj*Ys)+uqR=#DsCWqECrA
zb)pb_c<nnTRuo~MDZQ-N)ovHM_GxS3H^r`f2DJ;m-70zHtlchp?K84=e%r0mr>tH4
z+Gk|#3TU@#fU<TKXrGalvS)#}TeU!0yBf65$l4XrZq-ByWTRDKyhd7zsO~tb7B9O*
z{g!<(x<tFGqBa7xE6b$7zEdiOky$~~p>p`|s6zI!7SxHqSOpC_A14=n=qd3oegj9~
zB(+WG_!z9N*dP?6Yy>ypnn2oa;0=bN`G+H9tZBd{uZF&jP56LHjV at N4`t7Fsvw$|6
z)n;k|eWMWq&pN4%hdmXpBSLg1#SqT!c7)pNszdAw01+{r7N}fasx_(61Q%05>kTm!
z7gK?GF@=ZYRuCD#GKfpD1U2P=l_;;`0_(6na3!yc;b?oi#Kdrs!%zrzISg$tn<ujN
zFciXF4nwtC8HPe{Aw)4m=yY^zsRdt~@B^dl_VxzVZid;+6Nk5;ysk3^9pVU9gjfg^
zX3>GltpGi|Kn5XS6RAT-ZhNeOL8M8>1DujXGj7p?28 at fP`atz?K>!&q2qaf18C0k?
z(?Sf92Ed-b&1z^CE#qZ)L8!f4fA0jj&z};9apYees;cK1Ild8X0mHt7Vs_`8YS3WB
z`E`J9t@)anKWA2BX-~Y6H?ttBX;y1P1NMxI-{M$4h?3pms{#9HCtqZZH)?I%Mm72X
zd0!<~&`DxHv_EtAo~qyuACtV%Ev{!4$Yej}VX^hL^`OGB at 28`E%*QPYCu|*pbNK#3
z*^(f)!!r*xtgpMsqoYnXo#^lh3aE(v21R*3x9R%{pPq2;qY(W7g^eC&eTSu~ri+Y~
zm=Coy)mRyl?QQfartFhVMQZD~Ejf2UH=k?6*NFP^^GP^dYN_Sr2eEj#REID6S)ZZX
zs3jQ7_-xWqq=S~tMtG;8ooLzCL8OD0tBlCaU2D0+upW+zSl&O`P`UBh#ESKREwaS&
zn$M0Q-^beG#`C739~jz6ruG`v*IkQ1vmCt*?L^B&!z$@oWV&I^?OLSFu$D(fEbmb^
zRAvmd$!f!@vqd`8|7OEFBPwEfx7tt##XAh^5?f at c<-OU4%I`4VJEM?on(;hlSWnv`
z9W2~qSg&*~ve&S_?pnn9z+8&?&>U*Y@>*ZLblKmKv#oUbU1QVIJxOW4A;Z(&I&nY0
zYXCks=Pq$2;mdtVBwJnhNN2L!RoEvftxunW`y7H#XL?4cIqAjtD4n;TN=loPPITIS
zQ}-Kz?{TIK1}`a13#LZ-6z`QDqo#L1h*FTeK10B>66hO^N4*7osJUM*%%S+y{if{)
zTMG~?%>xyaVPXFc%qpNhvX%1Zx*F4T+&Srv*aM=t15J;jwlqGq7e$RMK0TNxc~xp~
zvTIJdW&DuwC=?nzlx%$DbRr1D!}7quhyBt)roy at rWN6X-^H3!tqq#2b!`zLE%al?X
zCQ3i0M(awT+yRd2L2!(%r%$x>GVOYS#8{)ak0aaT><sp?vrXj(x{bNx9kmDips2iE
zAX!n&)`2g|<tkJBQO!zaN3CT2=X5ZM6_}f<P~&}uq8RgX(O3s~rw`q at U$ipO43wJa
zQSKpD^(vJgr%9;-w`>1&y8$DyNtVd`K1U9<%V2+`GTE7f4%{i)=HfnVa)te+dW*&h
zDb7SO9flUHREbZJgU6vx4{@PoC^dC7pd#=NrC6UnhrxSTK*Xj|4co=^K at y&UmZAcd
zfsSIF=`?LB&j5TVl64{t4+=|jp_|3!h;+DxnOvU1)A<N~Gjq0;gp)I8keEA{*W7tV
zz~fLi-)aL&9ch(?QVZ;J7gj9nP)}%uVr-dRPq0v_MU$0#sAaHHi)X77(|?8zuKW;W
zL#ZW}p6Ybg_z{S)R4dSD{4&a)%<L?8N>Xlx1#H}p!J`lj3F&Amb)NqAuTrVfn<lG?
z$SjW%P2`__rh7HKN!9pEPOioOP}gfd&vOIe^PY&P4Y?STeBgGa1W=sY0l2Pnd#B(-
zp2GOh?Mj`2z-2Jd<x5h%JS$N+LtWma-e*FCD>X^=@eBn?T at CzxLcNnz>d6TFhk-r_
z+>Jmf75C+LN_%;#MZ+8J)V1&|qSRY%mD*wj{^m|i-H5=4<h<?nsgx{O)*Cr-?Q-|>
zoDSAd*T3Dpc`<i=>PGr55Q+a4^YS^AT?U~N^1nbd(WcNfxxRF}R7wkk&cH`8T~|Zf
z{i4m4l=>(<>6A%=k$qoB>y`YcC%L}24p+ao0lNkzxzg4_QuUYMP!sgE5leY^FfJ^~
z5WB{$#Yb8E&E#t=!-?sLnvrQS&Ws9YJ29v5VHV?D<jBW at H0q~!VE7h9^#v?0WB6Da
zCfaO^K}$uS{&U2g*HOg5t+KeS*|yS<6EkL9?nC+18iw-Uf?z*CptVV82+EcA0gX*L
z2A_@{Pxwl=|Lp^m`VIXJN&f;<SAb7S)IVX2;k7z>Qh@#zi?`m%6Z8DfTD*-;-e*kP
zKOocSJl at G;i&Fk&;59G at +mm*nt(eA;;s<;Moa<h<|3ORSoTOihh|bYq!2R&yTi1PV
z|H!dQT|h18I<@$#E%*XwO#dx_aluutOOle4L39I584iV?f#rI@?Jq<>Eh3jC9Vj9?
z%?yYfz?cuZ{r5uTeEP3+YVm((!Phur`VT)47Sh at qVoccq_+`R3#lSBUrtVu~l#CgV
zPm`msaorvR*8`r#+~1YNR%oi+zZ>x7l-?Z!e+PIo%kl0Qc<w<;T?ps8#|aO(63{;g
zKVUUICgGFH8?e`6KImks0VP>VodV~2I2PXq>>c8d#NuCD^1m{;8Zc`D$_vi*gbiJb
z;D>~MZ9)EjBRCrUnd_;f8unJYvHK6k8MB)3(@7tAELfk at Dc_+<{+=hsjc)&mmfY`>
zIK(w40yC&mk|rv(lX5q>{ZByddg^<&gFb(+9K-v42Oa(e;9UskdfwUa^@(=1#e2oc
z(<jW|E#6<8Jbl7o;G}iF>g4H@@HFuLz;bxg$<yh*V(~tR=S4dw<sXmI5e=U?rD&Bd
zK7Yg#_&i=f`5(1-UpRS=_R<SwS_$X+DyIJZ>w!tC!;>8ylH_T?pTQfGk2oWfP5tP$
zmji4)@eG42|49hG%W4{(9IZ~}f7*f%NRGA!^hyO7$Kv|p8WSUZlm%zTNM8;3(hNxF
zIZf0>`%jBk;N<B(^WaG)UZIo6c+O(qYDrCVN;!)CMN43Mynym&Og2f(aPk(R5$n^`
zf1D+-%qgIo%+ufvnSy++bn+y!&fG{aMWC@$0cS26Ezzb9qK>RQXh}79Dy94>g(k&y
z9RwViT5L(RBu6hCK3*V9uJ5!2A{_)AYWzhev8^4XbOD_Xf#=~|XLV|g^1o;aoD;7>
z`3s6o<el+6u~hlbg}~q7T<3SH-CUGEu%xc&TFO}wQ!#24tv7Zq at 2HJ!mgugoMV0>*
zOX{Z1r5pu1?qHMlElyFX7x~kz>MTp at -p-{Q7Jh1p-ru#T@~=3=B>Q0JQVt6rvP6H=
zxu~x9DN~i&F$6X9yJW`Imlj_tdLw5^Z-&&LDD`YIP9#f8662p5 at C*cA=nu~GR`<mo
zPWcBNs?@P?u9uUUSL at 1E4XBo#(qCfWTLFJZ>9>+E;y~P7=lUL|)Gzl#_#LN>cITq}
zM_B^@bPCvoD>+gA>n*9hok}VHUQ6KLP677AMnlOorFIX4A)h$~9EO}>34G at ih&SX<
zmXz{1%G{PhS2x|H<8lf(3^@)0k7KCoN_Gl34EdEMkmeMylQ8)iGQ+6xbt<L&^_IW@
zr+~wdM<MXZ2pBTRDc~?<P{0U`atg#7a-1bKx>G6Tf5Z|P;}mch;+u)<=SUbb&MDw9
zWUVDI(J2sb$geG_f=;EBf8;Ea&Sa;6!;n at 8tQiGEikt!tL!P$;W;g}n4H;i*)XeNu
zO8GZi0;Ns?haoRPV8l=uGTU>ged?K>cI at GXx5~-0&u1gmW=S2}wUo1$c-oS$b;>hm
z%0KuBlVY8d7fn%1g)FJ#x|T9+_il)KXCr&3dmLlp0qKD12ygM28y^2A1fM3f%_*7w
zM?m|}0ep$4AG$kzca%OBh at h8wcyF$Ipn=UmpQP+=kH~2o(q9CWH5c$hQU^x(5Flq0
z{Y{MU6 at We={IpZpJx{4JIM=gI;ekg3x{dH2C!GEep#Jj#|Iw*qB#>63e>TD&qQq7D
z7C^5P{)>lz$>6^&^fk|Z1FQ_DoPo~xQ8#37a;KkhB;vuj-gL(M#6sV8#7m#M0E03(
z*LzOcn=JGn4%va<0G+iEvL9<RRr)-Heoo|T$&N17fj0p8lxVV77k1paG4N|kz#A{1
z1|D8!BBvUjG%=nQYTyp=-hy+DaPp#UFxICAehAt509_-0jJ!{p at W4t$*v&{|9Ff$(
zCjgCH40xP@*(0cd1%L#e;DCJ};Ivf(Z?Sl at oV=O15UPQh<+we9bImb4UT%Gwcb&zX
z at 8oHngO@1P4Ch+r;HiP9TJW(B*qHIH#S1xkI;qG~+|j_f>NHOc{1~D6%YYnbq>*nt
zE#QpN(HZcZet=Scg&V{<uUZHW9xxG;jIMvWhipb at h!y_QGvrK!eX8H!5VYkdxrW||
zGhR1{bD<59JiGDla;<d_*aMFbb?iFI?M^#}+yP?|3=vvsLHkKRfw{yB3A_L9Nq<5-
znC<N4<#eI%*NExkl%`6#1Lkr1(EX9eo}P36!;>- at Rl^BS_a~n8ie&16zi(W0U!&-#
zg6uVrasSIR at J<h=d6VGxdv!9Bprn=l8F-wka3AI+;CqP~NH4&x`q^;qnchMh_3s8U
zI0fiUl4erWW=T}nng2pah}3PJOG)kd=cg)l3!MAUl5Ubj)~WmNv3P$mJVr6RLA@|%
z0Ox)~EQ^VEzr}mo at S^dg%8x*Kq?Bdq-p2j02h}kEMd)%TCrcxljerPp6rGZc61<ls
z<4s0&&lkbZy#0=0p?gwXX&YEl{u%_g66%xk398MNb_(n9J9t&f3Ghlie&tO$3x3XZ
zxWDoGFSX+IOBu(3t&URwuS#L_VrS_7+M9A2{G3N|f9v(X1}gRKGwCpS-_`uv!-xYW
zz*MQ^A;vZz?GXv(Uj?Sr at _s3dqEl1@wgSF|SzO_aqt6%?M#^mvmKOIPFUnvzL|yLR
zxQ7YvQSijl-?^3hA+UORo)>{Hk~)^AZvSGsl<AiuKTsO+j%2%b2K^37mjgBOyOA}K
zKQ|fb?-udW<UuUh&k(TViMUF+*{ZVH6#q)ZpGiu`<4AQVocpgyJ0RhE0nr_`^ZTUX
zXM<~NO<~Tip!^^B{9rbGuH*+?BX|m*iGUh(8MK_wDC}A;hDYY;X(;4W$`@dd##xY@
zjS2e+ at VJr(y1jGYc at y%<gWaz5g$Qh*$T0U9H14!_!B8nofiwNdL)?StXE{r<=K_S{
zg%JIc{2VAw!dVipSfw8T)F|FW#sB*6ilNVQcyBzUa9 at +^DaS2_^8A(m{#*OuOin{N
zyq9_o?>y30 at w(w30Z8BvQ|}bGQs6THe?sZKsXpEw80oJp`18~Pfkk>isK35xbAO$x
zC4KeOGN>JYFM%gj`xkinJspD1`%`uKKaPNFf2|sI^9M0|Y3j&DeUxHUcYCTz8ub)H
z?xR!FMp0$@>j*9G3#3J|q0y8~@Z^MCo|?V_T#<-Kj?yMEUdloEm(y=Ws+h&v$l!4H
z1&Hf<d5J#Q at gAtleSGR@URf*yPEJjmMMdeOQI4Yi5-Aytrpy6P4ER}UdW|J<sT5LL
zIpd}9Nrf12LaG!;i~+hlXn;!{;F;`4yY at alhR=bnKs4_Qj>kZ$$AS9`qUgLb*=E_u
zyuV3Z2mD&%tK6w$*CXKlt1In307{2m*CF4-gvOl-f!|Q*t)~!nvb6L&24WZHqgtco
zV+XFr?STe9jqrZ5Kkwbro~2;sc=-9G!TU_6)dPBeJ8lFJK6CJX?vNd~oG4|#bfT95
z;WWSZ8z=f25I$t^ez(n$+DQi}dB))Vy?+Ime8k{&xf~MyO91idfHye?eiIO%4tP^y
z;4y&sbimuk#eADg`GbJ at bikVy178P-ow3&+1HS{96YbuCE}r|Ak^=#8qTM^xRldIk
z>*CF{E)d?|`PV{(^XJ~-9mM>*fOFE;JI29N{tp3hcGi1P44e&!^CR9o7i-1XF`xm^
zU4$pOOnpif4|oii2i>$6kKCp0Xxj#)1LLfWH(=pxHOjvTI46C)3tTz8XO;%wV~;Ko
zP0p+fkN0{11rX-^k9UQOPuNTZCaz`ue+82_o8F*H-)yo;`6#RWnZSit=j7Rujno=T
zs;O%!hjsp2E%`R5JR7d^e{AtKIeF0(wbVrP&0^QdT}zqlMIg!<DDPHhfiZhV;66)W
zr&FNCDpBSC+!DChDL_M<nVN#WT++F!Qz_+-K!7t)-kY2P4nrQW1nzVSI1KsH61dMP
z5N}8cvL@*~)~S^8Z-4-2puA5z1ssO#u>@Xl3OEcIf`%;`UUUk?8&Y9Oz1FFe^4|;r
z&OmwJa|$>N`Q8%vr&GXTNGVQf(eQ~=Al{I(Evc_Nl~VqfAix<YZ<5<_QaKEn0;UM`
zaSAvL*=z|6a0<j5@|-0#tWzoFACB24&Omv`I0YPrthWRvI0YPrJZ=dTI0fPj>7QZJ
zIk;0PJu*8QLiSCcI<N$t_jpewKv&9B2Sq?Hg-hAvdx8DMOYEKG;&=_wr?YMad6wQ6
z*d6<>$2CL#RMzuA|3%Ip<2j!I<!PPrXZA$CH|;<6XDVyNXnjFQd4*wNtE?FSdETY`
zHC9|(lvM}zIdCbjzDsTLCxTk#`Czd-O?kaj_5)x`F5ix_C2eL$WxWY at GJGlT-82Tu
z`KK~zdS8OS%NhhSjo$Yq`@+wf51^Ic2NFqZ;wAMKf*(nlMAc2W7wDhK`6og9Zd at IB
zV<xUY$z$>78Hc~k_`_)XNK}v8 at 3<lBe6a75TPL|UNKaM=B&RONx|v=FXS+bzSb9xW
zS;OH!60X-_v?=Y7iO5|J1$#|*rIjM&qof)u&<q33rPR1pkm6XUS70H+PS)5{s9>gs
z)VPZf;zNdBrPSrpiKxuUQ1S>^z5kHgC;w+qk=v($<(}K8XbVIAW=W`D>CYu}_}xN|
z*dt{2dqU>8 at +moYh>&>&LgpVS<j5)^3r-NS at O&X<w+mVHoRG!u3n~9j$daK2RJOE0
z$g<f&R#XaExn9W8=LtDx7m5Gk`-NQcjF6wdCgjrhg<Sr%kSjcsD0$@&Ay*wB<eJGs
zuAL_2y17EGUn=Cr)k1cy6>?LXkeg2ua_e>>w_POU7uN{6{Wc+Y-Y4X)Cxra+IU&1W
z5pvHvLhk)q$o(Fae6IfiAIYdHDdbVr!zC1&C1g#5kh%+n9QO+$YabQTut!MKTSA)E
z6lz&FT1ZQgkjP>oZ4E-!ZxQmdYlWQf3n3 at +`D^Z|%`XT!>2)C||4Yc}o<j1@>?>s3
z7$Msy3OV~wA?GX*a(<PN3oaLO;r&7`dQQkCZwR?`uaL`n7g6UG8A7fq6ms=^A=iY3
zT)S1sb=Q%MZFpKpV at U}^O;So@*Ig)~mRp5{9~KgMUP$Y|gtU1NW`y?rg{(hV$c9Bi
zHr5I`{yrg_{v_mQdxf0fKZNm4%oeiwP$4Jrd1CI^lN*JcvPH<Lmk2rSb|I(#TF4pi
z3fY2l8WFZ;3ORF{kZnOB+na@)^)n%7pDE;=ONH#XRmgew3pxLfLN543$c0HbcXP*H
zw4acRGlg6>MaUJ?g<Q2r$kkOsuHPu+hV4Rbyj;kxUyzJn^Q4g4SA^94Q^;{ihmp5-
zsF3;`Aq at c`jmw2J)eC7pS;)GJg|z%aNcc%1k-v~+9mdCmxmnY^(@3U|5HjOXA%Vq0
zX08!3Ym<=Dok9-3LC6sg3Yon}$eeeD%>7!(y#CXvbAG0fBTIxVC>OG at T1eRjA&bry
zviLfZ{MNgLv`Hh%Z&x!2t`|G=H%L3n-*~ow$6qgG(?ddj_Og%@J{59edVujZX9+o}
zRLIGzg`BcZ$f?_foOX?n)9({<#&bfpydh-k=R(fxGn2};jT5qcs*tl53puAj$j&W7
z&bwB~1&;{1 at J~W6`j?Q4J+r9gk_;g~FBEd=d?A;u5pwy-Law+>$d&g9xoVG)t3MEO
zO|MdFxptJ0>m~}h{%|2TR0z3olaO5(3AyPmAvgbC$SvOpxwY@%)N<SYLVi&!<n|Rp
z?pQD6&hv!ab)S&CUlVfA`$F#hPRN74BdFz}(Lx?B0?FI#QgUGG6ch6c)?ghsoO at 9+
zFJ}{va^vb&YljD21dy{3xKOu2%;m=H+IjGp*|mR8z%}(zJZIALm@@Zi&8|@&=j;&m
z2}X^bQTrM(Wk!uD$c!32){I)7Vw#K#=UR3kEb_x8zu*!pXCz_GlMeHaIBF#(M)vlH
zNuGnVQ+#?{;F+qjxpJ4y)pKZSz7M!(M%p<XTTz*h3^i8ZGMC_L+-L~#{@$~MTvyup
zkXGa70O3rAX9Xi#Xc!3REIh|JP#N`H0#p^aAe(&QGNjb&{Lw3Nn4ug7dtK~GYo7 at C
zDEui6U1A_=Qj=0vK<ZK#78tuy5Kp8nh1ZJ01*555xnvZyDih-6sX1izTIxz$5>+nH
zG6RY7u>!3yP!&xW_v__m40Kcj!cNwtH^Az3w3xyyh;B9cBcR_hwN;XJx6kboZVT0!
zoZk+9YHG!l`$6%B28vpcYFAn|Lz7-1KO~x&7mZGS2PieC*4Ubbn=hJGVFg5sxJ0~o
zBigguRkR4Yif5wLcwL2 at lPhe2MBx^SF<2r&HnAf5O6YS=c4yuPz>Q{=lv~^jBqg=*
zNgxN8 at M%c#0yJY!YRPLD=$HHza1qfWjxh^AV36~_g`d&K3ESec(cDs9hwwSz)V^pr
zL)4*H6G}ORRtl7)3OVsw(hi^`7cxck6&BM+M)B`4&*w=l<h*Q&WPn*ITtPmuLN0eN
zT*DxJB@)CKMwJ{-j0;*yPNR?5Vf-uP5}d+Ih|yQX35ra%Zcg`mpD+9+Ia`K9hBt2|
zk25Gf{uMG<!hwIuU&)}akiJ6kF{Kho<STNS at e=w<=qr>UEh-M9MpKdtN1_s^9f-fD
z5uVPwk3v>%VIiO*@lB_X?YWSDB at C8Gkj<;)SaLrmqn19w_*ckaAy1VVnS8D=2<K1I
zn9TElj)J$ZuXqATvM*2sk~Vu2aG(5f{$KY4fy2m}(<$q4vKGq3mHe?~s=$#%m&T$-
z*HW_P#j;f37^3B|sEJTb))8_iDJD7WT1(cE!eYAmMkdfgbV)2~bZsPSK`cuJP9}OZ
zt6k5)i7x2 at XPybxZE*c7qq&#pn!OvWm&iUcYC72}@EXvxGSL||ZRWc`dmjb)B~f`P
zv6%yaP9f*$C`W5L6lmItculi_)>6JMDleJ>O_X05kG2t=+gT>Eeg at VVWG|9PI at KKn
z7Tc++%qMZPa}hw_$l at zNyspfbfZPo4fRV*_fq2|<&wL-e=_4~g1 at kd@2aYWMEt#pA
ze9Pk{cn6Kj^x-b$b$ADlD*ii2iaV2!pud23$f(R5Fu#X)=&0h<mF#pfc at H)U-u?E^
z<b7B+y(2SuFLp4!qcV9vHk;mzOx}|%qjz*B at 5`#`Js^|!W?_2AWb*#(WO_42?@oHh
zi{8uWJxKK4OmCLxy_enzqW4L9vqkR<^yY}(H|Wh3y&uz?m-#Ow at eRDgGvtg*J{oV|
z<x6Ke7~T;h1<inW{|rG7f_G#_<~Vc~li<x*Hp`QmQJ!4_KPw|+iON3A at -IzRnF}Ep
zpy1K7Jid$-BFIxa<0vgC{*|dJb3Fv-P_Tl6$BG~;CL^c?#lJdL1r|~0^cx|r&!OUF
z0FqM!tB9XLBh0x~Nni^TFu)oD+o(tbSq%VM30`lj^L+!ws*tTKYZF+fl6}K4+zCn?
z%`V;sG&wo2lgyjgJvo?xONicRrz=r>x}{!4)~&V$PS!56Zs%1js>{T>gRHyQ*5X;E
z_mg!EmFGV~?{z-5P8E0(fzb!aDJ16w|5W}nM6;yJRDnGVjJHKp;LijmL{B at 3bNCxT
zGfoM-OLCf&?*4@=p#$)L#O#j<@6>kA{x<`^F-HG~f%D`nm2*AoI{@Be06yZVqkaU=
zk~CvGOz8xDTO_Ho at IOZ)*)l4B5My4YyMH^2I>OB1;AO%c&@4sGKNT3y2<J<+ at J|JD
z2wWVMm^lf+p^Vnb2?t-46PQ8K3pg9$b0|2R=q2&8^NC(&=h5`$i-}$#=$ay{BBg{2
z>k%$K3Vcs;pn_sgh?o=|c`8s#^m55%T;#wyvK|+fM0k|SwcaP;Euw<VKjCj91jk%H
z-g6 at 8#bZv$J_Gc*Vqhn#>@(qKnqxMnW}jvGPwJb!1Ag|LV@~#EUu5}D8IXNB{C{NJ
zQ-@~nw&YJ6pZzfWtjjT5CT9N{{?941wK)4(_&p`?pE*7I5Actof7|TrFX3NF|Ms%%
z at 8K7n=d8$1TBTHk_>S7_boj-#oz2-p;6H)*`H}4X;Xjl93)-{Cz%OwxUY~uSC4cFb
z?1}Jm#$?Q8J5(Y2^zojnk&JK5G1<F7CHt#X_AlU<B#up0g<r#F-Po8DRoENxqhWo~
zrLZc at B!}vCBNU%-GG_sN8A``2%3KKV8}McxA(xqd!aFRtFvzHs)lucDtCem5XLxVe
zeF*I}L(Qn)r2 at rZjyp#p-w0t<$XoWnG@|E5(fq>++~uQ)7>$7rkzd*((X5yzx|IA&
zqkLL5R|QrPzB(SBS50_<JPXsBqz#%l4P@??ICc*JRjq{Y7Fe=uq&E at Py@Hr4yi*Ql
z-nQU>zUMRu3_bEZ{7dh4<mJYfeB_Prv7S<oyx;hIYTi at uj$5cri&Hr7dGZ!(o^69q
z5}WsD@)mWLB`pwmivo|uX3MZXAnQE4lvH3ZfeR$}^5<ZEL6+_zqG;B)K$DII=W+qX
zIH}-3FQPX at MFVLBZV|wNrW1WQ9vw#X3aK3FX2mCeqC6`D{PC2zUO;=qsykq9Kpy$$
z+e!IGO=aD%!3T=Sk_(V-YSKMYQUwkr>)L3nr4nl;{);4PDf!n)1W6`;9)UYVkIG-n
zz}Y$wIGTYSwkj1^O<-pf$X`R?Cb>SUtVRS{30y+O`l8A5R9VLZJ(Zj*V>u?B?PUEz
z)QWuIJOa1dfYx97bE5Z9L*N>EAF``imEJ_)M#c!-N$;*GFK`cmJ8f-q)x3v at lsTHC
zw8X#@gl~2T27X86Rzdiu0)HTIn=OLNH-SfOK)1`RH-LT!ci^9*akD-J at IAr5IKY%3
z2E%X%zUcsm6QFy~0p<ZXgy6>xa3+9-1V43v%K=mo{K^5Y1<+3L`zV-xB7kiKJ-RT+
zQt9UbxsqrfCwe20UlR2@(FcM2mgrC?`T~&Gh-Ny`cY*wyXqE%b{N^yFz5;qshTI*f
z)#$66GyT)hgy7BA=rDLE9F%z=&>VPkGBOL`EhIWYZVhI`J1i%w9Aq_I?j*@2r&m>0
z9e_51B at XaJ0Ndg63LM}C0Is3rGzWMKfcpr}bAZ1B at EpNK4)D(a-XXZ$0e%eNYl5pB
zU{VFL2bWvr0QUnhj$oYw%mXl$V3PwZ1yD|~)d8*ou$Ew{4f;6qtpX9Em(y=f)#Cwd
zA$UAX$ft{GCx9ymo)iTGHv-7pU;{qRsN)<XdOZDFVdi7gu}J{Hi5Z#C!21Ne!xm+}
z1n*1qE?nT*JZygU-{AiY*svp2_Q&vZtT$`{nsp1h3AyTS#$e$;;1n0k%l;aaIVqU0
zvR#$Ne`IoYs^wphn(edv3;Sjdwftqi>`|6~(ZK8jE&t-7*?E?~d_;DU<zJGKJsp1b
zi3Ll?XU~P7-ABQ)i7K!dfk|tmK&9{ENDtT4qY2k`fU5|H1(qSB?%Z`0Y{IH0wZ%p;
zm$5do)^`%k at Hdkm5x$HxjS*W2>;B5N&BWMAmhQOh7>4z8vMQxU8A}DOCQv2z%Aakb
z3hW}QT4Xt-HU0JNL_<+?w3>T}*4UBF4aq}9>l~>)PGDWU%HI-g71SZShv*KuOO#xU
zo(X#kX=LEfWZf=zh*4JHb)t95t)T;bkLY=F$+J;o-p6F^mV1tP*5_nhAh(9`tp6kH
z9=SD)XL+l at +8ixR@>QT8(KBLEGyWSy)}~mN3XC9nS}bZJWRi74wDfff6NsJ|k4_?b
zdMs+x975LF(m*8{$q0jL=1j1#v8I~5J!*j563wg!x|5vqq8v$o<|RNMBIoB(j*jyr
z(D%u?I?B;;{slC>8k}8Gjx;kdBQPASNhjH-kWXiH4AE0<R0XmKY_|a;mQQqNRIg-D
z+E1XEtcyA=l<8z$92ZMlGn=eSI%O>)D=y!<l(UWktBUNC#XyN3HTB<kXr&6jz<&{+
z2L`awr<znDCjiY;fffS#u7juwtS8VYw&&tml`5Qs|DwC6gSDBgwW3@`vEnNiA>p4v
zetp!8IHABf<R34589Yf%Nc_M>WXa=ipXA_|&?*`9Y5i0cxSB#|M&rL6C&U^ky at f)@
zF)xAL^y*QcRE{2lJw#NG(utz0eS%1f6pA#cz_SE4M(a;Ue37WWkJ1qrqIl%M$%=<z
zAA|oI+?1p;qO<WFY)TRhU*z7odLcu}oEu+!>k+u?k$4FF3xNzPkU1N}5ff15$sz0k
z)NF!SUX3K4f^;t6-2<@~5a&>ig4&Pqm~Y}y2%L;(8F)vANiJIeRr0QkTD}=99)38y
z at dHMS7tuE%Xh**i0g3)flDxpQ{3-xEbh?Ki(mFi&So%01M&c`M%WeRwmfS%x95mdu
zjBnkow=8 at Yke$SESB!;=UxVZTM#Qmr at ElyHwcj#(HRO3v#<lEWNN=G9h3=>Yi-*As
zK8fV9?7|87U-BmXIJDtkBHG_!PBD}(T?CCZ=RY*Q1S!gje!Y-gt=OyMnTSba at J3$5
zn4Izo*Lh+0MPriIy#yMT)EM1-jAH9<iPOD=Zzb{AAI`PxEU<rth-+cgQLd$o_AN|O
z%O at JK{vvh<#6I`I?gxx+7W(36fc64kj^)!$3~kZhz<YW>#CXlbaLq$bKL at Ioml;XM
zbuH@)RhP0%_&k>ecp<5l?=V6Kicmg;)}Z*8p5rX at OQ0?dd>+e|L1ft${Hf)SnYh~c
z24G2y`?51`tnqtHjC4eIExQsi4q=RMx{9&vNhVa1hnBWtuZi1R;=YWkpExo}DQ+0$
zel>|tzL!m9i!8+4o+{*XF#TkX&+z2&oIKLQSz110HdV2e;pB8|zX_WZ&J!Hu)5oIY
zj!sBJC`$qLqi8=)NQGyQ3Z*X%c?9T4xD2=h;C7E3Hu(B&XAL^>tGSb}KjY;U->AP|
zG4`L2yn5A{llyNxyLtSu)4p8))CW0zuAh5hbJ39ZADlGg?BAZ#@a@}Y&1>%e_PP(&
zpZxJP)8BVLu|4<n#g~6G at Yvkly??Xd!_lW7GkpHc^$Ulry85p*kACpnj^qD*?WZ56
z{o6C-nRBmo*PQ+8juV1AFW7YVITxP!(8PoD7uQ_9`2GindcHd64@<TnQy0VSg1Zmy
zw{Wk*eFXO{Twhee2)Jyxsc`e*@Xms&huZ|V9qux?Tj3spdlv3hxR2nzh2w@@8E_Nf
zro)xNt%hrc+YGk@?kc!D;2wixuZCn5J4YVuNEx1E!dzv*uv982Uo2smry37=HwBcv
z3QuhweC3xiY_UAJI*?&@vpo3v48v at dJos`e!_uBXWj`TMc1}EQTA=ytb$D<QDdjCb
zw>e<g($Ccq3|lr2j!W;-IDNc;P~OTj*K#l{%^s8;8N<vY53UhmSUNsXzC6RQobaIR
zV;Hu|i0eZbw)C;{V%RD#zGI21lRDt_g9q23P{vAwZ_hAnrBQA2EY||y^2#u%Rfh7)
zHNsXM$bJt9Tk^bCP at k0^cM4*d*F_%k>M|%h8XkOcnS3iOI}Rai$y?_$Wq80`IT+^o
z%=6chL9<hIoyjl~%OX;~rBCxMTl)O&x^oB2LU;)rs!1Gm^18rdH5|iPa6I at L9>cE<
zk)Ykrpt#gVIQADjm_F at FQXZA8*t6(#iKoD&!u5uu-Do~?5ocTuAlTPf{mf|i4}i;r
z8w*D}vf*goM7RPtJnX_S5WOrM?cjKiH`~+UsDGxRrG_33%4Wc#N3n|x<;vh+3|DTj
zWuSNnBwO&V2CaargsXz9g<A{P2)7Q7 at gtzE#=imdu3+Wl1CJZO>-K416g_bMAJ_DH
z`oZnbF8}h%y-%O<{PdDV+j4g8d?4fKL%(|a^IG at Eqd!V(`RKioV=M1@=CU=HZ#eGa
z8%}%5H~6jN4)`c-)2_X%W{m#T!z1^WuZ--x^w at XbTfFVI<6r#7H|DHMhX4ML$%~GA
z=D_fAYaTf{zigYYZ`<xWo_=T1OK+X9vH#(_PWyV*Z3q1$r{v&6X4jr}>yGPBoB8z3
zuEQ>PVCbst7Z?2M;+JRq{=BJo9d!KEs~^7LnNPnNKfk|k+Jl3uGA`J3)s4 at 5HS+f4
z>E(NyKYC&1_x)0aKA3yU##xb-(?^XRchCzD=KrdXJDhXw#**r9x4&Mp<{vNaUFn<h
zee-|*T6y|e9~=<e<SV=9(o5f3*Z=*!bFQ2beCfGm19Sba-dM8g-1}}n`m8JFUHN|-
z|M~0fi|@a7Q*P^*spWb5J$y~^K{sqTN=@9nrO(b^p1&#UAG5El8S$8J)%)fCvb+BL
z@^zQqF?rFzr=~8LTRQ#Hx0ZNXCl8*s^X=bmJ374m)%3E4kG{SAyb&+n{(4sOp{~Qu
zShQas_k~OSH~cB}@>kE_aoLq`F7|)+Mr+ovzYUpI{nm4VjNu=hGjQgh8(+NO?GYPS
zy_t31wr!g)eEs{ZFWwrlI(0+s4d;EbXZXF at gQo3x<;$iayI#xMd(eQqhc`|6CgtHP
zHr4)ZY|XCY``r1#yn_46e)YxwU4Pf9n?6cL{lo3&LED6z2Dcb41h*b;8yw&E<Xh6O
zz<mVwJskJ98VgqpHxKSuxOH%+!d(P+Gu*>)d*I%N`vR^PPM#5Pd2j)^rEs-y$HUzW
z_b}WZxVPcHfa`@5Z3J8%TmWt<TrJ%3a2LSsf_o6|Ik>mrK7&i?g=;-r4%{(tO>if}
zT>!TW?m at Wc;NF7!3@!yH at -Vm@xGK0dxUF!P!QBq`INZPClF<zefy;tB6s`=e3a$-q
zD;&3|ydCawxEJBxhx-OD4ISBNxXExwz^#O9fZGgr9^4IZ_rpC4_XgZ2aGrkXOW-EJ
zmBTf_ZH7A!?gqH~;hu$i1MU+z4?3Zta1-DTgF7DXY`Cl8cEddd$MqEK`?$n{{SglC
zYsv1E!{osjfnlfw!b3Jb1m%FhK)%&FK4<?7#FYwE$wlQ>M6?V-eAU=Me0_irS0pht
z99*42h^ya?6d%bF;=P_Rk4p^*aU#e-^7bzvE|Nk-z8eg(NfR!|GTOKeD5I9*FC7$z
ztf~a<m2E?^MibC;6KrVMY8{dD&_)-RaZneR)f-5*u>|xM@?#)wqe`iEIFlmR3=-mE
zE0b~FJrd%635S5<m=6{qE?YBFT=GYVi at OZOMJ$B)qJT+}YhVa*KFSmiAKek+gFIsd
zSLP7nQW+DGuSgT(>;DGgA{s(`Il(|&Ohbq-Dj10CbqI0Z%%sQ{qX}_EoiUZqyb19+
zxG{puUkLG)1fz>D?xL-z5AX+wZ})@ng=vO#P4b0KBhD9ise#MutRh*hAwCf>Qe1pP
zDZU6{AbIr|5SIZOYxq_)rFhq2ATHn`#1|<{M0tN45Z5RgDK5yP6rYQl{LA||fW{(h
zq`0jFrMS_A(Z$6(g!rO`fewH)Gs3++0rBNp!{M?_3b&y4O)6X>Nr+FW4aB8Eg!m?h
ziO8qzg!pjY*dp6$0P?^V196!jrTEs3iOA>Vg!uT}KzuSoi1RN7;&Nry*oSa{xJd>G
zcTvEP8wY at Jg)<0`$_%Z6yNZ~kxz#U~{s+!LTn$BtZ>gAwvM&LkW~ek$Tt!AHE{`zz
z=VN|CeEM%9ayb<tuCg+aY^Dl`o2(j$iyA4#*<z!M3ycVHTG>EctVW1y$xK99`3Z=t
zQUP&05D;#`0K(S_L9RvxfpE1b2#;DgDnd0`4VP=K32|X5n*a{kIs)`p&}Ja6k)srs
zuo+#u5hTQwyhe&UOt4b8Ul63YR}g;Vv{Bso0wKPp3?j#Bt$`2U48%2YRLXac48&!8
zgt)TLlm{Qq5aN8LsT8icCBzvyBgNIlgt*q%KwJk%i0ku=dhY!|h}+&6h%5XEaXFrW
zWU~xFe?ulriq~XlDXyY5Qd|?uh+HI#V&%c5bcFcElaZ30F#yeoHYqOpqZD7VGE#i0
zj}YI(GY}Ud6XLpLlOgVQP3V3&V;A3KBgBbB6Oro#3GqEG1Ib=0fX+wQMC4jMN^z}|
zk>UbJLR^h#AU;YX^vrY{8knr10nrR`*(9a7xY0z+S*;;H0W=U7I8y4QsFZBr0qEYS
zF0SCF6rY`#Y;!9Hpfc=(F7DuhANRcg;f59<Jh)2%L>2dl0knU#?Qy*%mEIOjnoAG~
zaaEUzU$|OBeB^5&*&+l|TsNK$ii6J_8S(DvwiK76i+X(uQi^Ll3Gsb8ql>Q+5aP0D
znu&v}I|=d4IwQr^sD!v?)IeP3PKXbNOp);Q3p8cL{fO}6hBzSHg$RTj41sVFJP3Ey
z0pTPW2#=j6Rle3|Ag;P*5_|*FKu=U?=&|WG#HCJ@;;IfK#nonnxHic^2t|)dcwNdh
z!$SI+oHrW)*Fzpu5p!%dA<j|b=)k{9V0|mx8UGH$N3PXqymnxMHhI(dx=MfVf8kpe
zbrs)dQp7NVM~Cz$8pL!Q9r)7?(v|))!^d4jr}|eLK2C{F`J4Ys{2hjWAY!BbOh_x^
z|6>N}%KkluZ%&#H@%I{}tNdAKNLTs8Wk?R!#>L9D-skf5O-ZHAJU?*WtE;j(vGD!(
zMnC%BG~em&nf-7lC<o<c!EG^erk!;vR}Z<(KSJO6kgGLvY<F^4>CQYQ`D~oDO!pzU
z<{zQ&9muWt5psQz at 9956ZZhP?8#&W1JI(JgkjpS~rhYq>I~8)NKO)^*A-8vet`Ae6
zo$C7&<X$#%rrmZb$LZ)jKSEz7`kMQU9NV!RR(%9cL2c;z;BC-jM(&658-d&|BWK!m
zr}l9g{3;{&L+$TL$ZaulU6l*lG7s0rviZ`|Q!Y(L&}X%GwllV==?CfZt%RRP>LEt4
zmETgG-xF}vNLJHu8n|4pZ_ at gapg3`kD_7o(=H~jks)`7{6(7!9QPor(%B^T_&YRiP
zh%X;U!g;eoZJ~O6ezqlVNmEljz8qU;$;}GYRJ7Jda at XU_#fFpD8g9v}tZU56&CRQ8
ztg3IV4&_x%n2^_&ul7Mg_|$w}6~0BgCNDofcVg}&E6JadR#|;Tq^7B*A)I$)Mb*Oc
z6}im at aAdrE);yaXu3jsdG`ag9CY6VePv-^s{l)PAGS&ZmiglBU3;&lnG at k<h2 at N#C
zM#GxKYe4d`O`e4K5@=J)2KvI0>grHUZY{5btZDP%L$df4(7KBHx{aY0`2 at BW$A>%D
z1l#ID?F`}*;I_`t`l?VfPimu9hec6SxTd|DK73)E$yrh95AxIPNM%i9Frv+X5EIdA
z=mU&iRHN`SU3@(h->*ji-4vA~Y~lPQy=G8~-#w0o_)&Tj;zyCS3fx@=88Q*ApowV(
zO;iMRa!>=KbX$cVU7h`rdPfTKsd^Je67rdP1TCeGFmr+KMdzA6h%o`(RuDj!szu;u
z5zve#BP8c2{Foh<(r7YjYytVMu@<h<-#DfU{bgyuEJgF}W8#)Nrf<G#EagVCwOCwG
zYt}67w?1fWl{eJ$L$J`!FV9-?fMUJi*EBUv%B^bFL-*t<%KC~P9$tC+_x{w=?-cLP
zJY&6Oo+R(d9+x*Y-J7)Go#T@>tVniwu>aAW-qeU^Z11 at qm9)$CfahrOeeX)W)l($i
zS2jK1@$~+!Cw-+S#d~tHn{iI>le)q)y7%1V6vVo!`2o)q_`ykfv;PC0eiH4P6Cdyd
z;9KBLtuYC0T;UlG<UsEVPhPI4cdpj;hIgtbxA#0m-hwDOy(5%PdT;#>&q4?nc~@w$
zFHcCVfgP>Fy(npi$KQL0rx2?A5znZ(p27(2ihSZ3j7SFn22tLCXFBL1loI>ANnahG
znv1A&larCi=f^W^t!}rBq`yE}V!WC22B;78MNo_ra(->-FF`R5$>F#u4fN-r7$4*`
zf?~!!Cj{CT^l(tj2;@uwWqdCv+F8yQxSkIKeGe3EGv{Sc%oyeT1{C9#oJT-$R^;3O
ziiVSO7AWrBa?Sun!y42Eigw4>rubMgX9*}~LULvpin~8PYRt(4rTlnMbW%AStH6XD
zGd9op^;`*iw;H<K(BX!DF-P;CHT36(h7CQ~&>@DtK3mJ*Xy`&i#~Ql#2+hCE(7A>l
zia`?W@?JDSQ_Po1csh(Go?$36!SI{-BYn)!s|?+2=xRf!8=7ILGW1QO|1m?aGIX<{
zs|}rQXojJ<U#AIPv<W`WMb&FNxc&v<BNw33kc9UcR9YH5`b5O-xCw7&1RQU}k$)8f
zI37d1H0ZGIy*C^AJ2YFJ2p;8E!|^CYr84}cgs>FE at R>M|>kQv#!uf_j(S%7Df4T`b
zm~fd1pAJes at 7H+b(mwb%oA4{33_oVVIVQZvgf|%Zy(YZegjskz1|!_x at ECpyjk&+;
zF}0Tg9QPvZV5`cw at W*lCL2+R|UUbI4J&wOJE{u!u$_4YvBa?!`{QQ0NdFLrLbuHnD
zd~4ZGYu|s}8DD$G2jyc^?dEr*t2kik2~GJWVpK3(+td=VzBt_ at icx>aZI7xf)++0p
zFmy8?xb6v4Q3Q42Ahq^{w#n5MkqV<|-?n0WqCNUW^nL$Hbm#Zi?bP=DS!2G5zH)&n
z%!0~_aGkV&45{Z-EhtAf!7-T`@z23G(1Ddy)YmuR=DeweK<O-eIG#hzmikbmbTEl1
z!-v;-Pf=Pnuc|=>n=!PH)IjOdMvOzNgNsAq)`pNXkvQ`TVZ)k8Eu%Z7x|Od&%s7M^
zt9wLO^ZXuBgH}1K5#OQjf!xi^cdE*tQpTdTKLB44o5XzF_XHzN!Ip}4t8=ivA74Hx
z=qTy=U3_4k*B#R=CY#>HYEww5G=HKEHkB?e&!@`Zn)U00nBfUGHR9GUvLV<uQ5`XJ
SW>DWV1|t=f^`VKlhW<Za!fU+%

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/X86/Inputs/String/main.o b/llvm/test/tools/dsymutil/X86/Inputs/String/main.o
new file mode 100644
index 0000000000000000000000000000000000000000..29716a88f5c07540cb99b4188776e6b24326a6c8
GIT binary patch
literal 50140
zcmcg#34B!5^}aL7B!NJfA#5s3SP}`4giI0^#bJ%?YXA|&agt16Ae)&<0*H!OQ4|zZ
zR77!CT<X3rRcotNYpb>{b!oM>*8NXy>r%D;zwg}p-n>kL+XVB=opbJY&OP_s_1*X0
zeeeDLzaRZCT`5<J!Vf|!!def0auD!$5W?pK_w#qmeOhoa)8NmF!=_^BK at fkzU@W{g
zrg<G-T)u2^JZ^E_=>-00kJ<kFVWqMOq^gZ1)?YBVvZ^W=URxDzj0Iz%%3!dqJ+HCT
z&m`EJrj*-C+yM;+tD>={Nc~D9OSCuK*n=7Qd(>h~JkfSASRJlxUKxZ@(Fg{o9W{B;
zkw#moLSt|JG7UYEU=L^;la{^OhN=$j?LAuC`MV}+QqVAQ(xJUjWo1*ih3(VUzirEP
z!rM*T=N=z7WVjCPMe1uBC{MH(F#cpu(y3pn)^zJHl*-U-hxY11Rbn#H-onduB2$g(
zy=!#b at ta^T)Yw=X4%Ub2!cizC+FNAo9cv7}|2^$BRIZi=Nwjy%721<w#-SsxGfbT9
z- at nFCRieEYuFwgsA+-8?+Ka7g?6AB?Ua9RJnx*NVztdh-Lmm8z1)J+zBlXq6;GAhX
zrT%TaRns>Om~ppKoKt>__U)pvgz|=01#6nn8d{h*-WJ at Z@nxnx-Zl1mJ)-BSOr=(7
z4J*AKZ?%znv6xtYdvDizccy7N>0V9y8+(Yg at y`!{bBAQ#qpM0q;2)KU4?{X1Xz8O$
z?L|T1k6M7hKW4!|UG{BLesJIaZ^?`;f1kXxV#aA7=FHf(;*}X&{_-vp+jQGWuV~=g
zg-5)OM56cz{THtI(HW=xD(9HV$E|q$12uEY6PC?6TRszckIWu}6!Ty49<!|JF$gVf
z`LpFq(V4TYY!hTw5}25?<<l8keo3p6s-yIY_7dYWo}BJwj-VNu@(7|<JdU4lzH#+Z
zeU<8)u}Tf<je5_hQ4=Pk6NGDP8`NZu?VPIGQ2olBmT*%v(ommMTwFN1uq0==pasRn
zqe~d~7nY6BS9PICePLB&qbgbwg?dqCbELL9S{rH!7lm4Caj1&Miul9no5zG`tQs>$
zv8oJ3BUJ{RP_-)5G%5$8!w!S&u)`P+#+pKrSX5*Ir!WLJt3t7cCN0Vdz at F1u5W}mk
zp?*TFsW}YU at _Dl>VkI!^FYZup=A6pn@^b%Z99CB~HM9n6!}Tj;tAgRCriP~S7T9hN
z|8S!X&9PuZO|S{I8g>|U!m6^Np%&RiS2Z-nf_0(j8WoMK4+lBzD7(y7t;Flf7R9S$
z`8-|X;xV?+q?<XfA~@a#XI7P$mya{iaQUJNf3VKVDy$kCBK5Iw6I?Q!xYDkzY- at J@
zY&{iR+-RAyS}GoQRA3u##)hh^o5Im(`JyUiSk)A+2{(o7tHR%%Xm*vVYN$tFvs~A)
zHWqZvw8=GI19b~#x0qU2wG9{n&Gpg9%KC714yq#V{)Co>NVRmW4y+ZAt`6H(x}d5~
z#iRQx!MM86+8`SnUBhCj+ky45)fh`n4eQDmRKc*YDmblCNiS*JQo%@F;}2}SQ8{|h
z*lntNA3CMg6DRDq<BiH;jae3glQ~LtC9>{<(;_uBi`kX!a{ZXz$@bBW$|kVe8B0!S
zcPA*_F=xcL%p9X~YC^S9&Jhc+w6r^UeA>ww;b`RI(zY5i7gUuOkG8P}_StxhURFn9
zm_0+a6C at j_Beq_fyg2#Qhhn30IDnAz6gD3K6`Wav at w6&jkHJuh6~hE6ZB9Zj{9g6h
zrgw6{vxok`Cb7C``J&k{@B>qqjE#nC!&v+@)U(lIIDCYgz%{PZZP?UY#ac7AznAV0
z^q?41y*)r>&O@)lyjVPz^WDm(P_6bPR3DpJDF=sgw1bsGafIk$(N28=r*LZow1jG#
zopaXy%~!QlV&FG4hMRa)%aP-Nq_##MjzZRC at I4zj?ysKJzqN#;aTHL}N58#X)@ZSh
zsQW1r?CB!?aIfvI_3iCpIv$RadfxmI^<yP1-+xZ5mmk%|$790$UY&gZd1Fap<^BC^
z{lF?H=>#7g^%LaWuNN)BU=!v9457M49?HX*r9+V>$8p2CR%^GK_+cwQ&X`T%M(5OO
zAG+-2NIPGGXq&nN?9k}=!6m52GU^1b;+Km&Ru?NN)X2J$qbq22C>D}9F)jm at z5dW^
zs$lI}h$b&uH2LUY#mwd9!No@}C=W6TmuXF*R{XX$G*w4I6B<AY9q%N5f5#eJAQt<b
zO*FHLP_d(7xNHR0W(`$dUMA%$pA#8fKBp301M!vNm at IZdnX|PH|LL-pmB-9#RNB-~
z{giNdU1MzBlu#7Ya);I9=o1OuXjD$IHLu%~+P76<+q#((DMp=ONXP5sd)3DGuwoYa
zW7`!d>4vN*3znDFM4F;(L!pi~EI!Z~+O>S3avBp2bBTtsY33&=Ts+GIUb at m~Yp4;2
z{&7J?4y(sv1iz|pY>2iw^;VI3tWra at Sl>4VYa`K^o;KCV&MClIH$Q4_sM6~zr_EqX
zB-}c)3JXXa>71({$8`bG!C1w?v_|voEPVF?gx3e`)zgpiK2*U&aaqt_q8-r*7U$Do
z@{U!+ipL~2A?D{!u)F|g)5-gnw2iXL at XAO%dWcXJ!4(Ovl6jzO!qJm)=>z6m%^YKX
z<RQ$;OU|#vcKf_|qA6!+ZO;yWRL?32%M65HR&`Ro8&gTP*qA1(3N(WgPF at 5I$Lk^y
za2zu`Xc9g6k}6o-CEY5C4zzP|e;zp-F8N8J6xXD9^dL#P at hoG>c7icgR`Y2ldB>`B
zDM^wxHnz&{U4~2AWLcGI2BArtD>WD4NRl=-Mqf!rAJI(G2A!7)lkF+vaO#2kfw6UP
z&tmDISx^3`*=!8X_jnPrt_q{Vs=`h&n5<`G;ZL}!1+LLEa>-ic%>-RY+?}ooHP^<1
zJPad)4)J8OvkTz76!fDSskkJ%3O8cb1Y- at s8aRyguQQ&kqh(dK;Slee2&J{8CjYW9
zPuXBjXwv2)YtcZ~g|=f>BwJW9muwOJA@&+x<xOt%X*)?8X`GX=)E$}hS{EieVJQhK
zNiQW~;{Yv}$6!YU50v^eK}V8p&o(yeoEPbT)VR0Ip)ESoR%ewG$BZPqE at xz2^X+Hk
z4)A2Nv+DBz^{DZU&Cyl3tzESS{odx2b$VQ5L!&m at f_qh(P1a^vO%rb8V2Tz>Yst;{
zmboOmL#fmqP8(5$Njqg3OVXz?p(t-BThoL at lC6HrW@lVaux!aR))`ZdE^g;cIkv6N
zs<Gs!9IL(#&>VmZJ6Nk?b)XL`I+k?l+ZgSHMz-vAN-H~zby`6?p`DFeawEiXm18E#
zjC-A(<!Q&}548ISsPmTLI$abeTy;vAWb4S7>$r*zsPT&NNnfYM*;`|6sEW0rhq8$$
z>vy8v<VUl^VrPu!w&psqxXBL++qI6n6k1(3Rg#DN at 6HDIXp&x#f3I9Rt@`&{V?RZ!
ze9Lr|)Vi~jTad7;4r7QMD=R5`W1`KK*q+A;P;<#vzjaGb-!@9hw=&sy%ZoJfP(`vu
zE#<xiSR+Zg-ik}GTfo|FB|C82#FMsPT7wOAdIesG+uEIQSzBA=bSdLFsg{Y`>ZF3|
zll`Q8Dr<69nM9Iy&e-gnN^=<NEXO*b+KNk9ZMepY9TeF6?d)<kn6$fznRHHtc4W2F
zUG0o2_DdDlhT7M#!IJm7Z5EwWzwM27wxgX<yJH<4xV~XOomdN!cfW(oI;pbvWBGu%
z+!@tACf=z#sCDVsomJ`Wv+ATe at 7QqiRo>oiC)D^@c^<C`55UMS9}`R3S=+32)|c!$
zE74#ltT$|vX!p)6aOay#er;8ZeW#K7mQYg!JNu(puR5bFd@{GHi^pLHCU1QPLpbQ`
zTdI;pBA9e7W8-!tDjSG(5j3By|JctdTVBPca7jDrG?`@Oj^Q3aJVGds#_2r<vMtaF
zCGBr9a^bm#BNz6OwotP5T#PNiEQ;)xZ&MN*NxmR at o3SGgs~m0eNUFQz85(I3+3#Vs
zh1oTel;KiG{a|B?Y^bm+3_$X=gB;kVQWwmjP34#zk}3kG0^4Krq!%C8YmX+~nUIrR
z6f37T#W7&=mA1c}^qxGEjoFOLM+Ls)!8`le+ at vZRQ(=5`CYE0h<4&u9{pFS9%!UV(
zS%gIAJI(F(_LFlMb0l_(H^`tNlXMrBeN<R-)p7p>4)WMlWn#&ihO4qA%PeUn(wR0p
z%U1GNP1!g3=z8TkTyEqa4_g{Y)=BQFFs5W>6Tg$ed}Nu|kv!RKi!n*deIssDvwDUT
zNIC=5nLKo=Z^@g*kGbUEUUC4l<JI(Ud-627 at mjq9a_&E4KG>IZi81rkHME3-)}9AE
z at 9<qYIurb~`SWqhq;o`7J4$SIDS6JLz2Ly*w*Oi_u%+C8zMavZ{4$;6QOXEzGoV-1
z*4ob`#LwkA5++;Gew at efw9(kM9zcoWu~s}9$EkL|QapBurO;yKcy`h}UKKyvOn9);
z+ETKpY7yUNf#l{PaC;g^NZ=2jP+nD~!Y4S&nW$15qe`uFi)n(2^EyC9Nt+vz37Xcf
zc5{Yr)^7<)@!J at DzJC9nm2$jbZOlWoBL6L_=Kh?herNUJKAv-1MuK}|dHpPmYw{6g
zI6MZ2cb~O=Jw-yIVm}T=c7q_PGrE7ji;JOWS;t-xN9@}Yg-?hlibT-7c69%#N?0Up
zm2TkMBIL~yO239f9%8Z|C6<R`gLM(Se}Sh{7)scahUHhxJg1;veS=qbti%g?<TW at -
zzZ?#)Wl+JE##qxZM?BaPtE>$I)YW&gLnL=l$J;<@>ndz at Zc!v0HFfgrb8Vy&Zx6z%
zug1I}$Z?enCmo4mo<BE7!%-%vYG{^?hY5(If;un|l85<52i3{#jWeZntE_{h_HEO+
zr??wk?5HSh9JU>pG1^AYs*01HFB?**#A>`HB^Z;Jz(})z=Xq*QbwhJyZCKTX>#A^X
z8bk&Q{9qKM-cY<3Nk>7cj5okgNt1dj+E80dcx_D+ud2-%L(Nr9OG4wr^&w;vjMU6r
zreA!qpe2HVDPqy2vHfUPMI at _LO+uoL=qt<Tj75UR%BD3P+UBsQG8HW4?=Vj>lNj at 3
z$i_PM+_DZiQ^Xq9upl at wSG?)1`?ZrnQ*ag-hblMk{NZ3HgbPE!<avC=O8kg{jw!Vo
zM_LGoYQ_)KlS(3c%<0s`B{`Xd^tLKQG8^GyVpOaFz)PtR5tDYz@<YqS8qMmc<%J_*
zTxh%CNXnEojtt4$`7vT=$4ERkD~(vU6WOtNR(3MvB(nvkfa*{aUVz7$O(RUEIWT-d
zhptM^RYzJ7KcTrHhG%%{RIQHJ8j2~dMww9pK7t1- at HQ>};B^bq{MEV_;4wCd*63)B
zs;O<zg9f at rM@EMv71d at FZ-y<r!3#?ATct0P)-;7NFg4$#-~6OPm3(;v)+uWvF-)HL
z36}F0r~2V~T%d`ri^fm}Ln@=VZd|oWoe*UzjGB^AWppi!L{+W)$S-k}dF@(-Un#zl
z!mBzA*?RoO8d|GVt3E=3#v1A>fkp{O5eI{qI&$V5taO7>O)>xDQChq<qNX;q5^s&D
ziC~rqR^k8>j8-;-;DKuZ`eClx${Nj7H8iY=0IsTSpcJKMt%k#ER1KalM=RM)+aS{!
zmq at zL;GtbCpj5EAQsIrGc*C3J$}(W^q**epm)~0GRMxK1S;7#9ZjH{erluC#<MHHv
zjG7=Vq&1Cruqg%_tqRoxt~c?hMK#`H=>_p-4teGsZ#`Y9RyN`;z0Snuup((f|7Z<{
znpPr&L+E;V5h-47r(-Q9tCpxSZRgoyWm<zauTuPt!og<nK at uH_vPW=#KYp6=YB*}@
z+N{wPWf6$@<UZVEC8NL+i{XuZ at Q5#w)X!UCR#P=R{^ONtczvD1D}_jcHF)N!Ug=-F
zDl)92hGH~v<%I_+`3lKcU88gYP{hSQPJ`mVRY<8`Q>pZw3R0#P0|u9mjYLDW_04q=
zWf=5p!5UYEGzLavm3Y_S8e+m|tg1fNR7*@4ja5fh;#CE}gwYt@*3`I)m at pbcdxe{b
z38OLbi<mG5Yp%zurihWzSQHOMhKUKIv1UBmBld&=HZBrfYdfPkYGT6BIU7b}CUvYq
zr$$?0p&1__CXV5XIi=0ei9_J9GHsJ8j&RPDSyudNwJTk7+FS6Z+BIiTyW(4|nn%f6
z?W)(D(Y4FlYSlh<?dsQ@(X|_()oKCi+D)K2qbqgK3U9Sqfx31xXwK-`4bf_~#CYh&
zo5HY0TdF9snx=*2l&BZ@<1i)KO%?YMsNGm52hN?+Figw_k_naPpN=Nv9BV-x at Z(g_
zpmQ*|@Q;}irvY_bfs?Fiz{JOBb!eSXtg;bZhhqY1tAW=UitZncQLwTOhrAkc>l^T*
z)*4-{82YVd`m=x*ThwA&0du2Kg3KD!hT%+w<A at MFNil}e-HKRiq&m#001y!~X at Sb&
zrCO63O>i(3wAK(qaWEB_2U9Ryw}Qy}l~EjuC8{YGtVDSf7g)#bg)3$IS&p{0N=hsj
zxeSHkewU%G3ucS1y$pr&ewU%ztSm!ecMMdqMCfpJYng>yyYMZm?AF#g)oPa6EEAWv
zpggWK2OZ-IR+Lx?RA$wI%Ir;s2go4wYhn>h<Thh13}Owk9^f@`bmJzyXu!Hynh#Vj
z7X*;?f<SVFl0}7TF+Ic(=>VMhTda;|QN9uuFQ=@k<#-!jkCw)wF2BudXC at dl7)$!?
zEK`eTPOC5PjAu-z`s0?SHP_W)6L8{dqU5ErquRZB at c_LI2}R>+SPNf}6TjqfpfdA!
zklDAr<LXDgV<q7=VN?AmTx?Y&sy6Zs#rQi*6TB~aiQ#Or-Ef!0RV?;C8>+C?4P(8J
z`vF_!xI~pl4e+$B(k}1kjOf+<tGsDM at 9$s5<#Xj`WqVSxynPSJdh3*fe6F5&zqNb3
zD+O;4Pa)aj!iNG<-L5g2DOs7Bhh-j)*Y|t+tC`v3 at M7$=?kXi~W;W4 at 2TeGrKfVc&
z-UqUjEUlOkms7n<b{jKYyF-<Vlx6mX%*vo!JRR-&GikYdA>5(*go7p?1Yi9~mF0nn
zQh3;-ov;e1mtwrmyU<mirPI#LcBJkZ#~o;P9JRHT>J>+gu2Q{=q^wHyNp;Q4ww&)f
z9F;<c`%#P!EsO?X{NN%8lsY6EWCFbFPk~k)P=q!b7%%m>OqOm?LZR^O29u<_QiF9P
zP;ZFaSRCr8VBo`SpEGTrbM5wlLS9_KQPe{Vm8q^w2Rhu*2aq)1b~cmEH^R7TW#rFf
z{f}&iDmAKuJXwf>428zc?1vgFbh`#*+Z_(FBFoO4%(?ySrWyd%(N1gaq{Z6FahdEQ
z{vOgCC3!+hhoQ~_=y6Jwc?B7hhc+1NLQ5(&ZZM#+kd3EWW at Z5FVN*oyaGGH|PUtQ1
zBha!cU^(chu!&CBCa}jUHHi%*9R&s_7s58n>_{}lGGsT{R7=YsXK+AH!;8{Yd4jG;
zj_fT3n9f((&oBxeM+P&kE~3;dt9F!{ZI3?qHK!2MLeI2G{nj63`6mNTskt-MDcL9C
z&H3{VhwDnsw=}D>*B?}$H61m#z at yxKIVrHp7kYFF;eb+$n0OPtuh2Ri%M>iOtgJtX
z7M9pjRE$zf5$$IgR6Qo?uZQ6M`|<++R5cm}<==Qs<d@$XaUTyhr5Zn}sjKkY&-I4a
z^SfT)(oTW+ja+;J;C;6%eF~~_D*)Fu?zA$zN?!yYxLp~O5xErJy1Xf>i)T41rk^V<
zrR!O+;L1o*nVx<i8OH;^pHSBnm9Ytt&lt%><ZeXDX}B9dm(ayiEf)Ub&R7FxA+_Fe
ztBfWq@>h38#(G3PpyX}0SEY}DXI=5B0oPu47tdyh`nmq;?%I_m|K&#hE)Yo{LC<yl
z2gWXi(s;^0MKZD0NYUqRmrDOD3Va4$yYIRZ*6tT;u9S>Nz??>%6gb)K&*;li{_GUj
zH`br4``dtBy;EFSZ*hq9kZ3;>^}a(a{oy`1ETls1Dz{c2WXbnYuCW{^rW0zxFiY^?
zxbi3`=2Q+?0ymVstVm;iQage77jb)2EGbiXSsNzV3`;;y#h(6gq at CSf#UZV-q)o$Y
zqhTjz+(^ea5L~N_K>2zj+Dd3m3Oa&vWqm_u(~mtwsq+Y5?)Lo=v_C#Z;i^kXJ(MbJ
z0I$@jFAuoLnw>JKKwq6DTkDjGd%h<v*?Om}3(PBD_nyY)iB1`Nl=3ZvY!`xSYsz-?
z71J5gLvZ(U!uPs;4_PYbrraqix<oZl at n9so?sNMJL1X04b6WAOwcwr3l)gs*XJE*>
zcBQ1UbLkG4z6J(+5PrbzTL>yDm!=#lDmu?bsO+Z7gKpn at prbLCT$eko_{snYe3dh$
z?<BxaQv13#uKW&AA9Qlp4Q=2<0M!t_xs8!}K=%^9wGAwz1mC)F-I1~ob!wX2*A>uW
z!gsZSj{&ri^>}w1_<F$qqV_#bxaU`Zj>N3*dcf*>%)%>;*K;leB7D#(R6Q>Q{w5PW
z+!lWq*ksOqzi5je1x)lGGq~z`C7 at 5J`nV0LgK_LZaQ)hXeDe^!h|rTMFLCD8o!xgC
zpuZA+D&>8T1?w at Lo{cW~EC<H*Zr?|i-qR^upqhce0;=?W(Az=1>)gI#G<z$8>$mOf
z`PN&qXWQBEJpx&Jf28}pv*YW5))TnM{^XSD0kh1Kz3P<d0duJ(d)+D1gYZ+xrVc=U
zZ#rc<zgfUV_I{!)J~=7hE=%j*PAz(+tIzj$OW{9>3d%QnpvmG>r_9k`)<fYB2(B;M
zw7>5?E8!ujjtNQ1)N{rlr7l2l4NNudqx;?-VDAynF}U)5g6Ls6fCi_=n^XBF0TOsf
zYP>fn-xk2nQF~|`?H4V0SR3sDgOys1;3{&usH^q_OXhdV^ql#yB^%?EF`cv8yA3hc
zCpxtp)xOM9n3SlXd{<kt$xd0k+I=5c3QL^|y35QNs?;S2uH{adB-Vwy(o(4JP{CP>
ze_E;y?Nl8_3E*%hIW~5vrF>^u3MaHva1`oAORFh0e&F!(0HG%*UnwR8$tTuM!C~eC
zOKVFzEnPuf&{T^MT-!SIM){Um3g;$TP`<k@*^We+c#5MnMphWXbwP*L%|W@&(%Q3s
zEoVbKV(DMsvA&}<vW6Q6_U>O*`Hr=;Zs=IcQK2_jsy8`RrCsDl_bP9`$@bokwHzL{
zSgQB$Usd^Dv$P)USj*wz#1SU%CpuQu?S3D$QbwX>o=#<2eQ5CxK+QU9Is+ON)cS2|
zX<SP(<B#gO9Kz?h(EYtNeQ}0UzH5Mg#DuS;vaHsT>tBElABFg<ZQx0O&LjL*>P4=&
z_7#9WBK$X}kM`t(8PQVs*r{Mwu9QUi0tLp*z7Dl8Ray%FbSiKjHWprhLQWwZ`L|QS
z;Yc2YqVPYbLZTy4OG|kib#7}Z-y at cS%c<aSq)U-f$0N8>oeB;|>MeyVr-Ge at DbKGg
zEpLZf%7?2jI-j0S1&1TGQ1~T+tG83Z;mGeTg+We*L`Q}d8#9AD)Kb2+mcme{g2R!g
zp^)o`BY92*ha+Pl6ot`Fg+xboSX%xLwUqCDOQF=M;BaJe3D(XCuCY!9ha)#z3X`1*
ziH>+M&cw{r4z-kTg{4sLRB$+QCluUeaAbz(=bYGO(P(DcuE0gM!YN~C)T5s6D&H}d
z)^YpS()vuPe79KotDO2Qneu&U$s$f!JV&iHYmD)0_5QU?- at OE?A0W6kdmL-xo}UAn
zHx}@j9&^Iu3n6+7p|hQu+4li*j|05RGXyT`v!m>;Km@(i!*g at J((bhc=nd4p%cIXC
zrNG$_0O~Ow at I%rDMmYyal;{&}lurZnGU2D3%KrdTb{Np#I+c4(0(2hX=bUi%m4N<D
z_zzASDTgby9KrRnQT~9<kzEJqal)^92$%xCWT9_(4(e$YF#U`^N<HF+?hWqj+6hR9
z;Cj=U?qv&o+mSB2=m?x;A-LXg>Yihv?>TgPy$Liw0NszYn<{%WVy6)KuM|hOY_GF{
zyh1cJO;>ip*y!~aOCc>$LG>Cr(In0=GU;L*7OGb>WKSTt`a5OuKG>F1y`F<^@g(RE
z{66|#>B7CHBf%~v8tO=-dhG?2G8u55fn|vG>I+EVkq+4Vem at 0ww_CDlPTAChDC;ss
zsS^=gGmVUgTd$UFv1D_cGHvrq$d*h+x}^@8>J<Sb at No{<xbc=H3p-^xtD~pkOdY`$
z(K6NR1;mQWfvh&#GE#c;iqTxay?=fP+F&{up3VObOrJ^cJk|BFyYD-Q^|j)kd;0D}
z+^f1TUkYo*DXxAuq1knZ;I%6x^4x`Amuro?=W}5AX=B&XZg<vik(cV3i)fh8atk_0
z<_TO&ypXW_AD-;Tg~5RDlE%x0-ZI$r@{*=XzYXs3@}c`fk9~R0{hlYi6ivemp6*XP
z*`ZY00pBelxwl?yR6+MD=(zvS)9ZE**4J3IyM1Xo8_7`e%KkTGyj0;1q!I8Q$>L at E
z)08>~!96u?jE(y40 at 5cP=nax*O5A73RJWP$LTHHA&pXzV*7MEDQ0gWG_sf!RiX_&#
z`|h!1uNoPX7+LQwxMqOh{)>3lCf)s(>}?~9r;{e1j`~Qy0-b=fjr$`HnxiK;mpe68
zI>`(~M3JlL^i<T~y{wtER5bS-QT%sW_hXsXlkUoTk4^2XL39hD%=AytY_6<-0rvh6
ztV;hFthD17Y3W~s=d}*^mubG;R+{eVd426Pey}Q?-Amm2Z(4dc at Vt)V{wmG)2B@^R
z*W|<Oy*_AopJT$FBjKtva$n<{m;Q(b4%iS%D<723B-%^Wa|_^`Sj1({G|H}w^Z`(o
z9`{)q>fjKly4+8=4`xNB7eOYTKJ8ZShal?W`MoH7nqnKUYg6}sab4>4bJ6c5op^hy
z-8#JwgVCda8vVOaG|@jV73S|2_43r-tk{1eVy6>zm42huWHYG#g{VK1l8u{*>Iek)
zYbo2I;hl_39If+g$|2`KYFm|(?V<h)yniqQoGbMKSAP!Svk+0eFNKv0z)3mzS at d+y
zF?1AqD*aQ42V)eZj=}}|kzib at z1(Rt!7M<|seRn8?D>eSqsqbVq3GOMOT;DSz$^W!
zecipuvz{f}^8mu|e5ig-c>xTkV3Z^pR at p;<8p9iCIQZR$Vb619SKOp<UzOphI2Z-=
zyvASO&D}AQvrrH3WSk4YmGvx*`T7GA_=Akw1%5%`GXQ@=?R^<uj4 at 053k&{FhF at UO
z?iuc(Pukr7&Cr_O*J-79D}G*rOq%vpFx|T!1)KM0==x7X#5F)Wg0^`<++LC~aA77c
zA0nx{HAAHgdJ-}BF&SCs(q#6Z5nI#^NRt#pqv;nwCIj-QjO=BQibhOIlyx=JrSHP8
z48LU=;uc#Yhs)XLp|0EIC35iN9Z;A1#Eii_vRDpm%E-ElhO!5v9>x4FsTqx?-w&BM
za8gEgjis?$Dk<x6rc39Y3UT1%45^Mb4(R%z11>dWk5{Q7d$FV%(kmN3Ilb_62Y$ME
z3b>eZ`y3No$AiZuQ<03d>{K<>v$!1TJWmd*0p&$G&vV{G55?FSg&&p6?!FBY&r^99
zf!s^>dG=WEZ_&o`qw*dA`YI)VNR+$*l&1immsy?OF*GbcoNrWK`jPsoy5~=fi$vv(
z0>~3_&ueYfwMTi2AzqK*dHrx&lOKo4Qy}7{2G5^66kiLml=AJkSn_6ZRNgZX{~wLN
z^IU%z=a0&z>z@&PI!{f<eRKrRyHb3S=Zyt$Ji+%Rk+xI|;6j2QN}a^b9eNeeUsCch
zL77?RqMFq3)cP5?QIdXG{z_0D9?~bMyi>v7iI5(kovg^A&>TU<^hvI)C}Lh&r;HS6
zvVqo8Yt-Y=;_avODJLQB6peh32BvCAjrtlfUO!1Mr!AMxMCIbtP7Rw0mtH97QhXCk
z6m;>kt_r%0y@#>PX%fpU|Bb|sd|Sx${|TAVYdBSA773YEE at bxcLgt((WbO_j^KKS0
z|Cd4*ydh-aS3(x`$)}ZyQ9>3UDP+m<LYDGkRzc>n?LwAcC*+vNgdF=4Nso*FA!OGV
zLN3X~WvGH4yZZ>aY`Bm;B|<JQ7jne{Ay-ujxw=lsHEV at jdzz5z&k?eBmyjE-5pv_L
zLT-LQ$j^T*<d)}z-1?f3+usp#$3KPK`IV5n(oyXNJ?`l#<lf;z?k^GYK!9XGl~nS8
z>X{M?Hwjs}TS(+rLRP;nWDVP}U_jmfgf#TP7%CXhSSaL#`9hk)LSh?*wConL_8uW8
zJul?s*M*$&o{){-2syPIE=m;)*fc=M<`N-i9VX=Lg+jI-C*+(pLeAYF<boYSc0MEI
z!hZ<4=qn++x);*s?twxs9VcYZJRw(93%PQ=kgKi~a`nAJu6coEXx(Q*>R000Pr=Xz
zsimPO{7Pa?uL_BNASCv+kmdo!)NCmg(mGqn+Eqf<og!rYg+fkzN5}>@F2fWIJ!znj
zlP3x}Wx0 at zYlNJ-S;(eKg`9Seke at v%<n%X$Z2p&!GqQ0-reNrqV})#4B;>3*A!lzB
zvUQJ;Z8r%y=RP6lJ|$%Pt3uBIhmZ?g7 at Gw{cjgGWuvo}N(}i5TNXVsCLiW at Px#AQd
zSMCsU?Oq|*Js{-zXN2s1og{DNCqh=GW7aOni}V+=x>(4XBZbuRl1)KgU89it(}gr#
zBBb#)AtyW`r0I1b(NBcLGR7d?@W4PJ6HA3m;?<af;gi=0nX*yH)SW`6-6*8|5g|wZ
zQONZ7gv|J#5NrWr@>#=$%sxWMoJB(Bt`suwR3Y=v6SClXAqyW8vgiepqUN`Sv`8l^
zYAqZ`aIN at Rv`+e2(fWr3Jn;`gHoPz7q_pwWJbAE?Qzi at 9xJ<~YygE}*wCNlnr(G`O
zXAcND{W&3<-w|@gS3=J0ei##M87kzg at j}jCEM)6yA=@?zId`{^9rp-1|9K%hKNNDI
z`*2#hXn>H5ON8vgW*~r<R14X?UdW|8g<N)<kUdWex%_WJuK1sjEBj$lQBZW%SRq%>
z6>`mSLavPox$ayc*WV~)@2`d2 at TQO(zZ7y)KCa0W6y1E7ke|;Ma!ZYnTQ>{2?K&a1
zKPKdkcZA%XiF5ISqI>!Xxp$P12LnPLnlI#Ge2X0`pnX_A7M_6PW9nDaaYRhNVDN8-
z0e6jHH2q>%*0ne$dC$O)($Fpg$+5GjZYH#LyRf0h)rxeYZ5iw`g9hgfrgi0#L-V)+
zP_M`sK~ee=SJtMuae<Z^NFSI5T4tafbYav;<R=H_qjw|j6cv at zm1D#e7C~&Q(Tjjq
zGPf0SfOdP`E|FeAbEf3IA<sw)6%PWPPJAShv}#w at a>j}#G8PugEQ>}*&jL!zX*ITG
zkp{)G@;?vN5^l*VUC-+gu9AhYRXP<5<TRI`YhXWDi2l#1#%P&D)3Hh at Ay-Dud2*RM
z9Dp0=Pbr0^T|m+^{G~v~l=13A={%gsc{0l0=!cZEX at h797e4;wjPiWTUrmlDNTugw
zqR6hXyzVw`1JJ%|{FQ{#$I?rIQk0)3I%TZ@%JwiNIsaaA6qG*O4Oyo8c^*_I1z=J9
zzoDF%pWDm)FEdK6Orn?}RoMr`cmt{IKjerV#vebUWx{2l5=-b^8M!iYeu+vlt`p0O
zsY1?A&QGrNPt#E^ss1?t4qt+wBDBv0E<*im8h<sQ65;B}u{ZkpQ^shSMA<pYwo>{V
z3N93m7zKVt{p{#R<nk>1M0Bo{p}CI%JsoUUZ|M$@RBzxikZv<>1n!j|UI*}Uid2DX
zD4N-!=w^!M^W4KLKQamecM at IF7B#jWq-b_qkqZ2hXhmDpBzT&l>2g9LE;;;qo}#%T
zV!nE99C(H3;<l)<^(IC0+KN=*U82XZsPQuB1QYi`lsyY)tCjK6OLD20i3dY8f#SJw
z*C|$ksX)6e5Sww=Ce8-hNd3ieeW|gDYk}^j<e0cbTe=!(w`GZzZUp)}>PO=Gy6#`3
z{_;fhb)vI6Dn#Df5Pd}PLP?}^{gl8WJ6DzaNxo8F1I!v&nmU{FL2l{@R2W$Az|wvo
z9=Du24Fu~Om^&E4Jg_|nmKIW&k;^@i6ToH<$_+p`4Q#JLrE@{j-MPGAdo0-AgL037
zFbuZOpwfB at Gjh4CKOJn}0l8e-pGS6JE|>RLkR6oECH^gBb8 at -Ne~9ehTrTyWCOagT
z%l$u*9h%D}|GQ*|iQUi04i~#AbHL_{T`$=YVs`-9kz#iQ*->J5EZG9FTTZr6>{gI1
z${jFLsSwzMa%9A<2HUS#ros(i4<0D!X0V6AU)0LEVEgCfE=IClU<WRp<jELVk$*XO
zHpalkD*qabUy`bFPlDoJDjqY*;~lt66gjj99<3FHU!I|IuY=;PR18t^I8kK73=C>T
z;g8QyfqSX6`9-MfF;w~xfYgk@<HXOP6J~7vhQOK3zyQw at IGctvkoN}wuMxb~Hs{SB
z#hH at 5EAOumy-)FVGXP2&EiU~h(A3nxXB6JR>B%7sd_(klJ6}oS)jc(BE<`um9ymo=
z6y3 at yj@vS+`cQNS`&y!C@*s+?qVXxi$X?@R?^J;ihz!b?Atd91KWa)b(GfCbs=ydV
zhTAGCa0G#o at nI)vrj`R8cv at gK$>~zNvkO>53-CLwd=cRt+RyT%7<s}ty at HYRWt7TT
z&#MMdOYj$tHi{D1CV94<FlA2j-c!J=9>njFlE~IkQ%+>cEA;el7f~mecq(LPA>=el
zRr5y$&S8QJq*?f*0_PLBIIb~q7l5moteNMq-nb-iJymz|1lQ{@a5K?eiMn?Xz0 at wF
zna%Gbx<}BRI6Kr0DK+fB1o6^GAorvOo}}92q9#>GnF{=l=w(vMgv5cDDf*>|B*8~C
zuI+vTwuA<9-9<{h3B|#e4fXsT^y0xM=YItH74X5QsQi84ndjh*8TtRR_*1*(e+r&6
z=ip7={I4zkw4V7X^RPC=nd{)6^~*mPyreySc>YlEY|FuCj?NzmekgUejLY|fFCl-{
zr2KK<=aN5rM*eZ&&m_NfL4Fv#*gSVxegyng#J8`?Uk6_7?`X_F3H;5(FNo!z2L3+s
zJ6rR&fS0rvug%|P>F+)>|3dIQ2_JmvcID at sKGc&A$UFGh{47u@{tA`f%Sv)whVl=G
zzV2)+3Dz%d;`*RVf0Ta_B{Z))p>QI}Z2}m8(ZLIIPXb#GcF1%&%q#}muh74ZNvW%o
z%28Jvy&jT78lg3o{+fkioOh|f9tek>D~Vr(vhwpRFmNr=^Wx}~n+e?ErHVMM0(TO*
z(^iQW#dOgJDc>EJ)2rz!@HpWs6X6+86Q1W1Tza1LL6hbW6y6n=8Td8AcMB{<Ht=5w
z>sdkE71`~$(4qYI;CH6y11R*H^#y)qcAJ$lUvsImx`SgoWy~66IIo&f0Cw1X?OKAt
z8D*3$(lXlzuVgmk2+9_AR3xnsm`;U9+ZM}+7EpA)h@@2lO9||hnvoxe=va#M3=v23
zDuG5QxlBNDPMc~VdR<&K5F>Dt01k8=(T5Y!jYRiI<H$5CocxIKyv>lGL!D~{v{$Tp
z0 at e=fr2GOqEAL!f>QR1n_`qcp$pJ`rHJKi%sRCD1bagz{X_D$p{FX at 4n<&3V5=b^v
zZYOY?*ilpNW8 at qi2|UKgcH5K+JV9Vb9GLPffg5C6Re66z<TV1jXjsp+tWTBq7SQ)8
zxxB5!<nswdw}@HM4}3x3RvXavC#wZO at 1cc22HA(~W>%AX5V)Qx0)5HujmrZ43EXa5
zo33UIA+o^H9i=A*@(JJQPz;PFa<d@(QGsy;er~Ja at J-+m8_@kSuN>$?gxo*I)8-uw
zAWZO82UrJS9l<vp;Hdz%5q!r1?gVfp!H*o^4FK*Y_%8?eFo35Be&GP02k-{LZ{lF~
z-vRuSphs5*MJoFXAlw?0o9RTm138GO&xsBOQb at F)6Xp5#RHDP2=xiWI5gp+`bMtZC
zE(r9{9639v0o$)JcOuXhup>0O5o~^b?h>HqgB_WZdpy`niH?+0gImD%E6BSa<OzgP
zB~nUWu~T`!2k<(<@ec6s06sw|@H at aS0c0$K=0peR12B-_YzKHKfKq}B9pDiFW)VEf
z0agGwp5O`x7y-~iu*w0R0$?k_hy&aS;3|R*4)7)b_Y-V(fR6)so?y8RdU-Kb1zsh3
z8F at 2Q-vaP4!4p|SUR_O}0Z6R?cxoIBbO%td&IY`^NQ*H>^hEO7VD87bUOEV1VNUKB
zVDrKDTbP at Qi=q?A&Y$hs*l$k$4DdsM^_vR~@LcQl!|`P-FAd32cOw=HD<By+dUpQt
zpe)JgIVyjp#m`O6uebPl8Tl<1Kfhc4$riuBn}52+FYJ}S&EgmJ%in4775(!sv-rh1
z`PYHxoH%;P at ci4rbNU#)bhHZGhe+{CsZg1_xYEPn`7y$)+QCl|jtVSGMw#4Ak{2jz
zX`93x#$KmrZ3oGW{2j_;BA1n>vG_4zJzv?rnG~N<q$e&rg%PR65LHTxGL;IX6Q~k@
z<;QkW1+plr7F{lB&3xUPXgKbUHq)PIjh)z>kPIOjapX3fzzK;a3yC%h>d+lSbi14-
zN-5?a27mo at GH?V%x5^n}Tojl_^maKlbf9yHo-c<y8#V4#P;{4^b0mt6p=hU^8YYUW
zD7r^Z4HHGR6m5)GCgmy+C3;3%)U5wbq-aB1kqT at gdU{*bBshzrljF6obJ#)jltgqF
z(amj9W9CYV&XEo(*+ at YcRTFQ3=otk6*0=*~el_t0pr284eq18?Py7bxkR^~@5|`*S
zBY at 7M<jS~2r&$7Y9VL6?66t2*M&MM4ichtNkXILU3(=q1s0wT+u+;{P+C at Zn#O+G)
zr2ho=P;^m;m2w?L7bm3B-rPdbt`0 at _Qj}0`UCVioK=c&Fo5Vp$9(Q%n5$w;y at LR%L
zOo11u8Il1&_f+5&0{X0js0#d<K)v{WtRxOGG4ECd-l1rX7?)M7aHoor$UmaIHtt4(
zQs6(7pD1!!JV{GP`oPx|$sJX%l;AB`l>&OTeVPiSFNM-s@$_l96XR533rzM=X*J6d
zIGC(n^-1ICHP{fMdX-KTQ*AzxCaDzZPys)I_3`%82 at fZ#&!cogTo2NJCxN(@PKCTA
zovG&D2G9B$p+rheM9rH4t@#^Gv at 57<=`+x70(@65?Bb%Nc^R&cPr?FkQzqoaDJ=b>
z|AUt76;<=MQwe{ZTwP1MVmt3cR`Q{MtmG9(BjPYIcRDnC0OQ}>jff1?yk+-M6V+~2
zLSf`lI8x%K#DWbF(Qd{hxN<clvUf~xnNo|NYm;z9f9$%w91!#N{E1s-)ciNwsQdyJ
zF1Bp{5+d97>j}2!?=uMpfV!4`2C)ZztbtQYT}zm(`y@#GtYLlYM7Ei!85NUf;O>Wl
z3lh44@{gEHr71qhZpF#t{*qw0L!?p>(hxEbSQlgazWZR|=0%siR`baF*Pijpvel<t
zvf)ehk3CPmUywP!?}{t$8hCJ at 4+d{O_U>~pJnI_h--YligjW#WMfe<{8#3;XFbZJ;
z!W;x{Mgmc63jVRS8D~53k6VQ47rPUipMTtcMjh4@|JdsoZ#8n+(uO!~u$}lPj}e1f
z`LO1h#*(x1G0uGW#|n1l!QREV<%3nX#Q4`y-C8=VPlk?kn3m;>Rh*gGc+;7gPhWFh
z&uNG+MyNJ{c@!b=?|1~pM<DQzJ3|?Nqpw8mHpiW0)q;TWB!A4GZJwe$XxmJ??TM!%
zu&vV(*w)<<ya?F{y%A^{eNCZH%WxSCIuwC at 21_`h?BMi?SOF-<WeLI<gs}+Y5$F@{
zO)FM0^`?MMMPPZ$5vC)|LcrxXg_Bd!!MTD$)hmwU6$T4|RwA%|Xr~5r6~bzSI)nxU
z;!#73AIo&Fc(=kgY5c;oHxxF1{#xbcZP)!V<Fc>UfBfs4)=!J=xbuPy75f at LeE6zy
z`CAv=e|5p$9S^)eB)DPkiJ7;1yS3caT-s-1m!}@w`tZ(Y{<VI^n<GZNH{<fR|Fg<H
zZ&vxFrM(J$$3(ZjUiMAnXDhZ|?BD*U&l|2=ceMKSt^UWmFI?jL`#X!y_Aa<*cU8{L
z4f~!t<M-#?ck3}XZ@>2R)FWJhE3SX$i{+CB<)-(0uyDiPeJggqwb*m;U;9p+9DM0_
z*X+Kn^za$0P9I<W)z+y`-RP?6|EM=waNhd7{O2Eh(%a{)>;-in9=dw?-UWBO{K~@{
z%D(hYe6Y_Q!OGHJQ+r?k(cllWUV7`~^%ws6n-MvOe0c7=`(|GL{%rq!efPdG;`!y@
zbpQE at FMfIL9Y5Rf=kY7wTRr5%tQYq!_x|>%&o96H%|*V|7hiY!rs4%>=Nxmy7YiQy
z^y~Z+CtUgL`4jFq|C8qqd2#34{THr&=FrzK*nVlox>eUzzxBH*u^qdQTlLr6nv9B~
zgKnMp>DWtGUbb%Ap4pe5vGAbG(HqaqymwUZiH}|U%H$ny|K{w#&IkH^b?f>44|(<v
zsotU6cK!P=%_Djox%c#a`8|s!4}R?7-EW=HV_~l+Cq!4T{KddqQzxB&_SqX>y!Fo`
zZhPu)3m>@P4=d9j-m~G$;d6TYcg4^12kxs_{ws9cml57a_!`0M;bl<tIfR)A$09T!
zY(m(H at G!!22yY{NiqHj}zCS_{!W4uh2&)jbAY6)YE5a`kUPO2o;Y)-p43fbJr3ljz
zmLt?5Y(zL8;W~u-5q^vC7lcm`JeWlLA&f+*K&U}jhp-jla)dh&evR-Eg6e{Chfshp
z384a^24Nk-l?ZnsJc;ls!bb=ku-OQC2;&jvAOsPb5Kc$97~v*_Um!e>@Hd3d5V~Rx
z9e^+zVJgB>gb2b0gmV$DLg0&9euMBD!p8_MOklkb4n;T&VJ^b)2vLO12)ht&MtB6_
z1%$sNe2$Qb2?g(PQpE_<5RO7vjc^jec7&@D{)F%$La!{$edT&i;{zp}gYd_jlAPvv
z2eFSJa?_Cz_X!$^mo*6SYKMV%*N+fy1{#Pb%Y=9iZ6F at 42yxE^XJh>FayB7e<u+Q}
zj6sN7BZg52Q>M}4C3 at p3Z_84PcWR9m_wl2DDn6A3TYMr5|9m(BgwGd%@Q-&&n3PK}
zlT=>k0f?{pFk0L%KrL<uH4yLZ5*m!UFbR2|l at PZ|8ZF-IB*dML2I4a;g!oj8fq18t
z&};F8yuD0_w|$Kk_tEp%!JQR=xXT`7gC at Wg@3ArscUPJ;s}LnriePG)J4Xm{BZ+aG
zw-gBRPJ>A}!r0<wP6Kg|5w*CZ!r0;^4MJSyo3<DUF9~rAi-CAgn-Fh68(X|*O^91f
z4Yb45G0$?1U)+8}EnY at 35V!vl;`R^YggnFn=rOdafq0XeTHJ$b%*%5zfG$AX_{D8C
z)Z)DnW1bi62yt0%5^~!JA#Myd5VtxJ;w}@Dqddt0XmY&Ryw^@GZkaU+`Q%9|ARb}?
z@%bbWJ`)1M=U9y1HZvT#O~ydH5J+phK4>7`X(z- at wFZ)H`+&Hm$CQ#&C$;#<n$g;9
z3jP^jqs6Cs=-CGd(Bkt{Abj8k|9r*-gn#lnAkep<Zy>%*iW%IGV65@=ORN~~|A7{F
zHyLGlpazn^qRd8_+oPDCmn2Z3{FB$^fbumuCLy;=P>VY#j253YfP&(CJD~MH1pM>C
z4iG-E0m47NVTwul1}u{&?^_b$y-Wk~qAMX at i!}+kO^XmOv6wsu8aKEH!)WoMAhmd{
z&_LW!L5TaK4J41r0rH?OOpe^-K`mZzG3I$+l at Ra3nS}Dt51__)&suH@)C$<x;yx56
z<PBD1ix2z|;xk0X7Pp=d;sy}|aT5n2?$b69x0w*)u5bf!R|Fwmvohv+OOg=pz8Ece
zGy_m`{3yabUew~PHj|LM;t27S+9Z@$G6CXaY6jv{LDb?CZw8Wws{r+k*95Q4Qj1pt
zjFvpz1nAzl7B>h|i<`;VE%C?QFNC;}-6Z7Z8A9CmZXkJ^6d=AV#6Y}aPc2@^HxPIG
z5aMPW196iIA>QOS5I5iv;;Fi+3GUG$#4YwlOP+xO#C?CJY57P7wfGc;(R!h)hIrCx
zw1$~!iW}jK7B?+1A$JiOi1$7T at lL2o$ome2cp2SjaW at a4^tksEjH}#bWVCoqfm(c$
z^l(u8aVHBQUcWSD<fcAC+~wDUI(kPFAwGOyY;hwHAwCLVAa36w#2pa^;^rhm&&3n+
zF)u>guV|W<w^s=9GQLU3r-0G`@i|od^Fc at uK79(p2TMV?854w0Q-bi1TasvqPb3(K
z4=<$x;yZx=@d-x|J~YNyJgGcf2|ez#G;Seg{hb76uyRkf;(XYae;egjpAmvJr~yH?
z8x|vu>D$R4HFDGm|Juo))3}^*b|ioEJLLO}99 at im?d)4;zOMC)lxwZm<?WW9u^n3M
z3OtkbF5o%hH{TflaJ0<wZgx-Y&ZglX^`;?wK40sxobqSsO+79395f~MYAN_0_AY?h
zyT;zP<@*ryp8Fnpe}mqAM$gnkyK=Cs{Bx~eFh^=4eRnFNUaLMvA;L0joTtml{=mPC
zQ;cD&ywi1gc~+Dv=S?n`>&vX}3WSx9;3}Hj*jO8>3dQgZqG-{ws)p)tVW_dOXlg?}
zzNit47EKGcglq9xgQlXz4Gp#UB0<E`n-;DKHP^-p*W!y9MpD!qZ7Qma)E5;N7Dei-
zYMZOWMO7n57PS<s1CS9uVN_IwZyc;FDlRS at U07me`9tzrP#cQXG&I#ki{^%^=2t8$
zY&3wQ;1$zm+u~^T8Y!eH-A|ZR5k6{CB;SIH{*<}?^f^XK#*O(YOK3hZ^8-3)lAVSv
ziF5E6KB}^kgAi|+Z)jRaE*h(@4%ZZ};-s%XO`*Rw1`)m+V<)h`{AJSUI3tmUXiaN1
zIeeCew#YIm`5?ddW4?Z+^MI1&gysNag0y)i#%D0_(IW^j2hk|vVic6$G13BR at naeB
z7{6p>V*HYZHi5%lkTH|cikg&G)FeezX9qKIN_Rx?n9b}j8#!{2?;DvovXE~ZA!-?Q
z#90c=9V~_BpvDYzM?eH?M_a%upc at TFiOmuPpJ8gF!I-fX<YO3Gxk`T+gC_LnNC2}I
z%?C4xTjrR*`4ooK8{O7w2~llXi!^V21;eUunCI66V4a^Uu=D}7Wg+MH1PbwyI5~Qx
zmZ&cFTBDz*d)Ie7DQTNhS~sP1nU&JI%+nKZ44x%W%O-GXM?ZK)T1wN+sV<L7OSwHQ
zW4k98a`k}6({+z0d$}h)?Qf}W$~I?a<ah>mot5grJCv_ze85u%9+H$ddpv+_kS67-
zQy%b40XHu#qsHyV at kzY{pHK${FM)bNp8!SG74SIQ4fIA(bcBMdKv8$ScWYX(85E@`
z;JFQ&sDM|NagnOvC{U~)3vhzO^-BSkm6C3<k&grI0^F<_3V3{FI;_cfC#Jxxb_?FX
z-3ioO+BJrrYUm6 at _hB_l`R#_THFO~C5P#IrD-7Le=<$Y5GBn3ftSVWaG}M90l7DUI
z5Ew&z?nqPu?XHDV7MP9D<KOwHlq_J at +OWXLw`;Lnai{*HCJt88ziHxcnD{;uPe=M5
zu1D2#CVnXr^k5?M_ZfIcRJ{g$XZ-PmcoF<_%5O|aKQAGEQiA^Z3G%BF;+XX84}1O;
z-*q_fxj8>sVdwS}eMZ7jnSOk at 44<#mhlrU~{5EaE_dLsijhD~1;VW at XGpq0g;A!~Q
zh6>`tCNeW&qQ!SiXo8<gN!GUWYveGtq at G{x3N8vqoAIp{hw%h2+k9 at -uFoI$=?&-i
zO_DX`_~=S-d2!hSetB(PxV1tK)P8>05oIbaZHq6OJ<ohE_D3~OIc<&?lNFKm;ZCp?
oT)B2_5GM`MhI%YGV(Wq}qt*1OQ}JoKs&FH|)5Wi0j^@<y|4{hK!vFvP

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/dsymutil/X86/dead-stripped.cpp b/llvm/test/tools/dsymutil/X86/dead-stripped.cpp
index 8a72aee6fb38fb8..6ea5ef22a65acbf 100644
--- a/llvm/test/tools/dsymutil/X86/dead-stripped.cpp
+++ b/llvm/test/tools/dsymutil/X86/dead-stripped.cpp
@@ -1,10 +1,5 @@
 // RUN: dsymutil -f -y %p/dummy-debug-map.map -oso-prepend-path %p/../Inputs/dead-stripped -o - | llvm-dwarfdump - --debug-info | FileCheck %s --implicit-check-not "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}"
 
-// RUN: dsymutil --linker llvm -f -y %p/dummy-debug-map.map -oso-prepend-path \
-// RUN: %p/../Inputs/dead-stripped -o - | llvm-dwarfdump - --debug-info | \
-// RUN: FileCheck %s --implicit-check-not \
-// RUN: "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}"
-
 // The test was compiled with:
 // clang++ -O2 -g -c dead-strip.cpp -o 1.o
 
diff --git a/llvm/test/tools/dsymutil/X86/dummy-debug-map.map b/llvm/test/tools/dsymutil/X86/dummy-debug-map.map
index 95b1f726d4ff9e7..ec5d8e4f1503155 100644
--- a/llvm/test/tools/dsymutil/X86/dummy-debug-map.map
+++ b/llvm/test/tools/dsymutil/X86/dummy-debug-map.map
@@ -16,8 +16,8 @@ objects:
       - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x20000, size: 0x10 }
   - filename: 3.o
     symbols:
-      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x30000, size: 0x10 }
-      - { sym: __ZN1S3bazIiEEvT_, objAddr: 0x0, binAddr: 0x30010, size: 0x10 }
+      - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x30000, size: 0x20 }
+      - { sym: __ZN1S3bazIiEEvT_, objAddr: 0x0, binAddr: 0x30020, size: 0x10 }
   - filename: 4.o
     symbols:
       - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x40000, size: 0x10 }
diff --git a/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test b/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test
index b6d2f4391c70e3c..651a874ff3ec4c9 100644
--- a/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test
+++ b/llvm/test/tools/dsymutil/X86/dwarf5-rnglists.test
@@ -57,8 +57,8 @@
 #DWARF-CHECK: 0x00000000: range list header: length = 0x00000011, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 #DWARF-CHECK: ranges:
 #DWARF-CHECK: 0x0000000c: [DW_RLE_base_addressx]:  0x0000000000000003
-#DWARF-CHECK: 0x0000000e: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x000000000000001d => [0x0000000100000f79, 0x0000000100000f96)
-#DWARF-CHECK: 0x00000011: [DW_RLE_offset_pair  ]:  0x0000000000000034, 0x000000000000003b => [0x0000000100000fad, 0x0000000100000fb4)
+#DWARF-CHECK: 0x0000000e: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x000000000000001d
+#DWARF-CHECK: 0x00000011: [DW_RLE_offset_pair  ]:  0x0000000000000034, 0x000000000000003b
 #DWARF-CHECK: 0x00000014: [DW_RLE_end_of_list  ]
 #
 #UPD-DWARF-CHECK: DW_TAG_compile_unit
diff --git a/llvm/test/tools/dsymutil/X86/empty-CU.test b/llvm/test/tools/dsymutil/X86/empty-CU.test
index db9f70874971b3a..7b06607a74cbc0b 100644
--- a/llvm/test/tools/dsymutil/X86/empty-CU.test
+++ b/llvm/test/tools/dsymutil/X86/empty-CU.test
@@ -1,8 +1,6 @@
 RUN: llvm-mc %p/../Inputs/empty-CU.s -filetype obj -triple x86_64-apple-darwin -o %t.o
 RUN: dsymutil --update -f %t.o -o - | llvm-dwarfdump -v - -debug-info | FileCheck %s
 
-RUN: dsymutil --linker llvm --update -f %t.o -o - | llvm-dwarfdump -v - -debug-info | FileCheck %s
-
 CHECK: .debug_info contents:
 CHECK: 0x00000000: Compile Unit: length = 0x00000008, format = DWARF32, version = 0x0003, abbr_offset = 0x0000, addr_size = 0x04 (next unit at 0x0000000c)
 
diff --git a/llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp b/llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp
index e933be8fd9bdb09..928b14b62bc672e 100644
--- a/llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp
+++ b/llvm/test/tools/dsymutil/X86/inlined-static-variable.cpp
@@ -1,9 +1,15 @@
-// RUN: dsymutil -f -y %p/dummy-debug-map.map -oso-prepend-path %p/../Inputs/inlined-static-variable -o - | llvm-dwarfdump - | FileCheck %s --implicit-check-not "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}"
-
-// RUN: dsymutil --linker llvm -f -y %p/dummy-debug-map.map -oso-prepend-path \
-// RUN: %p/../Inputs/inlined-static-variable -o - | llvm-dwarfdump - | \
-// RUN: FileCheck %s --implicit-check-not \
-// RUN: "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}"
+// RUN: dsymutil -f -y %p/dummy-debug-map.map -oso-prepend-path \
+// RUN:   %p/../Inputs/inlined-static-variable -o - -keep-function-for-static \
+// RUN:   | llvm-dwarfdump - | FileCheck %s --implicit-check-not \
+// RUN:   "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}" \
+// RUN:   --check-prefixes=CHECK
+//
+// RUN: dsymutil --linker llvm --no-odr -f -y %p/dummy-debug-map.map \
+// RUN:   -oso-prepend-path %p/../Inputs/inlined-static-variable -o - \
+// RUN:   -keep-function-for-static | llvm-dwarfdump - | FileCheck %s \
+// RUN:   --implicit-check-not \
+// RUN:   "{{DW_AT_low_pc|DW_AT_high_pc|DW_AT_location|DW_TAG|NULL}}" \
+// RUN:   --check-prefixes=CHECK
 
 // clang -g -c inlined-static-variable.cpp -o 4.o
 
diff --git a/llvm/test/tools/dsymutil/X86/keep-func.test b/llvm/test/tools/dsymutil/X86/keep-func.test
index f307f5ad89900dc..021c7212bd8319b 100644
--- a/llvm/test/tools/dsymutil/X86/keep-func.test
+++ b/llvm/test/tools/dsymutil/X86/keep-func.test
@@ -25,11 +25,6 @@ RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/
 RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT
 RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP
 
-RUN: dsymutil --linker llvm -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.omit.dSYM
-RUN: dsymutil --linker llvm -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.keep.dSYM -keep-function-for-static
-RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT
-RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP
-
 KEEP:     DW_AT_name	("MyDummyVar")
 KEEP:     DW_AT_name	("FOO_VAR_TYPE")
 KEEP:     DW_AT_name	("x1")
diff --git a/llvm/test/tools/dsymutil/X86/linker-llvm-union-fwd-decl.test b/llvm/test/tools/dsymutil/X86/linker-llvm-union-fwd-decl.test
new file mode 100644
index 000000000000000..627df30344d8b7c
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/linker-llvm-union-fwd-decl.test
@@ -0,0 +1,65 @@
+Test binaries created with the following commands:
+
+$ cat container.cpp
+#include "container.h"
+#include <stdlib.h>
+
+struct Container_ivars {
+  // real definition here
+};
+
+ContainerPtr allocateContainer() {
+  Container *c = (Container *)malloc(sizeof(Container));
+  c->ivars = (Container_ivars *)malloc(sizeof(Container_ivars));
+  return c;
+}
+
+extern void doSomething(ContainerPtr);
+
+int main() {
+  ContainerPtr c = allocateContainer();
+  doSomething(c);
+  return 0;
+}
+
+$ cat container.h
+struct Container_ivars;
+
+struct Container {
+  union {
+    struct Container_ivars *ivars;
+  };
+};
+
+typedef Container *ContainerPtr;
+
+$ cat use.cpp
+#include "container.h"
+
+void doSomething(ContainerPtr c) {}
+
+
+$ clang++ -O0 -g container.cpp -c -o container.o
+$ clang++ -O0 -g use.cpp -c -o use.o
+$ clang++ use.o container.o -o a.out
+
+Note that the link order in the last command matters for this test.
+
+RUN: dsymutil --linker llvm -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/union/a.out -o %t.dSYM
+RUN: llvm-dwarfdump --debug-info %t.dSYM | FileCheck %s
+
+CHECK:       DW_TAG_compile_unit
+CHECK-NEXT:    DW_AT_producer    ("llvm DWARFLinkerParallel library
+CHECK-NEXT:    DW_AT_language    (DW_LANG_C_plus_plus_14)
+CHECK-NEXT:    DW_AT_name        ("__artificial_type_unit")
+CHECK-NEXT:    DW_AT_stmt_list   (0x00000000)
+
+CHECK:       DW_TAG_structure_type
+CHECK:         DW_AT_calling_convention        (DW_CC_pass_by_value)
+CHECK:         DW_AT_name      ("Container_ivars")
+CHECK-NEXT:    DW_AT_byte_size (0x01)
+CHECK-NEXT:    DW_AT_decl_line (4)
+CHECK-NEXT:    DW_AT_decl_file ("{{.*}}container.cpp")
+
+CHECK:       DW_TAG_compile_unit
+CHECK-NOT:   DW_AT_declaration
diff --git a/llvm/test/tools/dsymutil/X86/location-expression.test b/llvm/test/tools/dsymutil/X86/location-expression.test
index 5414dff3745b285..3bffc9aeacca77a 100644
--- a/llvm/test/tools/dsymutil/X86/location-expression.test
+++ b/llvm/test/tools/dsymutil/X86/location-expression.test
@@ -18,15 +18,15 @@
 # CHECK: Compile Unit:
 # CHECK: DW_TAG_compile_unit
 # CHECK: DW_AT_name{{.*}}"CU1"
-# CHECK: 0x0000001b:   DW_TAG_variable
+# CHECK: DW_TAG_variable
 # CHECK: DW_AT_name {{.*}}"var1"
 # CHECK: DW_AT_type {{.*}}"class1"
 # CHECK:   DW_AT_location [DW_FORM_block1]  (DW_OP_const8u 0x{{.*}}, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address)
-# CHECK: 0x000000ab:   DW_TAG_variable
+# CHECK: DW_TAG_variable
 # CHECK: DW_AT_name {{.*}}"var2"
 # CHECK: DW_AT_type {{.*}}"class1"
 # CHECK:   DW_AT_location [DW_FORM_block]  (DW_OP_const8u 0x{{.*}}, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address, DW_OP_const8u 0x2000, DW_OP_form_tls_address)
-# CHECK: 0x00000146:   DW_TAG_variable
+# CHECK: DW_TAG_variable
 # CHECK: DW_AT_name {{.*}}"var3"
 # CHECK: DW_AT_type {{.*}}"class1"
 #
diff --git a/llvm/test/tools/dsymutil/X86/modules-empty.m b/llvm/test/tools/dsymutil/X86/modules-empty.m
index fc415acc59f6d60..eb70f51230de91b 100644
--- a/llvm/test/tools/dsymutil/X86/modules-empty.m
+++ b/llvm/test/tools/dsymutil/X86/modules-empty.m
@@ -29,6 +29,6 @@ int main() {
 }
 
 // The empty CU from the pcm should not get copied into the dSYM.
-// CHECK: DW_TAG_compile_unit
-// CHECK-NOT: DW_TAG_compile_unit
-
+// Check that module name occured only once.
+// CHECK: "Empty"
+// CHECK-NOT: "Empty"
diff --git a/llvm/test/tools/dsymutil/X86/odr-uniquing.cpp b/llvm/test/tools/dsymutil/X86/odr-uniquing.cpp
index 0e3b974ba005937..d87bb5b73c240e2 100644
--- a/llvm/test/tools/dsymutil/X86/odr-uniquing.cpp
+++ b/llvm/test/tools/dsymutil/X86/odr-uniquing.cpp
@@ -14,6 +14,8 @@
 // RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -v -debug-info - | FileCheck -check-prefixes=ODR,CHECK %s
 // RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -no-odr -o - | llvm-dwarfdump -v -debug-info - | FileCheck -check-prefixes=NOODR,CHECK %s
 
+// RUN: dsymutil --linker llvm -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -no-odr -o - | llvm-dwarfdump -v -debug-info - | FileCheck -check-prefixes=NOODR,CHECK %s
+
 // The first compile unit contains all the types:
 // CHECK: TAG_compile_unit
 // CHECK-NOT: DW_TAG
diff --git a/llvm/test/tools/dsymutil/X86/op-convert.test b/llvm/test/tools/dsymutil/X86/op-convert.test
index 15725a0435d4884..9960d1996496d65 100644
--- a/llvm/test/tools/dsymutil/X86/op-convert.test
+++ b/llvm/test/tools/dsymutil/X86/op-convert.test
@@ -12,21 +12,23 @@ objects:
       - { sym: _foo, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
 ...
 
+CHECK: DW_TAG_compile_unit
+CHECK: DW_AT_name        ("dbg.c")
 
-CHECK:      DW_TAG_base_type
+CHECK:0x[[ADDR1:[0-9a-f]+]]:      DW_TAG_base_type
 CHECK-NEXT:     DW_AT_name	("DW_ATE_signed_8")
 CHECK-NEXT:     DW_AT_encoding	(DW_ATE_signed)
 CHECK-NEXT:     DW_AT_byte_size	(0x01)
 
-CHECK:   DW_TAG_base_type
+CHECK:0x[[ADDR2:[0-9a-f]+]]:   DW_TAG_base_type
 CHECK-NEXT:     DW_AT_name	("DW_ATE_signed_32")
 CHECK-NEXT:     DW_AT_encoding	(DW_ATE_signed)
 CHECK-NEXT:     DW_AT_byte_size	(0x04)
 
 CHECK:     DW_TAG_variable
 CHECK-NEXT:     DW_AT_location	(
-CHECK-NEXT:     [0x0000000000001000,  0x0000000000001002): DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value
-CHECK-NEXT:     [0x0000000000001002,  0x0000000000001003): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value)
+CHECK-NEXT:     [0x0000000000001000,  0x0000000000001002): DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x[[ADDR1]]) "DW_ATE_signed_8", DW_OP_convert (0x[[ADDR2]]) "DW_ATE_signed_32", DW_OP_stack_value
+CHECK-NEXT:     [0x0000000000001002,  0x0000000000001003): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x[[ADDR1]]) "DW_ATE_signed_8", DW_OP_convert (0x[[ADDR2]]) "DW_ATE_signed_32", DW_OP_stack_value)
 CHECK-NEXT:     DW_AT_name	("y")
 
 CHECK:     DW_TAG_variable
@@ -34,6 +36,6 @@ CHECK-NEXT:     DW_AT_location	(DW_OP_constu 0x33, DW_OP_convert 0x0, DW_OP_stac
 CHECK-NEXT:     DW_AT_name	("d")
 
 CHECK:     DW_TAG_variable
-CHECK-NEXT:     DW_AT_location	(DW_OP_constu 0x2a, DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value)
+CHECK-NEXT:     DW_AT_location	(DW_OP_constu 0x2a, DW_OP_convert (0x[[ADDR2]]) "DW_ATE_signed_32", DW_OP_stack_value)
 CHECK-NEXT:     DW_AT_name	("c")
 
diff --git a/llvm/test/tools/dsymutil/X86/union-fwd-decl.test b/llvm/test/tools/dsymutil/X86/union-fwd-decl.test
index c5c8c9e93e0a06a..c73db0e3f5532e5 100644
--- a/llvm/test/tools/dsymutil/X86/union-fwd-decl.test
+++ b/llvm/test/tools/dsymutil/X86/union-fwd-decl.test
@@ -48,9 +48,6 @@ Note that the link order in the last command matters for this test.
 RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/union/a.out -o %t.dSYM
 RUN: llvm-dwarfdump %t.dSYM | FileCheck %s
 
-RUN: dsymutil --linker llvm -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/union/a.out -o %t.dSYM
-RUN: llvm-dwarfdump %t.dSYM | FileCheck %s
-
 CHECK: DW_TAG_compile_unit
 
 CHECK:          DW_AT_name      ("Container_ivars")
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
index 90c40fd1e4ab62e..b63668c39c90187 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
@@ -39,7 +39,7 @@
 #DWARF-CHECK:   DW_AT_name [DW_FORM_strx]  {{.*}}     "CU1"
 #DWARF-CHECK:   DW_AT_low_pc [DW_FORM_addrx]      (indexed (00000000) address = 0x0000000000001130)
 #DWARF-CHECK:   DW_AT_high_pc [DW_FORM_data8]   (0x0000000000000060)
-#DWARF-CHECK:   DW_AT_str_offsets_base [DW_FORM_sec_offset]       (0x00000008)
+#DWARF-CHECK:   DW_AT_str_offsets_base [DW_FORM_sec_offset]
 #DWARF-CHECK:   DW_TAG_subprogram
 #DWARF-CHECK:     DW_AT_name  [DW_FORM_strx] {{.*}}   "foo1"
 #DWARF-CHECK:     DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x0000000000001130)
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test
index 78b53897346c48c..a1bb3ec7d846d8c 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-rnglists.test
@@ -35,7 +35,7 @@
 #DWARF-CHECK:   DW_AT_low_pc [DW_FORM_addrx]      (indexed (00000000) address = 0x0000000000001130)
 #DWARF-CHECK:   DW_AT_ranges [DW_FORM_sec_offset] (0x[[CURANGE_OFF:[0-9a-f]*]]
 #DWARF-CHECK:   [0x0000000000001130, 0x0000000000001170))
-#DWARF-CHECK:   DW_AT_str_offsets_base [DW_FORM_sec_offset]       (0x00000008)
+#DWARF-CHECK:   DW_AT_str_offsets_base [DW_FORM_sec_offset]
 #DWARF-CHECK:   DW_TAG_subprogram
 #DWARF-CHECK:     DW_AT_name  [DW_FORM_strx] {{.*}}   "foo1"
 #DWARF-CHECK:     DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x0000000000001130)
@@ -65,7 +65,7 @@
 #DWARF-CHECK:       DW_AT_ranges [DW_FORM_sec_offset]     (0x[[F4RANGE_OFF:[0-9a-f]*]]
 #DWARF-CHECK:          [0x0000000000001160, 0x0000000000001170))
 #DWARF-CHECK: .debug_aranges contents:
-#DWARF-CHECK: Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
+#DWARF-CHECK: Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0002, cu_offset = 0x000000{{00|21}}, addr_size = 0x08, seg_size = 0x00
 #DWARF-CHECK: [0x0000000000001130, 0x0000000000001170)
 #DWARF-CHECK: .debug_addr contents:
 #DWARF-CHECK: 0x00000000: Address table header: length = 0x00000024, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00
@@ -79,19 +79,19 @@
 #DWARF-CHECK: 0x00000000: range list header: length = 0x00000026, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
 #DWARF-CHECK: ranges:
 #DWARF-CHECK: 0x[[F1RANGE_OFF]]: [DW_RLE_base_addressx]:  0x0000000000000000
-#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140)
+#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010
 #DWARF-CHECK: {{.}}: [DW_RLE_end_of_list  ]
 #DWARF-CHECK: 0x[[F2RANGE_OFF]]: [DW_RLE_base_addressx]:  0x0000000000000001
-#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150)
+#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010
 #DWARF-CHECK: {{.}}: [DW_RLE_end_of_list  ]
 #DWARF-CHECK: 0x[[F3RANGE_OFF]]: [DW_RLE_base_addressx]:  0x0000000000000002
-#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160)
+#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010
 #DWARF-CHECK: {{.}}: [DW_RLE_end_of_list  ]
 #DWARF-CHECK: 0x[[F4RANGE_OFF]]: [DW_RLE_base_addressx]:  0x0000000000000003
-#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170)
+#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000010
 #DWARF-CHECK: {{.}}: [DW_RLE_end_of_list  ]
 #DWARF-CHECK 0x[[CURANGE_OFF]]: [DW_RLE_base_addressx]:  0x0000000000000000
-#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170)
+#DWARF-CHECK: {{.}}: [DW_RLE_offset_pair  ]:  0x0000000000000000, 0x0000000000000040
 #DWARF-CHECK: {{.}}: [DW_RLE_end_of_list  ]
 
 #UPD-DWARF-CHECK: DW_TAG_compile_unit
@@ -145,15 +145,15 @@
 #UPD-DWARF-CHECK: 0x00000032 => 0x0000003e
 #UPD-DWARF-CHECK: ]
 #UPD-DWARF-CHECK: ranges:
-#UPD-DWARF-CHECK: 0x00000020: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000010 => [0x0000000000001130, 0x0000000000001140)
+#UPD-DWARF-CHECK: 0x00000020: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000010
 #UPD-DWARF-CHECK: 0x00000023: [DW_RLE_end_of_list  ]
-#UPD-DWARF-CHECK: 0x00000024: [DW_RLE_startx_length]:  0x0000000000000001, 0x0000000000000010 => [0x0000000000001140, 0x0000000000001150)
+#UPD-DWARF-CHECK: 0x00000024: [DW_RLE_startx_length]:  0x0000000000000001, 0x0000000000000010
 #UPD-DWARF-CHECK: 0x00000027: [DW_RLE_end_of_list  ]
-#UPD-DWARF-CHECK: 0x00000028: [DW_RLE_start_length ]:  0x0000000000001150, 0x0000000000000010 => [0x0000000000001150, 0x0000000000001160)
+#UPD-DWARF-CHECK: 0x00000028: [DW_RLE_start_length ]:  0x0000000000001150, 0x0000000000000010
 #UPD-DWARF-CHECK: 0x00000032: [DW_RLE_end_of_list  ]
-#UPD-DWARF-CHECK: 0x00000033: [DW_RLE_start_length ]:  0x0000000000001160, 0x0000000000000010 => [0x0000000000001160, 0x0000000000001170)
+#UPD-DWARF-CHECK: 0x00000033: [DW_RLE_start_length ]:  0x0000000000001160, 0x0000000000000010
 #UPD-DWARF-CHECK: 0x0000003d: [DW_RLE_end_of_list  ]
-#UPD-DWARF-CHECK: 0x0000003e: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000040 => [0x0000000000001130, 0x0000000000001170)
+#UPD-DWARF-CHECK: 0x0000003e: [DW_RLE_startx_length]:  0x0000000000000000, 0x0000000000000040
 #UPD-DWARF-CHECK: 0x00000041: [DW_RLE_end_of_list  ]
 
 ## Following yaml description has Content of the .debug_rnglists exactly like above data ^^^^^^
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-default.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-default.test
index 90cb99858c9efc9..2c4caa158258d28 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-default.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-default.test
@@ -3,23 +3,23 @@
 
 # RUN: yaml2obj %s -o %t.o
 
-# RUN: llvm-dwarfutil %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --linker apple %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr --linker apple %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --linker llvm %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr --linker llvm %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --no-garbage-collection --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr --no-garbage-collection --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --garbage-collection --no-garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-NOGC
+# RUN: llvm-dwarfutil --no-odr --garbage-collection --no-garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-NOGC
 
-# RUN: llvm-dwarfutil --linker llvm --garbage-collection --no-garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-NOGC
+# RUN: llvm-dwarfutil --no-odr --linker llvm --garbage-collection --no-garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-NOGC
 
-# RUN: llvm-dwarfutil %t.o --tombstone=universal - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr %t.o --tombstone=universal - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
-# RUN: llvm-dwarfutil --linker llvm %t.o --tombstone=universal - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
+# RUN: llvm-dwarfutil --no-odr --linker llvm %t.o --tombstone=universal - | llvm-dwarfdump -a - | FileCheck %s --check-prefixes=CHECK,CHECK-GC
 
 # CHECK: DW_TAG_compile_unit
 # CHECK: DW_AT_name{{.*}}"CU1"
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test
index 232f6a5553e5717..46ebcf24fe64dc0 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test
@@ -2,10 +2,10 @@
 ## are combined during --garbage-collection optimisation.
 
 # RUN: yaml2obj %s -o %t.o
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
+# RUN: llvm-dwarfutil --no-odr --garbage-collection %t.o %t1
 # RUN: llvm-dwarfdump -a %t1 | FileCheck %s
 
-# RUN: llvm-dwarfutil --linker llvm --garbage-collection %t.o %t1
+# RUN: llvm-dwarfutil --no-odr --linker llvm --garbage-collection %t.o %t1
 # RUN: llvm-dwarfdump -a %t1 | FileCheck %s
 
 # CHECK: DW_TAG_compile_unit
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-maxpc.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-maxpc.test
index cb3b435ea9aa4cc..7f0533a882dd8bc 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-maxpc.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-maxpc.test
@@ -3,11 +3,11 @@
 
 ## RUN: yaml2obj %s -o %t.o
 
-# RUN: llvm-dwarfutil --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
-# RUN: llvm-dwarfutil --tombstone=universal --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --tombstone=universal --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
 
-# RUN: llvm-dwarfutil --linker llvm --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
-# RUN: llvm-dwarfutil --linker llvm --tombstone=universal --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --linker llvm --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --linker llvm --tombstone=universal --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
 
 # CHECK: DW_TAG_compile_unit
 # CHECK: DW_AT_name{{.*}}"CU1"
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-no-garbage.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-no-garbage.test
index 1f5ddd78adaa24c..1a3f29d127cefc6 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-no-garbage.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-no-garbage.test
@@ -2,9 +2,9 @@
 ## does not affect files which do not have dead debug info.
 
 # RUN: yaml2obj %s -o %t.o
-# RUN: llvm-dwarfutil --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
 
-# RUN: llvm-dwarfutil --linker llvm --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
+# RUN: llvm-dwarfutil --no-odr --linker llvm --tombstone=maxpc --garbage-collection %t.o - | llvm-dwarfdump -a - | FileCheck %s
 
 # CHECK: DW_TAG_compile_unit
 # CHECK: DW_AT_name{{.*}}"CU1"
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test
index 2ee1d73b6f92f04..1a8010e364d25a6 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test
@@ -3,10 +3,10 @@
 ## optimisation.
 
 # RUN: yaml2obj %s -o %t.o
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
+# RUN: llvm-dwarfutil --no-odr --garbage-collection %t.o %t1
 # RUN: llvm-dwarfdump -a %t1 | FileCheck %s
 
-# RUN: llvm-dwarfutil --linker llvm --garbage-collection %t.o %t1
+# RUN: llvm-dwarfutil --no-odr --linker llvm --garbage-collection %t.o %t1
 # RUN: llvm-dwarfdump -a %t1 | FileCheck %s
 
 # CHECK: DW_TAG_compile_unit
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index a1f18e6f169db9e..d00ef1a8c228b08 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -1059,7 +1059,6 @@ DwarfLinkerForBinary::AddressManager<AddressesMapBase>::hasValidRelocationAt(
     uint64_t EndOffset) {
   std::vector<ValidReloc> Relocs =
       getRelocations(AllRelocs, StartOffset, EndOffset);
-
   if (Relocs.size() == 0)
     return std::nullopt;
 



More information about the llvm-commits mailing list