[BOLT][DWARF] Fix TU Index handling for DWARF4/5
authorAlexander Yermolovich <ayermolo@fb.com>
Thu, 2 Jun 2022 01:15:41 +0000 (18:15 -0700)
committerAlexander Yermolovich <ayermolo@fb.com>
Thu, 2 Jun 2022 01:16:12 +0000 (18:16 -0700)
When we generate split dwarf with -fdebug-types-section we will have
.debug_types.dwo sections. These go into TU Index when we run llvm-dwp. BOLT was
not handling DWP input correctly with this section.

Added support for handling DWP with TU Index as an input and output for DWARF4.
Added support for handling DWP with TU Index as an input for DWARF5

Reviewed By: maksfb

Differential Revision: https://reviews.llvm.org/D126087

bolt/include/bolt/Rewrite/DWARFRewriter.h
bolt/lib/Rewrite/DWARFRewriter.cpp
bolt/test/CMakeLists.txt
bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s [new file with mode: 0644]
bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s [new file with mode: 0644]
bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test [new file with mode: 0644]
bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test [new file with mode: 0644]
bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test [new file with mode: 0644]
bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test [new file with mode: 0644]
bolt/test/lit.cfg.py

index 82111d7..daf62e1 100644 (file)
@@ -16,6 +16,7 @@
 #include <mutex>
 #include <set>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 namespace llvm {
@@ -25,8 +26,12 @@ namespace bolt {
 class BinaryContext;
 
 class DWARFRewriter {
+public:
   DWARFRewriter() = delete;
+  using DebugTypesSignaturesPerCUMap =
+      std::unordered_map<uint64_t, std::unordered_set<uint64_t>>;
 
+private:
   BinaryContext &BC;
 
   std::mutex DebugInfoPatcherMutex;
@@ -75,6 +80,9 @@ class DWARFRewriter {
   /// Binary patchers for DWO debug_info sections.
   DebugInfoDWOPatchers BinaryDWODebugInfoPatchers;
 
+  /// Stores all the Type Signatures for DWO CU.
+  DebugTypesSignaturesPerCUMap TypeSignaturesPerCU;
+
   std::mutex LocListDebugInfoPatchesMutex;
 
   /// DWARFLegacy is all DWARF versions before DWARF 5.
index 9175c5c..b88dbbd 100644 (file)
@@ -39,6 +39,8 @@
 #include <cstdint>
 #include <string>
 #include <unordered_map>
+#include <utility>
+#include <vector>
 
 #undef  DEBUG_TYPE
 #define DEBUG_TYPE "bolt"
@@ -387,6 +389,10 @@ void DWARFRewriter::updateUnitDebugInfo(
   DWARFDataExtractor DebugInfoData = Unit.getDebugInfoExtractor();
   uint32_t Depth = 0;
 
+  bool IsDWP = false;
+  if (DWARFContext *DWOCtx = BC.getDWOContext())
+    IsDWP = !DWOCtx->getCUIndex().getRows().empty();
+
   while (
       DIEOffset < NextCUOffset &&
       Die.extractFast(Unit, &DIEOffset, DebugInfoData, NextCUOffset, Depth)) {
@@ -718,6 +724,20 @@ void DWARFRewriter::updateUnitDebugInfo(
           errs() << "BOLT-WARNING: unexpected form value for attribute at 0x"
                  << Twine::utohexstr(AttrOffset);
         }
+      } else if (IsDWP && Unit.isDWOUnit()) {
+        // Not a common path so don't want to search all DIEs all the time.
+        Optional<AttrInfo> SignatureAttrVal =
+            findAttributeInfo(DIE, dwarf::DW_AT_signature);
+        if (!SignatureAttrVal)
+          continue;
+        // If input is DWP file we need to keep track of which TU came from each
+        // CU, so we can write it out correctly.
+        if (Optional<uint64_t> Val = SignatureAttrVal->V.getAsReferenceUVal())
+          TypeSignaturesPerCU[*DIE.getDwarfUnit()->getDWOId()].insert(*Val);
+        else {
+          errs() << "BOT-ERROR: DW_AT_signature form is not supported.\n";
+          exit(1);
+        }
       }
     }
     }
@@ -1148,7 +1168,7 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage,
                 StringRef SectionName, StringRef SectionContents,
                 const StringMap<KnownSectionsEntry> &KnownSections,
                 MCStreamer &Streamer, DWARFRewriter &Writer,
-                const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
+                const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
                 std::unique_ptr<DebugBufferVector> &OutputBuffer,
                 DebugRangeListsSectionWriter *RangeListsWriter) {
   auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher,
@@ -1174,6 +1194,7 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage,
   auto SectionIter = KnownSections.find(SectionName);
   if (SectionIter == KnownSections.end())
     return None;
+
   Streamer.SwitchSection(SectionIter->second.first);
   StringRef OutData = SectionContents;
   uint32_t DWPOffset = 0;
@@ -1186,18 +1207,18 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage,
     return OutData;
   }
   case DWARFSectionKind::DW_SECT_INFO: {
-    OutData = getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO,
+    OutData = getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO,
                            DWPOffset);
     DebugInfoBinaryPatcher *Patcher = llvm::cast<DebugInfoBinaryPatcher>(
         Writer.getBinaryDWODebugInfoPatcher(DWOId));
     return applyPatch(Patcher, OutData);
   }
   case DWARFSectionKind::DW_SECT_EXT_TYPES: {
-    return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES,
+    return getSliceData(nullptr, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES,
                         DWPOffset);
   }
   case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
-    return getSliceData(DWOEntry, OutData,
+    return getSliceData(CUDWOEntry, OutData,
                         DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
   }
   case DWARFSectionKind::DW_SECT_ABBREV: {
@@ -1220,7 +1241,7 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage,
                      OutputBuffer->size());
   }
   case DWARFSectionKind::DW_SECT_LINE: {
-    return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE,
+    return getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE,
                         DWPOffset);
   }
   case DWARFSectionKind::DW_SECT_RNGLISTS: {
@@ -1233,6 +1254,87 @@ updateDebugData(DWARFContext &DWCtx, std::string &Storage,
 
 } // namespace
 
+struct TUContribution {
+  uint64_t Signature{0};
+  uint32_t Length{0};
+};
+using TUContributionVector = std::vector<TUContribution>;
+/// Iterates over all the signatures used in this CU, and
+/// uses TU Index to extract their contributions from the DWP file.
+/// It stores them in DWOTUSection.
+static std::string extractDWOTUFromDWP(
+    const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU,
+    const DWARFUnitIndex &TUIndex, StringRef Contents,
+    TUContributionVector &TUContributionsToCU, uint64_t DWOId) {
+  std::string DWOTUSection;
+  using TUEntry =
+      std::pair<uint64_t, const DWARFUnitIndex::Entry::SectionContribution *>;
+  std::vector<TUEntry> TUContributions;
+  for (const uint64_t TUSignature : TypeSignaturesPerCU.at(DWOId)) {
+    const DWARFUnitIndex::Entry *TUDWOEntry = TUIndex.getFromHash(TUSignature);
+    const DWARFUnitIndex::Entry::SectionContribution *C =
+        TUDWOEntry->getContribution(DW_SECT_EXT_TYPES);
+    TUContributions.emplace_back(TUSignature, C);
+  }
+
+  // Sorting so it's easy to compare output.
+  // They should be sharing the same Abbrev.
+  std::sort(TUContributions.begin(), TUContributions.end(),
+            [](const TUEntry &V1, const TUEntry &V2) -> bool {
+              return V1.second->Offset < V2.second->Offset;
+            });
+
+  for (auto &PairEntry : TUContributions) {
+    const DWARFUnitIndex::Entry::SectionContribution *C = PairEntry.second;
+    const uint64_t TUSignature = PairEntry.first;
+    DWOTUSection.append(Contents.slice(C->Offset, C->Offset + C->Length).str());
+    TUContributionsToCU.push_back({TUSignature, C->Length});
+  }
+  return DWOTUSection;
+}
+
+static void extractDWOTUFromDWO(StringRef Contents,
+                                TUContributionVector &TUContributionsToCU) {
+  uint64_t Offset = 0;
+  DataExtractor Data(Contents, true, 0);
+  while (Data.isValidOffset(Offset)) {
+    auto PrevOffset = Offset;
+    // Length of the unit, including the 4 byte length field.
+    const uint32_t Length = Data.getU32(&Offset) + 4;
+
+    Data.getU16(&Offset); // Version
+    Data.getU32(&Offset); // Abbrev offset
+    Data.getU8(&Offset);  // Address size
+    const auto TUSignature = Data.getU64(&Offset);
+    Offset = PrevOffset + Length;
+    TUContributionsToCU.push_back({TUSignature, Length});
+  }
+}
+
+static void extractTypesFromDWPDWARF5(
+    const MCObjectFileInfo &MCOFI, const DWARFUnitIndex &TUIndex,
+    const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU,
+    MCStreamer &Streamer, StringRef Contents, uint64_t DWOId) {
+  std::vector<const DWARFUnitIndex::Entry::SectionContribution *>
+      TUContributions;
+  for (const uint64_t Val : TypeSignaturesPerCU.at(DWOId)) {
+    const DWARFUnitIndex::Entry *TUE = TUIndex.getFromHash(Val);
+    const DWARFUnitIndex::Entry::SectionContribution *C =
+        TUE->getContribution(DWARFSectionKind::DW_SECT_INFO);
+    TUContributions.push_back(C);
+  }
+  // Sorting so it's easy to compare output.
+  // They should be sharing the same Abbrev.
+  std::sort(TUContributions.begin(), TUContributions.end(),
+            [](const DWARFUnitIndex::Entry::SectionContribution *V1,
+               const DWARFUnitIndex::Entry::SectionContribution *V2) -> bool {
+              return V1->Offset < V2->Offset;
+            });
+  Streamer.SwitchSection(MCOFI.getDwarfInfoDWOSection());
+  for (const auto *C : TUContributions)
+    Streamer.emitBytes(Contents.slice(C->Offset, C->Offset + C->Length));
+}
+
 void DWARFRewriter::writeDWP(
     std::unordered_map<uint64_t, std::string> &DWOIdToName) {
   SmallString<0> OutputNameStr;
@@ -1270,14 +1372,18 @@ void DWARFRewriter::writeDWP(
   std::deque<SmallString<32>> UncompressedSections;
   DWPStringPool Strings(*Streamer, StrSection);
   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
-  constexpr uint32_t IndexVersion = 2;
+  MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
+  uint16_t Version = 0;
+  uint32_t IndexVersion = 2;
 
   // Setup DWP code once.
   DWARFContext *DWOCtx = BC.getDWOContext();
   const DWARFUnitIndex *CUIndex = nullptr;
+  const DWARFUnitIndex *TUIndex = nullptr;
   bool IsDWP = false;
   if (DWOCtx) {
     CUIndex = &DWOCtx->getCUIndex();
+    TUIndex = &DWOCtx->getTUIndex();
     IsDWP = !CUIndex->getRows().empty();
   }
 
@@ -1291,7 +1397,14 @@ void DWARFRewriter::writeDWP(
     if (!DWOCU)
       continue;
 
-    assert(CU->getVersion() <= 4 && "For DWP output only DWARF4 is supported");
+    if (Version == 0) {
+      Version = CU->getVersion();
+      IndexVersion = Version < 5 ? 2 : 5;
+    } else if (Version != CU->getVersion()) {
+      errs() << "BOLT-ERROR: Incompatible DWARF compile unit versions.\n";
+      exit(1);
+    }
+
     UnitIndexEntry CurEntry = {};
     CurEntry.DWOName =
         dwarf::toString(CU->getUnitDIE().find(
@@ -1308,9 +1421,9 @@ void DWARFRewriter::writeDWP(
     // i.e. offset and length, of each compile/type unit to a section.
     std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
 
-    const DWARFUnitIndex::Entry *DWOEntry = nullptr;
+    const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
     if (IsDWP)
-      DWOEntry = CUIndex->getFromHash(*DWOId);
+      CUDWOEntry = CUIndex->getFromHash(*DWOId);
 
     bool StrSectionWrittenOut = false;
     const object::ObjectFile *DWOFile =
@@ -1322,27 +1435,46 @@ void DWARFRewriter::writeDWP(
              "No RangeListsWriter for DWO ID.");
       RangeListssWriter = RangeListsWritersByCU[*DWOId].get();
     }
+    std::string DWOTUSection;
+    TUContributionVector TUContributionsToCU;
     for (const SectionRef &Section : DWOFile->sections()) {
+      std::string DWOTUSection;
       std::string Storage = "";
       std::unique_ptr<DebugBufferVector> OutputData;
       StringRef SectionName = getSectionName(Section);
-      Expected<StringRef> Contents = Section.getContents();
-      assert(Contents && "Invalid contents.");
-      Optional<StringRef> TOutData =
-          updateDebugData((*DWOCU)->getContext(), Storage, SectionName,
-                          *Contents, KnownSections, *Streamer, *this, DWOEntry,
-                          *DWOId, OutputData, RangeListssWriter);
+      Expected<StringRef> ContentsExp = Section.getContents();
+      assert(ContentsExp && "Invalid contents.");
+      StringRef Contents = *ContentsExp;
+      const bool IsTypesDWO = SectionName == "debug_types.dwo";
+      if (IsDWP && IsTypesDWO) {
+        assert(TUIndex &&
+               "DWP Input with .debug_types.dwo section with TU Index.");
+        DWOTUSection =
+            extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents,
+                                TUContributionsToCU, *DWOId);
+        Contents = DWOTUSection;
+      } else if (IsTypesDWO) {
+        extractDWOTUFromDWO(Contents, TUContributionsToCU);
+      }
+
+      Optional<StringRef> TOutData = updateDebugData(
+          (*DWOCU)->getContext(), Storage, SectionName, Contents, KnownSections,
+          *Streamer, *this, CUDWOEntry, *DWOId, OutputData, RangeListssWriter);
       if (!TOutData)
         continue;
 
       StringRef OutData = *TOutData;
-      StringRef Name = getSectionName(Section);
-      if (Name.equals("debug_str.dwo")) {
+      if (IsTypesDWO) {
+        Streamer->emitBytes(OutData);
+        continue;
+      }
+
+      if (SectionName.equals("debug_str.dwo")) {
         CurStrSection = OutData;
       } else {
         // Since handleDebugDataPatching returned true, we already know this is
         // a known section.
-        auto SectionIter = KnownSections.find(Name);
+        auto SectionIter = KnownSections.find(SectionName);
         if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
           CurStrOffsetSection = OutData;
         else
@@ -1372,11 +1504,38 @@ void DWARFRewriter::writeDWP(
       errs() << "BOLT-ERROR: " << toString(std::move(Err)) << "\n";
       return;
     }
+
+    // Handling TU
+    if (!TUContributionsToCU.empty()) {
+      const unsigned Index =
+          getContributionIndex(DW_SECT_EXT_TYPES, IndexVersion);
+      for (const TUContribution &TUC : TUContributionsToCU) {
+        UnitIndexEntry TUEntry = CurEntry;
+        TUEntry.Contributions[0] = {};
+        TUEntry.Contributions[Index].Offset = ContributionOffsets[Index];
+        TUEntry.Contributions[Index].Length = TUC.Length;
+        ContributionOffsets[Index] += TUEntry.Contributions[Index].Length;
+        TypeIndexEntries.insert(std::make_pair(TUC.Signature, TUEntry));
+      }
+    }
   }
 
-  // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
-  // section does not exist, so no need to do anything about this.
-  ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
+  if (Version < 5) {
+    // Lie about there being no info contributions so the TU index only includes
+    // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
+    // contribution to the info section, so we do not want to lie about it.
+    ContributionOffsets[0] = 0;
+  }
+  writeIndex(*Streamer.get(), MCOFI.getDwarfTUIndexSection(),
+             ContributionOffsets, TypeIndexEntries, IndexVersion);
+
+  if (Version < 5) {
+    // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
+    // section does not exist, so no need to do anything about this.
+    ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
+    // Unlie about the info contribution
+    ContributionOffsets[0] = 1;
+  }
   writeIndex(*Streamer.get(), MCOFI.getDwarfCUIndexSection(),
              ContributionOffsets, IndexEntries, IndexVersion);
 
@@ -1389,9 +1548,11 @@ void DWARFRewriter::writeDWOFiles(
   // Setup DWP code once.
   DWARFContext *DWOCtx = BC.getDWOContext();
   const DWARFUnitIndex *CUIndex = nullptr;
+  const DWARFUnitIndex *TUIndex = nullptr;
   bool IsDWP = false;
   if (DWOCtx) {
     CUIndex = &DWOCtx->getCUIndex();
+    TUIndex = &DWOCtx->getTUIndex();
     IsDWP = !CUIndex->getRows().empty();
   }
 
@@ -1415,16 +1576,16 @@ void DWARFRewriter::writeDWOFiles(
     std::unique_ptr<ToolOutputFile> TempOut =
         std::make_unique<ToolOutputFile>(FullPath, EC, sys::fs::OF_None);
 
-    const DWARFUnitIndex::Entry *DWOEntry = nullptr;
+    const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
     if (IsDWP)
-      DWOEntry = CUIndex->getFromHash(*DWOId);
+      CUDWOEntry = CUIndex->getFromHash(*DWOId);
 
     const object::ObjectFile *File =
         (*DWOCU)->getContext().getDWARFObj().getFile();
     std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
     std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
-    StringMap<KnownSectionsEntry> KnownSections =
-        createKnownSectionsMap(*Streamer->getContext().getObjectFileInfo());
+    const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
+    StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
 
     DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
     if (CU->getVersion() == 5) {
@@ -1439,23 +1600,42 @@ void DWARFRewriter::writeDWOFiles(
         std::unique_ptr<DebugBufferVector> OutputData;
         if (Optional<StringRef> OutData = updateDebugData(
                 (*DWOCU)->getContext(), Storage, "debug_rnglists.dwo", "",
-                KnownSections, *Streamer, *this, DWOEntry, *DWOId, OutputData,
+                KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData,
                 RangeListssWriter))
           Streamer->emitBytes(*OutData);
       }
     }
+
+    TUContributionVector TUContributionsToCU;
     for (const SectionRef &Section : File->sections()) {
       std::string Storage = "";
+      std::string DWOTUSection;
       std::unique_ptr<DebugBufferVector> OutputData;
       StringRef SectionName = getSectionName(Section);
       if (SectionName == "debug_rnglists.dwo")
         continue;
-      Expected<StringRef> Contents = Section.getContents();
-      assert(Contents && "Invalid contents.");
-      if (Optional<StringRef> OutData =
-              updateDebugData((*DWOCU)->getContext(), Storage, SectionName,
-                              *Contents, KnownSections, *Streamer, *this,
-                              DWOEntry, *DWOId, OutputData, RangeListssWriter))
+      Expected<StringRef> ContentsExp = Section.getContents();
+      assert(ContentsExp && "Invalid contents.");
+      StringRef Contents = *ContentsExp;
+      if (IsDWP && SectionName == "debug_types.dwo") {
+        assert(TUIndex &&
+               "DWP Input with .debug_types.dwo section with TU Index.");
+        DWOTUSection =
+            extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents,
+                                TUContributionsToCU, *DWOId);
+        Contents = DWOTUSection;
+      } else if (IsDWP && CU->getVersion() >= 5 &&
+                 SectionName == "debug_info.dwo") {
+        assert(TUIndex &&
+               "DWP Input with .debug_types.dwo section with TU Index.");
+        extractTypesFromDWPDWARF5(MCOFI, *TUIndex, TypeSignaturesPerCU,
+                                  *Streamer, Contents, *DWOId);
+      }
+
+      if (Optional<StringRef> OutData = updateDebugData(
+              (*DWOCU)->getContext(), Storage, SectionName, Contents,
+              KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData,
+              RangeListssWriter))
         Streamer->emitBytes(*OutData);
     }
     Streamer->Finish();
index 298303e..2ac5b47 100644 (file)
@@ -40,6 +40,7 @@ list(APPEND BOLT_TEST_DEPS
   llvm-boltdiff
   llvm-bolt-heatmap
   llvm-dwarfdump
+  llvm-dwp
   llvm-mc
   llvm-nm
   llvm-objdump
diff --git a/bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s b/bolt/test/X86/Inputs/dwarf4-ftypes-split-dwarf.s
new file mode 100644 (file)
index 0000000..354f6ee
--- /dev/null
@@ -0,0 +1,546 @@
+# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-4 -fdebug-types-section
+# struct Foo {
+#   char *c1;
+#   char *c2;
+#   char *c3;
+# };
+#
+# struct Foo2 {
+#   char *c1;
+#   char *c2;
+# };
+#
+# int main(int argc, char *argv[]) {
+#   Foo f;
+#   f.c1 = argv[argc];
+#   f.c2 = argv[argc + 1];
+#   f.c3 = argv[argc + 2];
+#   Foo2 f2;
+#   f.c1 = argv[argc + 3];
+#   f.c2 = argv[argc + 4];
+#   return 0;
+# }
+
+       .text
+       .file   "main.cpp"
+       .globl  main                            # -- Begin function main
+       .p2align        4, 0x90
+       .type   main,@function
+main:                                   # @main
+.Lfunc_begin0:
+       .file   1 "." "main.cpp"
+       .loc    1 12 0                          # main.cpp:12:0
+       .cfi_startproc
+# %bb.0:                                # %entry
+       pushq   %rbp
+       .cfi_def_cfa_offset 16
+       .cfi_offset %rbp, -16
+       movq    %rsp, %rbp
+       .cfi_def_cfa_register %rbp
+       movl    $0, -4(%rbp)
+       movl    %edi, -8(%rbp)
+       movq    %rsi, -16(%rbp)
+.Ltmp0:
+       .loc    1 14 10 prologue_end            # main.cpp:14:10
+       movq    -16(%rbp), %rax
+       movslq  -8(%rbp), %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    1 14 8 is_stmt 0                # main.cpp:14:8
+       movq    %rax, -40(%rbp)
+       .loc    1 15 10 is_stmt 1               # main.cpp:15:10
+       movq    -16(%rbp), %rax
+       .loc    1 15 15 is_stmt 0               # main.cpp:15:15
+       movl    -8(%rbp), %ecx
+       .loc    1 15 20                         # main.cpp:15:20
+       addl    $1, %ecx
+       .loc    1 15 10                         # main.cpp:15:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    1 15 8                          # main.cpp:15:8
+       movq    %rax, -32(%rbp)
+       .loc    1 16 10 is_stmt 1               # main.cpp:16:10
+       movq    -16(%rbp), %rax
+       .loc    1 16 15 is_stmt 0               # main.cpp:16:15
+       movl    -8(%rbp), %ecx
+       .loc    1 16 20                         # main.cpp:16:20
+       addl    $2, %ecx
+       .loc    1 16 10                         # main.cpp:16:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    1 16 8                          # main.cpp:16:8
+       movq    %rax, -24(%rbp)
+       .loc    1 18 10 is_stmt 1               # main.cpp:18:10
+       movq    -16(%rbp), %rax
+       .loc    1 18 15 is_stmt 0               # main.cpp:18:15
+       movl    -8(%rbp), %ecx
+       .loc    1 18 20                         # main.cpp:18:20
+       addl    $3, %ecx
+       .loc    1 18 10                         # main.cpp:18:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    1 18 8                          # main.cpp:18:8
+       movq    %rax, -40(%rbp)
+       .loc    1 19 10 is_stmt 1               # main.cpp:19:10
+       movq    -16(%rbp), %rax
+       .loc    1 19 15 is_stmt 0               # main.cpp:19:15
+       movl    -8(%rbp), %ecx
+       .loc    1 19 20                         # main.cpp:19:20
+       addl    $4, %ecx
+       .loc    1 19 10                         # main.cpp:19:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    1 19 8                          # main.cpp:19:8
+       movq    %rax, -32(%rbp)
+       .loc    1 20 3 is_stmt 1                # main.cpp:20:3
+       xorl    %eax, %eax
+       popq    %rbp
+       .cfi_def_cfa %rsp, 8
+       retq
+.Ltmp1:
+.Lfunc_end0:
+       .size   main, .Lfunc_end0-main
+       .cfi_endproc
+                                        # -- End function
+       .section        .debug_types.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+       .short  4                               # DWARF version number
+       .long   0                               # Offset Into Abbrev. Section
+       .byte   8                               # Address Size (in bytes)
+       .quad   7448148824980338162             # Type Signature
+       .long   30                              # Type DIE Offset
+       .byte   1                               # Abbrev [1] 0x17:0x33 DW_TAG_type_unit
+       .short  33                              # DW_AT_language
+       .long   0                               # DW_AT_stmt_list
+       .byte   2                               # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type
+       .byte   5                               # DW_AT_calling_convention
+       .byte   9                               # DW_AT_name
+       .byte   24                              # DW_AT_byte_size
+       .byte   1                               # DW_AT_decl_file
+       .byte   1                               # DW_AT_decl_line
+       .byte   3                               # Abbrev [3] 0x24:0x9 DW_TAG_member
+       .byte   6                               # DW_AT_name
+       .long   64                              # DW_AT_type
+       .byte   1                               # DW_AT_decl_file
+       .byte   2                               # DW_AT_decl_line
+       .byte   0                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x2d:0x9 DW_TAG_member
+       .byte   7                               # DW_AT_name
+       .long   64                              # DW_AT_type
+       .byte   1                               # DW_AT_decl_file
+       .byte   3                               # DW_AT_decl_line
+       .byte   8                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x36:0x9 DW_TAG_member
+       .byte   8                               # DW_AT_name
+       .long   64                              # DW_AT_type
+       .byte   1                               # DW_AT_decl_file
+       .byte   4                               # DW_AT_decl_line
+       .byte   16                              # DW_AT_data_member_location
+       .byte   0                               # End Of Children Mark
+       .byte   4                               # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type
+       .long   69                              # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x45:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end0:
+       .long   .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+       .short  4                               # DWARF version number
+       .long   0                               # Offset Into Abbrev. Section
+       .byte   8                               # Address Size (in bytes)
+       .quad   5322170643381124694             # Type Signature
+       .long   30                              # Type DIE Offset
+       .byte   1                               # Abbrev [1] 0x17:0x2a DW_TAG_type_unit
+       .short  33                              # DW_AT_language
+       .long   0                               # DW_AT_stmt_list
+       .byte   2                               # Abbrev [2] 0x1e:0x19 DW_TAG_structure_type
+       .byte   5                               # DW_AT_calling_convention
+       .byte   11                              # DW_AT_name
+       .byte   16                              # DW_AT_byte_size
+       .byte   1                               # DW_AT_decl_file
+       .byte   7                               # DW_AT_decl_line
+       .byte   3                               # Abbrev [3] 0x24:0x9 DW_TAG_member
+       .byte   6                               # DW_AT_name
+       .long   55                              # DW_AT_type
+       .byte   1                               # DW_AT_decl_file
+       .byte   8                               # DW_AT_decl_line
+       .byte   0                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x2d:0x9 DW_TAG_member
+       .byte   7                               # DW_AT_name
+       .long   55                              # DW_AT_type
+       .byte   1                               # DW_AT_decl_file
+       .byte   9                               # DW_AT_decl_line
+       .byte   8                               # DW_AT_data_member_location
+       .byte   0                               # End Of Children Mark
+       .byte   4                               # Abbrev [4] 0x37:0x5 DW_TAG_pointer_type
+       .long   60                              # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x3c:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end1:
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   17                              # DW_TAG_compile_unit
+       .byte   0                               # DW_CHILDREN_no
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   27                              # DW_AT_comp_dir
+       .byte   14                              # DW_FORM_strp
+       .ascii  "\264B"                         # DW_AT_GNU_pubnames
+       .byte   25                              # DW_FORM_flag_present
+       .ascii  "\260B"                         # DW_AT_GNU_dwo_name
+       .byte   14                              # DW_FORM_strp
+       .ascii  "\261B"                         # DW_AT_GNU_dwo_id
+       .byte   7                               # DW_FORM_data8
+       .byte   17                              # DW_AT_low_pc
+       .byte   1                               # DW_FORM_addr
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .ascii  "\263B"                         # DW_AT_GNU_addr_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  4                               # DWARF version number
+       .long   .debug_abbrev                   # Offset Into Abbrev. Section
+       .byte   8                               # Address Size (in bytes)
+       .byte   1                               # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit
+       .long   .Lline_table_start0             # DW_AT_stmt_list
+       .long   .Lskel_string0                  # DW_AT_comp_dir
+                                        # DW_AT_GNU_pubnames
+       .long   .Lskel_string1                  # DW_AT_GNU_dwo_name
+       .quad   4780348136649610820             # DW_AT_GNU_dwo_id
+       .quad   .Lfunc_begin0                   # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .long   .Laddr_table_base0              # DW_AT_GNU_addr_base
+.Ldebug_info_end0:
+       .section        .debug_str,"MS",@progbits,1
+.Lskel_string0:
+       .asciz  "." # string offset=0
+.Lskel_string1:
+       .asciz  "main.dwo"                      # string offset=38
+       .section        .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+       .asciz  "main"                          # string offset=0
+.Linfo_string1:
+       .asciz  "int"                           # string offset=5
+.Linfo_string2:
+       .asciz  "argc"                          # string offset=9
+.Linfo_string3:
+       .asciz  "argv"                          # string offset=14
+.Linfo_string4:
+       .asciz  "char"                          # string offset=19
+.Linfo_string5:
+       .asciz  "f"                             # string offset=24
+.Linfo_string6:
+       .asciz  "c1"                            # string offset=26
+.Linfo_string7:
+       .asciz  "c2"                            # string offset=29
+.Linfo_string8:
+       .asciz  "c3"                            # string offset=32
+.Linfo_string9:
+       .asciz  "Foo"                           # string offset=35
+.Linfo_string10:
+       .asciz  "f2"                            # string offset=39
+.Linfo_string11:
+       .asciz  "Foo2"                          # string offset=42
+.Linfo_string12:
+       .asciz  "clang version 15.0.0"                  # string offset=47
+.Linfo_string13:
+       .asciz  "main.cpp"                      # string offset=68
+.Linfo_string14:
+       .asciz  "main.dwo"                      # string offset=77
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   0
+       .long   5
+       .long   9
+       .long   14
+       .long   19
+       .long   24
+       .long   26
+       .long   29
+       .long   32
+       .long   35
+       .long   39
+       .long   42
+       .long   47
+       .long   68
+       .long   77
+       .section        .debug_info.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
+.Ldebug_info_dwo_start2:
+       .short  4                               # DWARF version number
+       .long   0                               # Offset Into Abbrev. Section
+       .byte   8                               # Address Size (in bytes)
+       .byte   6                               # Abbrev [6] 0xb:0x6f DW_TAG_compile_unit
+       .byte   12                              # DW_AT_producer
+       .short  33                              # DW_AT_language
+       .byte   13                              # DW_AT_name
+       .byte   14                              # DW_AT_GNU_dwo_name
+       .quad   4780348136649610820             # DW_AT_GNU_dwo_id
+       .byte   7                               # Abbrev [7] 0x19:0x3c DW_TAG_subprogram
+       .byte   0                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .byte   1                               # DW_AT_frame_base
+       .byte   86
+       .byte   0                               # DW_AT_name
+       .byte   1                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   85                              # DW_AT_type
+                                        # DW_AT_external
+       .byte   8                               # Abbrev [8] 0x28:0xb DW_TAG_formal_parameter
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   120
+       .byte   2                               # DW_AT_name
+       .byte   1                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   85                              # DW_AT_type
+       .byte   8                               # Abbrev [8] 0x33:0xb DW_TAG_formal_parameter
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   112
+       .byte   3                               # DW_AT_name
+       .byte   1                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   89                              # DW_AT_type
+       .byte   9                               # Abbrev [9] 0x3e:0xb DW_TAG_variable
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   88
+       .byte   5                               # DW_AT_name
+       .byte   1                               # DW_AT_decl_file
+       .byte   13                              # DW_AT_decl_line
+       .long   103                             # DW_AT_type
+       .byte   9                               # Abbrev [9] 0x49:0xb DW_TAG_variable
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   72
+       .byte   10                              # DW_AT_name
+       .byte   1                               # DW_AT_decl_file
+       .byte   17                              # DW_AT_decl_line
+       .long   112                             # DW_AT_type
+       .byte   0                               # End Of Children Mark
+       .byte   5                               # Abbrev [5] 0x55:0x4 DW_TAG_base_type
+       .byte   1                               # DW_AT_name
+       .byte   5                               # DW_AT_encoding
+       .byte   4                               # DW_AT_byte_size
+       .byte   4                               # Abbrev [4] 0x59:0x5 DW_TAG_pointer_type
+       .long   94                              # DW_AT_type
+       .byte   4                               # Abbrev [4] 0x5e:0x5 DW_TAG_pointer_type
+       .long   99                              # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x63:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   10                              # Abbrev [10] 0x67:0x9 DW_TAG_structure_type
+                                        # DW_AT_declaration
+       .quad   7448148824980338162             # DW_AT_signature
+       .byte   10                              # Abbrev [10] 0x70:0x9 DW_TAG_structure_type
+                                        # DW_AT_declaration
+       .quad   5322170643381124694             # DW_AT_signature
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end2:
+       .section        .debug_abbrev.dwo,"e",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   65                              # DW_TAG_type_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   2                               # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   54                              # DW_AT_calling_convention
+       .byte   11                              # DW_FORM_data1
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   11                              # DW_AT_byte_size
+       .byte   11                              # DW_FORM_data1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   3                               # Abbreviation Code
+       .byte   13                              # DW_TAG_member
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   56                              # DW_AT_data_member_location
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   4                               # Abbreviation Code
+       .byte   15                              # DW_TAG_pointer_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   5                               # Abbreviation Code
+       .byte   36                              # DW_TAG_base_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   62                              # DW_AT_encoding
+       .byte   11                              # DW_FORM_data1
+       .byte   11                              # DW_AT_byte_size
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   6                               # Abbreviation Code
+       .byte   17                              # DW_TAG_compile_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   37                              # DW_AT_producer
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .ascii  "\260B"                         # DW_AT_GNU_dwo_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .ascii  "\261B"                         # DW_AT_GNU_dwo_id
+       .byte   7                               # DW_FORM_data8
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   7                               # Abbreviation Code
+       .byte   46                              # DW_TAG_subprogram
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   17                              # DW_AT_low_pc
+       .ascii  "\201>"                         # DW_FORM_GNU_addr_index
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   64                              # DW_AT_frame_base
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   8                               # Abbreviation Code
+       .byte   5                               # DW_TAG_formal_parameter
+       .byte   0                               # DW_CHILDREN_no
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   9                               # Abbreviation Code
+       .byte   52                              # DW_TAG_variable
+       .byte   0                               # DW_CHILDREN_no
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .ascii  "\202>"                         # DW_FORM_GNU_str_index
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   10                              # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   60                              # DW_AT_declaration
+       .byte   25                              # DW_FORM_flag_present
+       .byte   105                             # DW_AT_signature
+       .byte   32                              # DW_FORM_ref_sig8
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_line.dwo,"e",@progbits
+.Ltmp2:
+       .long   .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+       .short  4
+       .long   .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+       .byte   1
+       .byte   1
+       .byte   1
+       .byte   -5
+       .byte   14
+       .byte   1
+       .byte   0
+       .ascii  "main.cpp"
+       .byte   0
+       .byte   0
+       .byte   0
+       .byte   0
+       .byte   0
+.Lprologue_end0:
+.Ldebug_line_end0:
+       .section        .debug_addr,"",@progbits
+.Laddr_table_base0:
+       .quad   .Lfunc_begin0
+       .section        .debug_gnu_pubnames,"",@progbits
+       .long   .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info
+.LpubNames_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   48                              # Compilation Unit Length
+       .long   25                              # DIE offset
+       .byte   48                              # Attributes: FUNCTION, EXTERNAL
+       .asciz  "main"                          # External Name
+       .long   0                               # End Mark
+.LpubNames_end0:
+       .section        .debug_gnu_pubtypes,"",@progbits
+       .long   .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info
+.LpubTypes_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   48                              # Compilation Unit Length
+       .long   103                             # DIE offset
+       .byte   16                              # Attributes: TYPE, EXTERNAL
+       .asciz  "Foo"                           # External Name
+       .long   112                             # DIE offset
+       .byte   16                              # Attributes: TYPE, EXTERNAL
+       .asciz  "Foo2"                          # External Name
+       .long   85                              # DIE offset
+       .byte   144                             # Attributes: TYPE, STATIC
+       .asciz  "int"                           # External Name
+       .long   99                              # DIE offset
+       .byte   144                             # Attributes: TYPE, STATIC
+       .asciz  "char"                          # External Name
+       .long   0                               # End Mark
+.LpubTypes_end0:
+       .ident  "clang version 15.0.0"
+       .section        ".note.GNU-stack","",@progbits
+       .addrsig
+       .section        .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s b/bolt/test/X86/Inputs/dwarf5-ftypes-split-dwarf.s
new file mode 100644 (file)
index 0000000..08c26ae
--- /dev/null
@@ -0,0 +1,583 @@
+# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-5 -fdebug-types-section -S
+# struct Foo {
+#   char *c1;
+#   char *c2;
+#   char *c3;
+# };
+#
+# struct Foo2 {
+#   char *c1;
+#   char *c2;
+# };
+#
+# int main(int argc, char *argv[]) {
+#   Foo f;
+#   f.c1 = argv[argc];
+#   f.c2 = argv[argc + 1];
+#   f.c3 = argv[argc + 2];
+#   Foo2 f2;
+#   f.c1 = argv[argc + 3];
+#   f.c2 = argv[argc + 4];
+#   return 0;
+# }
+
+       .text
+       .file   "main.cpp"
+       .globl  main                            # -- Begin function main
+       .p2align        4, 0x90
+       .type   main,@function
+main:                                   # @main
+.Lfunc_begin0:
+       .file   0 "." "main.cpp" md5 0xa832f464c853be0f9c52da29cd913807
+       .loc    0 12 0                          # main.cpp:12:0
+       .cfi_startproc
+# %bb.0:                                # %entry
+       pushq   %rbp
+       .cfi_def_cfa_offset 16
+       .cfi_offset %rbp, -16
+       movq    %rsp, %rbp
+       .cfi_def_cfa_register %rbp
+       movl    $0, -4(%rbp)
+       movl    %edi, -8(%rbp)
+       movq    %rsi, -16(%rbp)
+.Ltmp0:
+       .loc    0 14 10 prologue_end            # main.cpp:14:10
+       movq    -16(%rbp), %rax
+       movslq  -8(%rbp), %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    0 14 8 is_stmt 0                # main.cpp:14:8
+       movq    %rax, -40(%rbp)
+       .loc    0 15 10 is_stmt 1               # main.cpp:15:10
+       movq    -16(%rbp), %rax
+       .loc    0 15 15 is_stmt 0               # main.cpp:15:15
+       movl    -8(%rbp), %ecx
+       .loc    0 15 20                         # main.cpp:15:20
+       addl    $1, %ecx
+       .loc    0 15 10                         # main.cpp:15:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    0 15 8                          # main.cpp:15:8
+       movq    %rax, -32(%rbp)
+       .loc    0 16 10 is_stmt 1               # main.cpp:16:10
+       movq    -16(%rbp), %rax
+       .loc    0 16 15 is_stmt 0               # main.cpp:16:15
+       movl    -8(%rbp), %ecx
+       .loc    0 16 20                         # main.cpp:16:20
+       addl    $2, %ecx
+       .loc    0 16 10                         # main.cpp:16:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    0 16 8                          # main.cpp:16:8
+       movq    %rax, -24(%rbp)
+       .loc    0 18 10 is_stmt 1               # main.cpp:18:10
+       movq    -16(%rbp), %rax
+       .loc    0 18 15 is_stmt 0               # main.cpp:18:15
+       movl    -8(%rbp), %ecx
+       .loc    0 18 20                         # main.cpp:18:20
+       addl    $3, %ecx
+       .loc    0 18 10                         # main.cpp:18:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    0 18 8                          # main.cpp:18:8
+       movq    %rax, -40(%rbp)
+       .loc    0 19 10 is_stmt 1               # main.cpp:19:10
+       movq    -16(%rbp), %rax
+       .loc    0 19 15 is_stmt 0               # main.cpp:19:15
+       movl    -8(%rbp), %ecx
+       .loc    0 19 20                         # main.cpp:19:20
+       addl    $4, %ecx
+       .loc    0 19 10                         # main.cpp:19:10
+       movslq  %ecx, %rcx
+       movq    (%rax,%rcx,8), %rax
+       .loc    0 19 8                          # main.cpp:19:8
+       movq    %rax, -32(%rbp)
+       .loc    0 20 3 is_stmt 1                # main.cpp:20:3
+       xorl    %eax, %eax
+       popq    %rbp
+       .cfi_def_cfa %rsp, 8
+       retq
+.Ltmp1:
+.Lfunc_end0:
+       .size   main, .Lfunc_end0-main
+       .cfi_endproc
+                                        # -- End function
+       .section        .debug_info.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+       .short  5                               # DWARF version number
+       .byte   6                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   7448148824980338162             # Type Signature
+       .long   31                              # Type DIE Offset
+       .byte   1                               # Abbrev [1] 0x18:0x33 DW_TAG_type_unit
+       .short  33                              # DW_AT_language
+       .long   0                               # DW_AT_stmt_list
+       .byte   2                               # Abbrev [2] 0x1f:0x22 DW_TAG_structure_type
+       .byte   5                               # DW_AT_calling_convention
+       .byte   9                               # DW_AT_name
+       .byte   24                              # DW_AT_byte_size
+       .byte   0                               # DW_AT_decl_file
+       .byte   1                               # DW_AT_decl_line
+       .byte   3                               # Abbrev [3] 0x25:0x9 DW_TAG_member
+       .byte   6                               # DW_AT_name
+       .long   65                              # DW_AT_type
+       .byte   0                               # DW_AT_decl_file
+       .byte   2                               # DW_AT_decl_line
+       .byte   0                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x2e:0x9 DW_TAG_member
+       .byte   7                               # DW_AT_name
+       .long   65                              # DW_AT_type
+       .byte   0                               # DW_AT_decl_file
+       .byte   3                               # DW_AT_decl_line
+       .byte   8                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x37:0x9 DW_TAG_member
+       .byte   8                               # DW_AT_name
+       .long   65                              # DW_AT_type
+       .byte   0                               # DW_AT_decl_file
+       .byte   4                               # DW_AT_decl_line
+       .byte   16                              # DW_AT_data_member_location
+       .byte   0                               # End Of Children Mark
+       .byte   4                               # Abbrev [4] 0x41:0x5 DW_TAG_pointer_type
+       .long   70                              # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x46:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end0:
+       .long   .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+       .short  5                               # DWARF version number
+       .byte   6                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   5322170643381124694             # Type Signature
+       .long   31                              # Type DIE Offset
+       .byte   1                               # Abbrev [1] 0x18:0x2a DW_TAG_type_unit
+       .short  33                              # DW_AT_language
+       .long   0                               # DW_AT_stmt_list
+       .byte   2                               # Abbrev [2] 0x1f:0x19 DW_TAG_structure_type
+       .byte   5                               # DW_AT_calling_convention
+       .byte   11                              # DW_AT_name
+       .byte   16                              # DW_AT_byte_size
+       .byte   0                               # DW_AT_decl_file
+       .byte   7                               # DW_AT_decl_line
+       .byte   3                               # Abbrev [3] 0x25:0x9 DW_TAG_member
+       .byte   6                               # DW_AT_name
+       .long   56                              # DW_AT_type
+       .byte   0                               # DW_AT_decl_file
+       .byte   8                               # DW_AT_decl_line
+       .byte   0                               # DW_AT_data_member_location
+       .byte   3                               # Abbrev [3] 0x2e:0x9 DW_TAG_member
+       .byte   7                               # DW_AT_name
+       .long   56                              # DW_AT_type
+       .byte   0                               # DW_AT_decl_file
+       .byte   9                               # DW_AT_decl_line
+       .byte   8                               # DW_AT_data_member_location
+       .byte   0                               # End Of Children Mark
+       .byte   4                               # Abbrev [4] 0x38:0x5 DW_TAG_pointer_type
+       .long   61                              # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x3d:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end1:
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   74                              # DW_TAG_skeleton_unit
+       .byte   0                               # DW_CHILDREN_no
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   114                             # DW_AT_str_offsets_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   27                              # DW_AT_comp_dir
+       .byte   37                              # DW_FORM_strx1
+       .ascii  "\264B"                         # DW_AT_GNU_pubnames
+       .byte   25                              # DW_FORM_flag_present
+       .byte   118                             # DW_AT_dwo_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   115                             # DW_AT_addr_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  5                               # DWARF version number
+       .byte   4                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   .debug_abbrev                   # Offset Into Abbrev. Section
+       .quad   4780348136649610820
+       .byte   1                               # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+       .long   .Lline_table_start0             # DW_AT_stmt_list
+       .long   .Lstr_offsets_base0             # DW_AT_str_offsets_base
+       .byte   0                               # DW_AT_comp_dir
+                                        # DW_AT_GNU_pubnames
+       .byte   1                               # DW_AT_dwo_name
+       .byte   0                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .long   .Laddr_table_base0              # DW_AT_addr_base
+.Ldebug_info_end0:
+       .section        .debug_str_offsets,"",@progbits
+       .long   12                              # Length of String Offsets Set
+       .short  5
+       .short  0
+.Lstr_offsets_base0:
+       .section        .debug_str,"MS",@progbits,1
+.Lskel_string0:
+       .asciz  "." # string offset=0
+.Lskel_string1:
+       .asciz  "main.dwo"                      # string offset=38
+       .section        .debug_str_offsets,"",@progbits
+       .long   .Lskel_string0
+       .long   .Lskel_string1
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   64                              # Length of String Offsets Set
+       .short  5
+       .short  0
+       .section        .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+       .asciz  "main"                          # string offset=0
+.Linfo_string1:
+       .asciz  "int"                           # string offset=5
+.Linfo_string2:
+       .asciz  "argc"                          # string offset=9
+.Linfo_string3:
+       .asciz  "argv"                          # string offset=14
+.Linfo_string4:
+       .asciz  "char"                          # string offset=19
+.Linfo_string5:
+       .asciz  "f"                             # string offset=24
+.Linfo_string6:
+       .asciz  "c1"                            # string offset=26
+.Linfo_string7:
+       .asciz  "c2"                            # string offset=29
+.Linfo_string8:
+       .asciz  "c3"                            # string offset=32
+.Linfo_string9:
+       .asciz  "Foo"                           # string offset=35
+.Linfo_string10:
+       .asciz  "f2"                            # string offset=39
+.Linfo_string11:
+       .asciz  "Foo2"                          # string offset=42
+.Linfo_string12:
+       .asciz  "clang version 15.0.0"                  # string offset=47
+.Linfo_string13:
+       .asciz  "main.cpp"                      # string offset=68
+.Linfo_string14:
+       .asciz  "main.dwo"                      # string offset=77
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   0
+       .long   5
+       .long   9
+       .long   14
+       .long   19
+       .long   24
+       .long   26
+       .long   29
+       .long   32
+       .long   35
+       .long   39
+       .long   42
+       .long   47
+       .long   68
+       .long   77
+       .section        .debug_info.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
+.Ldebug_info_dwo_start2:
+       .short  5                               # DWARF version number
+       .byte   5                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   4780348136649610820
+       .byte   6                               # Abbrev [6] 0x14:0x67 DW_TAG_compile_unit
+       .byte   12                              # DW_AT_producer
+       .short  33                              # DW_AT_language
+       .byte   13                              # DW_AT_name
+       .byte   14                              # DW_AT_dwo_name
+       .byte   7                               # Abbrev [7] 0x1a:0x3c DW_TAG_subprogram
+       .byte   0                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .byte   1                               # DW_AT_frame_base
+       .byte   86
+       .byte   0                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   86                              # DW_AT_type
+                                        # DW_AT_external
+       .byte   8                               # Abbrev [8] 0x29:0xb DW_TAG_formal_parameter
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   120
+       .byte   2                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   86                              # DW_AT_type
+       .byte   8                               # Abbrev [8] 0x34:0xb DW_TAG_formal_parameter
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   112
+       .byte   3                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   12                              # DW_AT_decl_line
+       .long   90                              # DW_AT_type
+       .byte   9                               # Abbrev [9] 0x3f:0xb DW_TAG_variable
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   88
+       .byte   5                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   13                              # DW_AT_decl_line
+       .long   104                             # DW_AT_type
+       .byte   9                               # Abbrev [9] 0x4a:0xb DW_TAG_variable
+       .byte   2                               # DW_AT_location
+       .byte   145
+       .byte   72
+       .byte   10                              # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   17                              # DW_AT_decl_line
+       .long   113                             # DW_AT_type
+       .byte   0                               # End Of Children Mark
+       .byte   5                               # Abbrev [5] 0x56:0x4 DW_TAG_base_type
+       .byte   1                               # DW_AT_name
+       .byte   5                               # DW_AT_encoding
+       .byte   4                               # DW_AT_byte_size
+       .byte   4                               # Abbrev [4] 0x5a:0x5 DW_TAG_pointer_type
+       .long   95                              # DW_AT_type
+       .byte   4                               # Abbrev [4] 0x5f:0x5 DW_TAG_pointer_type
+       .long   100                             # DW_AT_type
+       .byte   5                               # Abbrev [5] 0x64:0x4 DW_TAG_base_type
+       .byte   4                               # DW_AT_name
+       .byte   6                               # DW_AT_encoding
+       .byte   1                               # DW_AT_byte_size
+       .byte   10                              # Abbrev [10] 0x68:0x9 DW_TAG_structure_type
+                                        # DW_AT_declaration
+       .quad   7448148824980338162             # DW_AT_signature
+       .byte   10                              # Abbrev [10] 0x71:0x9 DW_TAG_structure_type
+                                        # DW_AT_declaration
+       .quad   5322170643381124694             # DW_AT_signature
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end2:
+       .section        .debug_abbrev.dwo,"e",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   65                              # DW_TAG_type_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   2                               # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   54                              # DW_AT_calling_convention
+       .byte   11                              # DW_FORM_data1
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   11                              # DW_AT_byte_size
+       .byte   11                              # DW_FORM_data1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   3                               # Abbreviation Code
+       .byte   13                              # DW_TAG_member
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   56                              # DW_AT_data_member_location
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   4                               # Abbreviation Code
+       .byte   15                              # DW_TAG_pointer_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   5                               # Abbreviation Code
+       .byte   36                              # DW_TAG_base_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   62                              # DW_AT_encoding
+       .byte   11                              # DW_FORM_data1
+       .byte   11                              # DW_AT_byte_size
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   6                               # Abbreviation Code
+       .byte   17                              # DW_TAG_compile_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   37                              # DW_AT_producer
+       .byte   37                              # DW_FORM_strx1
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   118                             # DW_AT_dwo_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   7                               # Abbreviation Code
+       .byte   46                              # DW_TAG_subprogram
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   64                              # DW_AT_frame_base
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   8                               # Abbreviation Code
+       .byte   5                               # DW_TAG_formal_parameter
+       .byte   0                               # DW_CHILDREN_no
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   9                               # Abbreviation Code
+       .byte   52                              # DW_TAG_variable
+       .byte   0                               # DW_CHILDREN_no
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   10                              # Abbreviation Code
+       .byte   19                              # DW_TAG_structure_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   60                              # DW_AT_declaration
+       .byte   25                              # DW_FORM_flag_present
+       .byte   105                             # DW_AT_signature
+       .byte   32                              # DW_FORM_ref_sig8
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_line.dwo,"e",@progbits
+.Ltmp2:
+       .long   .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+       .short  5
+       .byte   8
+       .byte   0
+       .long   .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+       .byte   1
+       .byte   1
+       .byte   1
+       .byte   -5
+       .byte   14
+       .byte   1
+       .byte   1
+       .byte   1
+       .byte   8
+       .byte   1
+       .ascii  "/home/ayermolo/local/tasks/T104766233"
+       .byte   0
+       .byte   3
+       .byte   1
+       .byte   8
+       .byte   2
+       .byte   15
+       .byte   5
+       .byte   30
+       .byte   1
+       .ascii  "main.cpp"
+       .byte   0
+       .byte   0
+       .byte   0xa8, 0x32, 0xf4, 0x64
+       .byte   0xc8, 0x53, 0xbe, 0x0f
+       .byte   0x9c, 0x52, 0xda, 0x29
+       .byte   0xcd, 0x91, 0x38, 0x07
+.Lprologue_end0:
+.Ldebug_line_end0:
+       .section        .debug_addr,"",@progbits
+       .long   .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+       .short  5                               # DWARF version number
+       .byte   8                               # Address size
+       .byte   0                               # Segment selector size
+.Laddr_table_base0:
+       .quad   .Lfunc_begin0
+.Ldebug_addr_end0:
+       .section        .debug_gnu_pubnames,"",@progbits
+       .long   .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info
+.LpubNames_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   40                              # Compilation Unit Length
+       .long   26                              # DIE offset
+       .byte   48                              # Attributes: FUNCTION, EXTERNAL
+       .asciz  "main"                          # External Name
+       .long   0                               # End Mark
+.LpubNames_end0:
+       .section        .debug_gnu_pubtypes,"",@progbits
+       .long   .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info
+.LpubTypes_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   40                              # Compilation Unit Length
+       .long   104                             # DIE offset
+       .byte   16                              # Attributes: TYPE, EXTERNAL
+       .asciz  "Foo"                           # External Name
+       .long   113                             # DIE offset
+       .byte   16                              # Attributes: TYPE, EXTERNAL
+       .asciz  "Foo2"                          # External Name
+       .long   86                              # DIE offset
+       .byte   144                             # Attributes: TYPE, STATIC
+       .asciz  "int"                           # External Name
+       .long   100                             # DIE offset
+       .byte   144                             # Attributes: TYPE, STATIC
+       .asciz  "char"                          # External Name
+       .long   0                               # End Mark
+.LpubTypes_end0:
+       .ident  "clang version 15.0.0"
+       .section        ".note.GNU-stack","",@progbits
+       .addrsig
+       .section        .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test b/bolt/test/X86/dwarf4-ftypes-dwo-input-dwp-output.test
new file mode 100644 (file)
index 0000000..5daae95
--- /dev/null
@@ -0,0 +1,30 @@
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections -write-dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.bolt.dwp | FileCheck -check-prefix=BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-TU-INDEX %s
+
+; Test input into bolt a .dwo file with TU Index.
+; Make sure the output .dwp file has a type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+
+; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; BOLT-DWP-TU-INDEX: Index Signature
+; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
diff --git a/bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwo-output.test
new file mode 100644 (file)
index 0000000..0fa5577
--- /dev/null
@@ -0,0 +1,26 @@
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo.dwo | FileCheck -check-prefix=BOLT %s
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure output in the .dwo files has type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
diff --git a/bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test b/bolt/test/X86/dwarf4-ftypes-dwp-input-dwp-output.test
new file mode 100644 (file)
index 0000000..125cf63
--- /dev/null
@@ -0,0 +1,32 @@
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections -write-dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.bolt.dwp | FileCheck -check-prefix=BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-TU-INDEX %s
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure the output .dwp file has a type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+
+; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; BOLT-DWP-TU-INDEX: Index Signature
+; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
diff --git a/bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test b/bolt/test/X86/dwarf5-ftypes-dwp-input-dwo-output.test
new file mode 100644 (file)
index 0000000..4b928c4
--- /dev/null
@@ -0,0 +1,27 @@
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf5-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT %s
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure output in the .dwo files has type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 5, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_compile_unit
index 78638e3..526458e 100644 (file)
@@ -91,6 +91,7 @@ tools = [
     ToolSubst('link_fdata', command=sys.executable, unresolved='fatal', extra_args=[link_fdata_cmd]),
     ToolSubst('merge-fdata', unresolved='fatal'),
     ToolSubst('llvm-readobj', unresolved='fatal'),
+    ToolSubst('llvm-dwp', unresolved='fatal'),
 ]
 llvm_config.add_tool_substitutions(tools, tool_dirs)