summaryrefslogtreecommitdiffstats
path: root/build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch
diff options
context:
space:
mode:
Diffstat (limited to 'build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch')
-rw-r--r--build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch1323
1 files changed, 1323 insertions, 0 deletions
diff --git a/build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch b/build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch
new file mode 100644
index 0000000000..2f2011859f
--- /dev/null
+++ b/build/build-clang/revert-llvmorg-15-init-17171-g8bb4451a651a.patch
@@ -0,0 +1,1323 @@
+From cb2407418ae7fbd9874a07ba7943acff5257c996 Mon Sep 17 00:00:00 2001
+From: Mike Hommey <mh@glandium.org>
+Date: Thu, 26 Jan 2023 13:35:14 +0900
+Subject: Revert "[Reland][DebugInfo][llvm-dwarfutil] Combine
+ overlapped address ranges."
+
+This reverts commit 8bb4451a651ac00432d04e020d83f43c445aaebb for
+breaking debug line info on mac (bug 1810249).
+---
+ llvm/include/llvm/ADT/AddressRanges.h | 82 +-----
+ llvm/include/llvm/DWARFLinker/DWARFLinker.h | 22 +-
+ .../llvm/DWARFLinker/DWARFLinkerCompileUnit.h | 30 ++-
+ llvm/include/llvm/DWARFLinker/DWARFStreamer.h | 2 +-
+ llvm/lib/DWARFLinker/DWARFLinker.cpp | 73 +++--
+ .../DWARFLinker/DWARFLinkerCompileUnit.cpp | 10 +-
+ llvm/lib/DWARFLinker/DWARFStreamer.cpp | 20 +-
+ llvm/lib/Support/AddressRanges.cpp | 57 ++--
+ .../gc-func-overlapping-address-ranges.test | 254 ------------------
+ .../gc-unit-overlapping-address-ranges.test | 247 -----------------
+ llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 1 +
+ llvm/tools/dsymutil/DwarfLinkerForBinary.h | 4 +-
+ llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp | 22 +-
+ llvm/unittests/Support/AddressRangeTest.cpp | 102 +------
+ 14 files changed, 158 insertions(+), 768 deletions(-)
+ delete mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test
+ delete mode 100644 llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test
+
+diff --git a/llvm/include/llvm/ADT/AddressRanges.h b/llvm/include/llvm/ADT/AddressRanges.h
+index c02844a095d1..1953680d5222 100644
+--- a/llvm/include/llvm/ADT/AddressRanges.h
++++ b/llvm/include/llvm/ADT/AddressRanges.h
+@@ -10,10 +10,9 @@
+ #define LLVM_ADT_ADDRESSRANGES_H
+
+ #include "llvm/ADT/Optional.h"
+-#include "llvm/ADT/STLExtras.h"
+-#include "llvm/ADT/SmallVector.h"
+ #include <cassert>
+ #include <stdint.h>
++#include <vector>
+
+ namespace llvm {
+
+@@ -48,29 +47,20 @@ private:
+ /// The AddressRanges class helps normalize address range collections.
+ /// This class keeps a sorted vector of AddressRange objects and can perform
+ /// insertions and searches efficiently. The address ranges are always sorted
+-/// and never contain any invalid or empty address ranges.
+-/// Intersecting([100,200), [150,300)) and adjacent([100,200), [200,300))
++/// and never contain any invalid or empty address ranges. Intersecting
+ /// address ranges are combined during insertion.
+ class AddressRanges {
+ protected:
+- using Collection = SmallVector<AddressRange>;
++ using Collection = std::vector<AddressRange>;
+ Collection Ranges;
+
+ public:
+ void clear() { Ranges.clear(); }
+ bool empty() const { return Ranges.empty(); }
+- bool contains(uint64_t Addr) const { return find(Addr) != Ranges.end(); }
+- bool contains(AddressRange Range) const {
+- return find(Range) != Ranges.end();
+- }
+- Optional<AddressRange> getRangeThatContains(uint64_t Addr) const {
+- Collection::const_iterator It = find(Addr);
+- if (It == Ranges.end())
+- return None;
+-
+- return *It;
+- }
+- Collection::const_iterator insert(AddressRange Range);
++ bool contains(uint64_t Addr) const;
++ bool contains(AddressRange Range) const;
++ Optional<AddressRange> getRangeThatContains(uint64_t Addr) const;
++ void insert(AddressRange Range);
+ void reserve(size_t Capacity) { Ranges.reserve(Capacity); }
+ size_t size() const { return Ranges.size(); }
+ bool operator==(const AddressRanges &RHS) const {
+@@ -82,64 +72,6 @@ public:
+ }
+ Collection::const_iterator begin() const { return Ranges.begin(); }
+ Collection::const_iterator end() const { return Ranges.end(); }
+-
+-protected:
+- Collection::const_iterator find(uint64_t Addr) const;
+- Collection::const_iterator find(AddressRange Range) const;
+-};
+-
+-/// AddressRangesMap class maps values to the address ranges.
+-/// It keeps address ranges and corresponding values. If ranges
+-/// are combined during insertion, then combined range keeps
+-/// newly inserted value.
+-template <typename T> class AddressRangesMap : protected AddressRanges {
+-public:
+- void clear() {
+- Ranges.clear();
+- Values.clear();
+- }
+- bool empty() const { return AddressRanges::empty(); }
+- bool contains(uint64_t Addr) const { return AddressRanges::contains(Addr); }
+- bool contains(AddressRange Range) const {
+- return AddressRanges::contains(Range);
+- }
+- void insert(AddressRange Range, T Value) {
+- size_t InputSize = Ranges.size();
+- Collection::const_iterator RangesIt = AddressRanges::insert(Range);
+- if (RangesIt == Ranges.end())
+- return;
+-
+- // make Values match to Ranges.
+- size_t Idx = RangesIt - Ranges.begin();
+- typename ValuesCollection::iterator ValuesIt = Values.begin() + Idx;
+- if (InputSize < Ranges.size())
+- Values.insert(ValuesIt, T());
+- else if (InputSize > Ranges.size())
+- Values.erase(ValuesIt, ValuesIt + InputSize - Ranges.size());
+- assert(Ranges.size() == Values.size());
+-
+- // set value to the inserted or combined range.
+- Values[Idx] = Value;
+- }
+- size_t size() const {
+- assert(Ranges.size() == Values.size());
+- return AddressRanges::size();
+- }
+- Optional<std::pair<AddressRange, T>>
+- getRangeValueThatContains(uint64_t Addr) const {
+- Collection::const_iterator It = find(Addr);
+- if (It == Ranges.end())
+- return None;
+-
+- return std::make_pair(*It, Values[It - Ranges.begin()]);
+- }
+- std::pair<AddressRange, T> operator[](size_t Idx) const {
+- return std::make_pair(Ranges[Idx], Values[Idx]);
+- }
+-
+-protected:
+- using ValuesCollection = SmallVector<T>;
+- ValuesCollection Values;
+ };
+
+ } // namespace llvm
+diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+index 4729e5f806d8..32636aa9b359 100644
+--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
++++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+@@ -9,7 +9,6 @@
+ #ifndef LLVM_DWARFLINKER_DWARFLINKER_H
+ #define LLVM_DWARFLINKER_DWARFLINKER_H
+
+-#include "llvm/ADT/AddressRanges.h"
+ #include "llvm/CodeGen/AccelTable.h"
+ #include "llvm/CodeGen/NonRelocatableStringpool.h"
+ #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+@@ -38,6 +37,25 @@ enum class DwarfLinkerAccelTableKind : uint8_t {
+ Pub, ///< .debug_pubnames, .debug_pubtypes
+ };
+
++/// Partial address range. Besides an offset, only the
++/// HighPC is stored. The structure is stored in a map where the LowPC is the
++/// key.
++struct ObjFileAddressRange {
++ /// Function HighPC.
++ uint64_t HighPC;
++ /// Offset to apply to the linked address.
++ /// should be 0 for not-linked object file.
++ int64_t Offset;
++
++ ObjFileAddressRange(uint64_t EndPC, int64_t Offset)
++ : HighPC(EndPC), Offset(Offset) {}
++
++ ObjFileAddressRange() : HighPC(0), Offset(0) {}
++};
++
++/// Map LowPC to ObjFileAddressRange.
++using RangesTy = std::map<uint64_t, ObjFileAddressRange>;
++
+ /// AddressesMap represents information about valid addresses used
+ /// by debug information. Valid addresses are those which points to
+ /// live code sections. i.e. relocations for these addresses point
+@@ -124,7 +142,7 @@ public:
+ /// original \p Entries.
+ virtual void emitRangesEntries(
+ int64_t UnitPcOffset, uint64_t OrigLowPc,
+- Optional<std::pair<AddressRange, int64_t>> FuncRange,
++ const FunctionIntervals::const_iterator &FuncRange,
+ const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
+ unsigned AddressSize) = 0;
+
+diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+index 05e291c05132..930db0913226 100644
+--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
++++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+@@ -9,8 +9,8 @@
+ #ifndef LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
+ #define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
+
+-#include "llvm/ADT/AddressRanges.h"
+ #include "llvm/ADT/DenseMap.h"
++#include "llvm/ADT/IntervalMap.h"
+ #include "llvm/CodeGen/DIE.h"
+ #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+
+@@ -18,9 +18,12 @@ namespace llvm {
+
+ class DeclContext;
+
+-/// Mapped value in the address map is the offset to apply to the
+-/// linked address.
+-using RangesTy = AddressRangesMap<int64_t>;
++template <typename KeyT, typename ValT>
++using HalfOpenIntervalMap =
++ IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
++ IntervalMapHalfOpenInfo<KeyT>>;
++
++using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
+
+ // FIXME: Delete this structure.
+ struct PatchLocation {
+@@ -81,7 +84,8 @@ public:
+
+ CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
+ StringRef ClangModuleName)
+- : OrigUnit(OrigUnit), ID(ID), ClangModuleName(ClangModuleName) {
++ : OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
++ ClangModuleName(ClangModuleName) {
+ Info.resize(OrigUnit.getNumDIEs());
+
+ auto CUDie = OrigUnit.getUnitDIE(false);
+@@ -139,7 +143,7 @@ public:
+ return UnitRangeAttribute;
+ }
+
+- const RangesTy &getFunctionRanges() const { return Ranges; }
++ const FunctionIntervals &getFunctionRanges() const { return Ranges; }
+
+ const std::vector<PatchLocation> &getRangesAttributes() const {
+ return RangeAttributes;
+@@ -178,6 +182,10 @@ public:
+ /// offset \p PCOffset.
+ void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
+
++ /// Check whether specified address range \p LowPC \p HighPC
++ /// overlaps with existing function ranges.
++ bool overlapsWithFunctionRanges(uint64_t LowPC, uint64_t HighPC);
++
+ /// Keep track of a DW_AT_range attribute that we will need to patch up later.
+ void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
+
+@@ -262,10 +270,12 @@ private:
+ std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
+ ForwardDIEReferences;
+
+- /// 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.
+- RangesTy Ranges;
++ FunctionIntervals::Allocator RangeAlloc;
++
++ /// The ranges in that interval 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.
++ FunctionIntervals Ranges;
+
+ /// The DW_AT_low_pc of each DW_TAG_label.
+ SmallDenseMap<uint64_t, uint64_t, 1> Labels;
+diff --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+index 0ccab0efa8f4..003fe548252a 100644
+--- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
++++ b/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+@@ -96,7 +96,7 @@ public:
+ /// original \p Entries.
+ void emitRangesEntries(
+ int64_t UnitPcOffset, uint64_t OrigLowPc,
+- Optional<std::pair<AddressRange, int64_t>> FuncRange,
++ const FunctionIntervals::const_iterator &FuncRange,
+ const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
+ unsigned AddressSize) override;
+
+diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
+index 3e14edb5f730..6e0fe801a630 100644
+--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
++++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
+@@ -504,14 +504,22 @@ unsigned DWARFLinker::shouldKeepSubprogramDIE(
+ &DIE);
+ return Flags;
+ }
+- if (*LowPc > *HighPc) {
+- reportWarning("low_pc greater than high_pc. Range will be discarded.\n",
+- File, &DIE);
++
++ // TODO: Following check is a workaround for overlapping address ranges.
++ // ELF binaries built with LTO might contain overlapping address
++ // ranges. The better fix would be to combine such ranges. Following
++ // is a workaround that should be removed when a good fix is done.
++ if (Unit.overlapsWithFunctionRanges(*LowPc, *HighPc)) {
++ reportWarning(
++ formatv("Overlapping address range [{0:X}, {1:X}]. Range will "
++ "be discarded.\n",
++ *LowPc, *HighPc),
++ File, &DIE);
+ return Flags;
+ }
+
+ // Replace the debug map range with a more accurate one.
+- Ranges.insert({*LowPc, *HighPc}, MyInfo.AddrAdjust);
++ Ranges[*LowPc] = ObjFileAddressRange(*HighPc, MyInfo.AddrAdjust);
+ Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
+ return Flags;
+ }
+@@ -1580,7 +1588,7 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
+ DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
+ OrigDwarf.getDWARFObj().getRangesSection(),
+ OrigDwarf.isLittleEndian(), AddressSize);
+- Optional<std::pair<AddressRange, int64_t>> CurrRange;
++ auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
+ DWARFUnit &OrigUnit = Unit.getOrigUnit();
+ auto OrigUnitDie = OrigUnit.getUnitDIE(false);
+ uint64_t OrigLowPc =
+@@ -1603,11 +1611,12 @@ void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit,
+ if (!Entries.empty()) {
+ const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
+
+- if (!CurrRange ||
+- !CurrRange->first.contains(First.StartAddress + OrigLowPc)) {
+- CurrRange = FunctionRanges.getRangeValueThatContains(
+- First.StartAddress + OrigLowPc);
+- if (!CurrRange) {
++ if (CurrRange == InvalidRange ||
++ First.StartAddress + OrigLowPc < CurrRange.start() ||
++ First.StartAddress + OrigLowPc >= CurrRange.stop()) {
++ CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc);
++ if (CurrRange == InvalidRange ||
++ CurrRange.start() > First.StartAddress + OrigLowPc) {
+ reportWarning("no mapping for range.", File);
+ continue;
+ }
+@@ -1714,7 +1723,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
+ // in NewRows.
+ std::vector<DWARFDebugLine::Row> Seq;
+ const auto &FunctionRanges = Unit.getFunctionRanges();
+- Optional<std::pair<AddressRange, int64_t>> CurrRange;
++ auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
+
+ // FIXME: This logic is meant to generate exactly the same output as
+ // Darwin's classic dsymutil. There is a nicer way to implement this
+@@ -1733,14 +1742,19 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
+ // it is marked as end_sequence in the input (because in that
+ // case, the relocation offset is accurate and that entry won't
+ // serve as the start of another function).
+- if (!CurrRange || !CurrRange->first.contains(Row.Address.Address) ||
+- (Row.Address.Address == CurrRange->first.end() && !Row.EndSequence)) {
++ if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() ||
++ Row.Address.Address > CurrRange.stop() ||
++ (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) {
+ // We just stepped out of a known range. Insert a end_sequence
+ // corresponding to the end of the range.
+- uint64_t StopAddress =
+- CurrRange ? CurrRange->first.end() + CurrRange->second : -1ULL;
+- CurrRange = FunctionRanges.getRangeValueThatContains(Row.Address.Address);
+- if (!CurrRange) {
++ uint64_t StopAddress = CurrRange != InvalidRange
++ ? CurrRange.stop() + CurrRange.value()
++ : -1ULL;
++ CurrRange = FunctionRanges.find(Row.Address.Address);
++ bool CurrRangeValid =
++ CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address;
++ if (!CurrRangeValid) {
++ CurrRange = InvalidRange;
+ if (StopAddress != -1ULL) {
+ // Try harder by looking in the Address ranges map.
+ // There are corner cases where this finds a
+@@ -1748,9 +1762,14 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
+ // for now do as dsymutil.
+ // FIXME: Understand exactly what cases this addresses and
+ // potentially remove it along with the Ranges map.
+- if (Optional<std::pair<AddressRange, int64_t>> Range =
+- Ranges.getRangeValueThatContains(Row.Address.Address))
+- StopAddress = Row.Address.Address + (*Range).second;
++ auto Range = Ranges.lower_bound(Row.Address.Address);
++ if (Range != Ranges.begin() && Range != Ranges.end())
++ --Range;
++
++ if (Range != Ranges.end() && Range->first <= Row.Address.Address &&
++ Range->second.HighPC >= Row.Address.Address) {
++ StopAddress = Row.Address.Address + Range->second.Offset;
++ }
+ }
+ }
+ if (StopAddress != -1ULL && !Seq.empty()) {
+@@ -1766,7 +1785,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
+ insertLineSequence(Seq, NewRows);
+ }
+
+- if (!CurrRange)
++ if (!CurrRangeValid)
+ continue;
+ }
+
+@@ -1775,7 +1794,7 @@ void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit,
+ continue;
+
+ // Relocate row address and add it to the current sequence.
+- Row.Address.Address += CurrRange->second;
++ Row.Address.Address += CurrRange.value();
+ Seq.emplace_back(Row);
+
+ if (Row.EndSequence)
+@@ -1915,9 +1934,11 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
+ // the function entry point, thus we can't just lookup the address
+ // in the debug map. Use the AddressInfo's range map to see if the FDE
+ // describes something that we can relocate.
+- Optional<std::pair<AddressRange, int64_t>> Range =
+- Ranges.getRangeValueThatContains(Loc);
+- if (!Range) {
++ auto Range = Ranges.upper_bound(Loc);
++ if (Range != Ranges.begin())
++ --Range;
++ if (Range == Ranges.end() || Range->first > Loc ||
++ Range->second.HighPC <= Loc) {
+ // The +4 is to account for the size of the InitialLength field itself.
+ InputOffset = EntryOffset + InitialLength + 4;
+ continue;
+@@ -1945,7 +1966,7 @@ void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File,
+ // fields that will get reconstructed by emitFDE().
+ unsigned FDERemainingBytes = InitialLength - (4 + AddrSize);
+ TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize,
+- Loc + Range->second,
++ Loc + Range->second.Offset,
+ FrameData.substr(InputOffset, FDERemainingBytes));
+ InputOffset += FDERemainingBytes;
+ }
+diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+index 1cb20c0bb948..ebb1106521cc 100644
+--- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
++++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+@@ -105,11 +105,19 @@ void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
+
+ void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
+ int64_t PcOffset) {
+- Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
++ // Don't add empty ranges to the interval map. They are a problem because
++ // the interval map expects half open intervals. This is safe because they
++ // are empty anyway.
++ if (FuncHighPc != FuncLowPc)
++ Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
+ this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
+ this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
+ }
+
++bool CompileUnit::overlapsWithFunctionRanges(uint64_t LowPC, uint64_t HighPC) {
++ return Ranges.overlaps(LowPC, HighPC);
++}
++
+ void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
+ if (Die.getTag() != dwarf::DW_TAG_compile_unit)
+ RangeAttributes.push_back(Attr);
+diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+index a00e51fcf135..55ff6b14f945 100644
+--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
++++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+@@ -321,14 +321,13 @@ void DwarfStreamer::emitSwiftReflectionSection(
+ /// sized addresses describing the ranges.
+ void DwarfStreamer::emitRangesEntries(
+ int64_t UnitPcOffset, uint64_t OrigLowPc,
+- Optional<std::pair<AddressRange, int64_t>> FuncRange,
++ const FunctionIntervals::const_iterator &FuncRange,
+ const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
+ unsigned AddressSize) {
+ MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
+
+ // Offset each range by the right amount.
+- int64_t PcOffset =
+- (Entries.empty() || !FuncRange) ? 0 : FuncRange->second + UnitPcOffset;
++ int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
+ for (const auto &Range : Entries) {
+ if (Range.isBaseAddressSelectionEntry(AddressSize)) {
+ warn("unsupported base address selection operation",
+@@ -340,7 +339,8 @@ void DwarfStreamer::emitRangesEntries(
+ continue;
+
+ // All range entries should lie in the function range.
+- if (!FuncRange->first.contains(Range.StartAddress + OrigLowPc))
++ if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() &&
++ Range.EndAddress + OrigLowPc <= FuncRange.stop()))
+ warn("inconsistent range data.", "emitting debug_ranges");
+ MS->emitIntValue(Range.StartAddress + PcOffset, AddressSize);
+ MS->emitIntValue(Range.EndAddress + PcOffset, AddressSize);
+@@ -365,13 +365,11 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
+ // IntervalMap will have coalesced the non-linked ranges, but here
+ // we want to coalesce the linked addresses.
+ std::vector<std::pair<uint64_t, uint64_t>> Ranges;
+- const RangesTy &FunctionRanges = Unit.getFunctionRanges();
+- for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++) {
+- std::pair<AddressRange, int64_t> CurRange = FunctionRanges[Idx];
+-
+- Ranges.push_back(std::make_pair(CurRange.first.start() + CurRange.second,
+- CurRange.first.end() + CurRange.second));
+- }
++ const auto &FunctionRanges = Unit.getFunctionRanges();
++ for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end();
++ Range != End; ++Range)
++ Ranges.push_back(std::make_pair(Range.start() + Range.value(),
++ Range.stop() + Range.value()));
+
+ // The object addresses where sorted, but again, the linked
+ // addresses might end up in a different order.
+diff --git a/llvm/lib/Support/AddressRanges.cpp b/llvm/lib/Support/AddressRanges.cpp
+index 187d5be00dae..5ba011bac4e9 100644
+--- a/llvm/lib/Support/AddressRanges.cpp
++++ b/llvm/lib/Support/AddressRanges.cpp
+@@ -12,59 +12,48 @@
+
+ using namespace llvm;
+
+-AddressRanges::Collection::const_iterator
+-AddressRanges::insert(AddressRange Range) {
++void AddressRanges::insert(AddressRange Range) {
+ if (Range.size() == 0)
+- return Ranges.end();
++ return;
+
+ auto It = llvm::upper_bound(Ranges, Range);
+ auto It2 = It;
+- while (It2 != Ranges.end() && It2->start() <= Range.end())
++ while (It2 != Ranges.end() && It2->start() < Range.end())
+ ++It2;
+ if (It != It2) {
+- Range = {Range.start(), std::max(Range.end(), std::prev(It2)->end())};
++ Range = {Range.start(), std::max(Range.end(), It2[-1].end())};
+ It = Ranges.erase(It, It2);
+ }
+- if (It != Ranges.begin() && Range.start() <= std::prev(It)->end()) {
+- --It;
+- *It = {It->start(), std::max(It->end(), Range.end())};
+- return It;
+- }
+-
+- return Ranges.insert(It, Range);
++ if (It != Ranges.begin() && Range.start() < It[-1].end())
++ It[-1] = {It[-1].start(), std::max(It[-1].end(), Range.end())};
++ else
++ Ranges.insert(It, Range);
+ }
+
+-AddressRanges::Collection::const_iterator
+-AddressRanges::find(uint64_t Addr) const {
++bool AddressRanges::contains(uint64_t Addr) const {
+ auto It = std::partition_point(
+ Ranges.begin(), Ranges.end(),
+ [=](const AddressRange &R) { return R.start() <= Addr; });
+-
+- if (It == Ranges.begin())
+- return Ranges.end();
+-
+- --It;
+- if (Addr >= It->end())
+- return Ranges.end();
+-
+- return It;
++ return It != Ranges.begin() && Addr < It[-1].end();
+ }
+
+-AddressRanges::Collection::const_iterator
+-AddressRanges::find(AddressRange Range) const {
++bool AddressRanges::contains(AddressRange Range) const {
+ if (Range.size() == 0)
+- return Ranges.end();
+-
++ return false;
+ auto It = std::partition_point(
+ Ranges.begin(), Ranges.end(),
+ [=](const AddressRange &R) { return R.start() <= Range.start(); });
+-
+ if (It == Ranges.begin())
+- return Ranges.end();
+-
+- --It;
+- if (Range.end() > It->end())
+- return Ranges.end();
++ return false;
++ return Range.end() <= It[-1].end();
++}
+
+- return It;
++Optional<AddressRange>
++AddressRanges::getRangeThatContains(uint64_t Addr) const {
++ auto It = std::partition_point(
++ Ranges.begin(), Ranges.end(),
++ [=](const AddressRange &R) { return R.start() <= Addr; });
++ if (It != Ranges.begin() && Addr < It[-1].end())
++ return It[-1];
++ return llvm::None;
+ }
+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
+deleted file mode 100644
+index cfbb7cb10558..000000000000
+--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-func-overlapping-address-ranges.test
++++ /dev/null
+@@ -1,254 +0,0 @@
+-## This test checks that overlapping function address ranges
+-## are combined during --garbage-collection optimisation.
+-
+-# RUN: yaml2obj %s -o %t.o
+-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
+-# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+-
+-# CHECK: DW_TAG_compile_unit
+-# CHECK: DW_AT_name{{.*}}"CU1"
+-# CHECK: DW_AT_low_pc{{.*}}0000000000001000
+-# CHECK: DW_AT_ranges
+-# CHECK: [0x0000000000001000, 0x000000000000102d)
+-# CHECK: [0x0000000000002002, 0x000000000000200d)
+-# CHECK: [0x000000000000201b, 0x000000000000202a)
+-# CHECK: [0x0000000000003002, 0x0000000000003007)
+-# CHECK: [0x0000000000003012, 0x0000000000003017)
+-# CHECK: [0x0000000000003018, 0x000000000000301a)
+-# CHECK: [0x0000000000003022, 0x0000000000003027
+-# CHECK: DW_TAG_class_type
+-# CHECK: DW_AT_name{{.*}}"class1"
+-# CHECK: DW_TAG_class_type
+-# CHECK: "class2"
+-# CHECK: DW_TAG_subprogram
+-# CHECK: DW_AT_name{{.*}}"foo1"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
+-# CHECK: DW_AT_type{{.*}}"class1"
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo2"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001004
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001007
+-# CHECK: DW_AT_type{{.*}}"class2"
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo3"
+-# CHECK: DW_AT_low_pc{{.*}}0x000000000000100d
+-# CHECK: DW_AT_high_pc{{.*}}0x000000000000102d
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo4"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000002002
+-# CHECK: DW_AT_high_pc{{.*}}0x000000000000200d
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo5"
+-# CHECK: DW_AT_low_pc{{.*}}0x000000000000201b
+-# CHECK: DW_AT_high_pc{{.*}}0x000000000000202a
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo6"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003002
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003007
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo7"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003012
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003017
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo8"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003022
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003027
+-# CHECK: DW_TAG_subprogram
+-# CHECK: "foo9"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003012
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000003017
+-# CHECK: "foo10"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000003018
+-# CHECK: DW_AT_high_pc{{.*}}0x000000000000301a
+-
+---- !ELF
+-FileHeader:
+- Class: ELFCLASS64
+- Data: ELFDATA2LSB
+- Type: ET_REL
+- Machine: EM_X86_64
+-Sections:
+- - Name: .text
+- Type: SHT_PROGBITS
+- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+- Address: 0x1000
+- AddressAlign: 0x0000000000000010
+- Content: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+- - Name: .text2
+- Type: SHT_PROGBITS
+- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+- Address: 0x2000
+- AddressAlign: 0x0000000000000010
+- Content: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+- - Name: .text3
+- Type: SHT_PROGBITS
+- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+- Address: 0x3000
+- AddressAlign: 0x0000000000000010
+- Content: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+-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
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_ranges
+- Form: DW_FORM_sec_offset
+- - Tag: DW_TAG_subprogram
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_high_pc
+- Form: DW_FORM_data8
+- - Attribute: DW_AT_type
+- Form: DW_FORM_ref4
+- - 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_ref4
+- - 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_ref4
+- - Tag: DW_TAG_base_type
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- debug_info:
+- - Version: 4
+- Entries:
+- - AbbrCode: 1
+- Values:
+- - CStr: by_hand
+- - Value: 0x04
+- - CStr: CU1
+- - Value: 0x00
+- - Value: 0x00
+- - AbbrCode: 3
+- Values:
+- - CStr: class1
+- - AbbrCode: 4
+- Values:
+- - Value: 0x00000052
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 3
+- Values:
+- - CStr: class2
+- - AbbrCode: 4
+- Values:
+- - Value: 0x00000052
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 8
+- Values:
+- - CStr: int
+- - AbbrCode: 2
+- Values:
+- - CStr: foo1
+- - Value: 0x1000
+- - Value: 0x10
+- - Value: 0x00000026
+- - AbbrCode: 2
+- Values:
+- - CStr: foo2
+- - Value: 0x1004
+- - Value: 0x3
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo3
+- - Value: 0x100d
+- - Value: 0x20
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo4
+- - Value: 0x2002
+- - Value: 0xb
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo5
+- - Value: 0x201b
+- - Value: 0xf
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo6
+- - Value: 0x3002
+- - Value: 0x5
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo7
+- - Value: 0x3012
+- - Value: 0x5
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo8
+- - Value: 0x3022
+- - Value: 0x5
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo9
+- - Value: 0x3012
+- - Value: 0x5
+- - Value: 0x0000003c
+- - AbbrCode: 2
+- Values:
+- - CStr: foo10
+- - Value: 0x3018
+- - Value: 0x2
+- - Value: 0x0000003c
+- - AbbrCode: 0
+-
+- debug_ranges:
+- - Offset: 0x00000000
+- AddrSize: 0x08
+- Entries:
+- - LowOffset: 0x0000000000001000
+- HighOffset: 0x000000000000102d
+- - LowOffset: 0x0000000000002000
+- HighOffset: 0x000000000000202d
+- - LowOffset: 0x0000000000000000
+- HighOffset: 0x0000000000000000
+-...
+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
+deleted file mode 100644
+index f9d42c28d420..000000000000
+--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/gc-unit-overlapping-address-ranges.test
++++ /dev/null
+@@ -1,247 +0,0 @@
+-## This test checks that overlapping compile unit address ranges
+-## are ignored (i.e. left unchanged) by --garbage-collection
+-## optimisation.
+-
+-# RUN: yaml2obj %s -o %t.o
+-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1
+-# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+-
+-# CHECK: DW_TAG_compile_unit
+-# CHECK: DW_AT_name{{.*}}"CU1"
+-# CHECK: DW_TAG_class_type
+-# CHECK: DW_AT_name{{.*}}"class1"
+-# CHECK: DW_TAG_subprogram
+-# CHECK: DW_AT_name{{.*}}"foo1"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
+-# CHECK: DW_TAG_subprogram
+-# CHECK: DW_AT_name{{.*}}"foo2"
+-# CHECK: DW_AT_low_pc{{.*}}0x0000000000001000
+-# CHECK: DW_AT_high_pc{{.*}}0x0000000000001010
+-# CHECK: DW_AT_type{{.*}}"class2"
+-
+---- !ELF
+-FileHeader:
+- Class: ELFCLASS64
+- Data: ELFDATA2LSB
+- Type: ET_REL
+- Machine: EM_X86_64
+-Sections:
+- - Name: .text
+- Type: SHT_PROGBITS
+- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+- Address: 0x1000
+- AddressAlign: 0x0000000000000010
+- Content: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+-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
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_high_pc
+- Form: DW_FORM_data8
+- - Tag: DW_TAG_subprogram
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_high_pc
+- Form: DW_FORM_data8
+- - Attribute: DW_AT_type
+- Form: DW_FORM_ref4
+- - 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_ref4
+- - 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_ref4
+- - Tag: DW_TAG_base_type
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- - 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
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_high_pc
+- Form: DW_FORM_data8
+- - Tag: DW_TAG_subprogram
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- - Attribute: DW_AT_low_pc
+- Form: DW_FORM_addr
+- - Attribute: DW_AT_high_pc
+- Form: DW_FORM_data8
+- - Attribute: DW_AT_type
+- Form: DW_FORM_ref4
+- - 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_ref4
+- - 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_ref4
+- - Tag: DW_TAG_base_type
+- Children: DW_CHILDREN_no
+- Attributes:
+- - Attribute: DW_AT_name
+- Form: DW_FORM_string
+- debug_info:
+- - Version: 4
+- Entries:
+- - AbbrCode: 1
+- Values:
+- - CStr: by_hand
+- - Value: 0x04
+- - CStr: CU1
+- - Value: 0x1000
+- - Value: 0x1b
+- - AbbrCode: 3
+- Values:
+- - CStr: class1
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 3
+- Values:
+- - CStr: class2
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 3
+- Values:
+- - CStr: class3
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 8
+- Values:
+- - CStr: int
+- - AbbrCode: 2
+- Values:
+- - CStr: foo1
+- - Value: 0x1000
+- - Value: 0x10
+- - Value: 0x0000002a
+- - AbbrCode: 0
+- - Version: 4
+- Entries:
+- - AbbrCode: 1
+- Values:
+- - CStr: by_hand
+- - Value: 0x04
+- - CStr: CU1
+- - Value: 0x1000
+- - Value: 0x1b
+- - AbbrCode: 3
+- Values:
+- - CStr: class1
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 3
+- Values:
+- - CStr: class2
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 3
+- Values:
+- - CStr: class3
+- - AbbrCode: 4
+- Values:
+- - Value: 0x0000006c
+- - CStr: member1
+- - AbbrCode: 0
+- - AbbrCode: 8
+- Values:
+- - CStr: int
+- - AbbrCode: 2
+- Values:
+- - CStr: foo2
+- - Value: 0x1000
+- - Value: 0x10
+- - Value: 0x00000040
+- - AbbrCode: 0
+-...
+diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+index 5f43680ba498..293fd6b17fe1 100644
+--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
++++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+@@ -18,6 +18,7 @@
+ #include "llvm/ADT/DenseSet.h"
+ #include "llvm/ADT/FoldingSet.h"
+ #include "llvm/ADT/Hashing.h"
++#include "llvm/ADT/IntervalMap.h"
+ #include "llvm/ADT/None.h"
+ #include "llvm/ADT/Optional.h"
+ #include "llvm/ADT/PointerIntPair.h"
+diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+index 623441c749a5..be9bedc6627d 100644
+--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
++++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+@@ -132,8 +132,8 @@ private:
+ for (const auto &Entry : DMO.symbols()) {
+ const auto &Mapping = Entry.getValue();
+ if (Mapping.Size && Mapping.ObjectAddress)
+- AddressRanges.insert(
+- {*Mapping.ObjectAddress, *Mapping.ObjectAddress + Mapping.Size},
++ AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
++ *Mapping.ObjectAddress + Mapping.Size,
+ int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
+ }
+ }
+diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+index 3e70f460bc58..fb8cca0ac55c 100644
+--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
++++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+@@ -49,7 +49,7 @@ public:
+ if (Size == 0)
+ continue;
+ const uint64_t StartAddr = Sect.getAddress();
+- TextAddressRanges.insert({StartAddr, StartAddr + Size});
++ TextAddressRanges[{StartAddr}] = {StartAddr + Size, 0};
+ }
+
+ // Check CU address ranges for tombstone value.
+@@ -60,7 +60,7 @@ public:
+ for (auto &Range : *ARanges) {
+ if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
+ Options.Tombstone, CU->getAddressByteSize()))
+- DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0);
++ DWARFAddressRanges[{Range.LowPC}] = {Range.HighPC, 0};
+ }
+ }
+ }
+@@ -147,13 +147,17 @@ protected:
+ // of executable sections.
+ bool isInsideExecutableSectionsAddressRange(uint64_t LowPC,
+ Optional<uint64_t> HighPC) {
+- Optional<AddressRange> Range =
+- TextAddressRanges.getRangeThatContains(LowPC);
+-
+- if (HighPC)
+- return Range.has_value() && Range->end() >= *HighPC;
++ auto Range = TextAddressRanges.lower_bound(LowPC);
++ if ((Range == TextAddressRanges.end() || Range->first != LowPC) &&
++ Range != TextAddressRanges.begin())
++ --Range;
++
++ if (Range != TextAddressRanges.end() && Range->first <= LowPC &&
++ (HighPC ? Range->second.HighPC >= HighPC
++ : Range->second.HighPC >= LowPC))
++ return true;
+
+- return Range.has_value();
++ return false;
+ }
+
+ uint64_t isBFDDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC,
+@@ -207,7 +211,7 @@ protected:
+
+ private:
+ RangesTy DWARFAddressRanges;
+- AddressRanges TextAddressRanges;
++ RangesTy TextAddressRanges;
+ const Options &Opts;
+ };
+
+diff --git a/llvm/unittests/Support/AddressRangeTest.cpp b/llvm/unittests/Support/AddressRangeTest.cpp
+index 468f1e22ffa8..95943ad0365a 100644
+--- a/llvm/unittests/Support/AddressRangeTest.cpp
++++ b/llvm/unittests/Support/AddressRangeTest.cpp
+@@ -100,7 +100,7 @@ TEST(AddressRangeTest, TestRanges) {
+ EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x1000)));
+ EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x1000 + 1)));
+ EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2000)));
+- EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2001)));
++ EXPECT_FALSE(Ranges.contains(AddressRange(0x1000, 0x2001)));
+ EXPECT_TRUE(Ranges.contains(AddressRange(0x2000, 0x3000)));
+ EXPECT_FALSE(Ranges.contains(AddressRange(0x2000, 0x3001)));
+ EXPECT_FALSE(Ranges.contains(AddressRange(0x3000, 0x3001)));
+@@ -125,22 +125,16 @@ TEST(AddressRangeTest, TestRanges) {
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
+
+- // Verify that adjacent ranges get combined
+- Ranges.insert(AddressRange(0x2000, 0x2fff));
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2fff));
+-
+- // Verify that ranges having 1 byte gap do not get combined
+- Ranges.insert(AddressRange(0x3000, 0x4000));
++ // Verify that adjacent ranges don't get combined
++ Ranges.insert(AddressRange(0x2000, 0x3000));
+ EXPECT_EQ(Ranges.size(), 2u);
+- EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2fff));
+- EXPECT_EQ(Ranges[1], AddressRange(0x3000, 0x4000));
+-
++ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
++ EXPECT_EQ(Ranges[1], AddressRange(0x2000, 0x3000));
+ // Verify if we add an address range that intersects two ranges
+ // that they get combined
+ Ranges.insert(AddressRange(Ranges[0].end() - 1, Ranges[1].start() + 1));
+ EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x4000));
++ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x3000));
+
+ Ranges.insert(AddressRange(0x3000, 0x4000));
+ Ranges.insert(AddressRange(0x4000, 0x5000));
+@@ -148,87 +142,3 @@ TEST(AddressRangeTest, TestRanges) {
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x5000));
+ }
+-
+-TEST(AddressRangeTest, TestRangesMap) {
+- AddressRangesMap<int> Ranges;
+-
+- EXPECT_EQ(Ranges.size(), 0u);
+- EXPECT_TRUE(Ranges.empty());
+-
+- // Add single range.
+- Ranges.insert(AddressRange(0x1000, 0x2000), 0xfe);
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_FALSE(Ranges.empty());
+- EXPECT_TRUE(Ranges.contains(0x1500));
+- EXPECT_TRUE(Ranges.contains(AddressRange(0x1000, 0x2000)));
+-
+- // Clear ranges.
+- Ranges.clear();
+- EXPECT_EQ(Ranges.size(), 0u);
+- EXPECT_TRUE(Ranges.empty());
+-
+- // Add range and check value.
+- Ranges.insert(AddressRange(0x1000, 0x2000), 0xfe);
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xfe);
+-
+- // Add adjacent range and check value.
+- Ranges.insert(AddressRange(0x2000, 0x3000), 0xfc);
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xfc);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x2000)->second, 0xfc);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x2900)->second, 0xfc);
+- EXPECT_FALSE(Ranges.getRangeValueThatContains(0x3000));
+-
+- // Add intersecting range and check value.
+- Ranges.insert(AddressRange(0x2000, 0x3000), 0xff);
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xff);
+-
+- // Add second range and check values.
+- Ranges.insert(AddressRange(0x4000, 0x5000), 0x0);
+- EXPECT_EQ(Ranges.size(), 2u);
+- EXPECT_EQ(Ranges[0].second, 0xff);
+- EXPECT_EQ(Ranges[1].second, 0x0);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0xff);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x4000)->second, 0x0);
+-
+- // Add intersecting range and check value.
+- Ranges.insert(AddressRange(0x0, 0x6000), 0x1);
+- EXPECT_EQ(Ranges.size(), 1u);
+- EXPECT_EQ(Ranges.getRangeValueThatContains(0x1000)->second, 0x1);
+-
+- // Check that values are correctly preserved for combined ranges.
+- Ranges.clear();
+- Ranges.insert(AddressRange(0x0, 0xff), 0x1);
+- Ranges.insert(AddressRange(0x100, 0x1ff), 0x2);
+- Ranges.insert(AddressRange(0x200, 0x2ff), 0x3);
+- Ranges.insert(AddressRange(0x300, 0x3ff), 0x4);
+- Ranges.insert(AddressRange(0x400, 0x4ff), 0x5);
+- Ranges.insert(AddressRange(0x500, 0x5ff), 0x6);
+- Ranges.insert(AddressRange(0x600, 0x6ff), 0x7);
+-
+- Ranges.insert(AddressRange(0x150, 0x350), 0xff);
+- EXPECT_EQ(Ranges.size(), 5u);
+- EXPECT_EQ(Ranges[0].first, AddressRange(0x0, 0xff));
+- EXPECT_EQ(Ranges[0].second, 0x1);
+- EXPECT_EQ(Ranges[1].first, AddressRange(0x100, 0x3ff));
+- EXPECT_EQ(Ranges[1].second, 0xff);
+- EXPECT_EQ(Ranges[2].first, AddressRange(0x400, 0x4ff));
+- EXPECT_EQ(Ranges[2].second, 0x5);
+- EXPECT_EQ(Ranges[3].first, AddressRange(0x500, 0x5ff));
+- EXPECT_EQ(Ranges[3].second, 0x6);
+- EXPECT_EQ(Ranges[4].first, AddressRange(0x600, 0x6ff));
+- EXPECT_EQ(Ranges[4].second, 0x7);
+-
+- Ranges.insert(AddressRange(0x3ff, 0x400), 0x5);
+- EXPECT_EQ(Ranges.size(), 4u);
+- EXPECT_EQ(Ranges[0].first, AddressRange(0x0, 0xff));
+- EXPECT_EQ(Ranges[0].second, 0x1);
+- EXPECT_EQ(Ranges[1].first, AddressRange(0x100, 0x4ff));
+- EXPECT_EQ(Ranges[1].second, 0x5);
+- EXPECT_EQ(Ranges[2].first, AddressRange(0x500, 0x5ff));
+- EXPECT_EQ(Ranges[2].second, 0x6);
+- EXPECT_EQ(Ranges[3].first, AddressRange(0x600, 0x6ff));
+- EXPECT_EQ(Ranges[3].second, 0x7);
+-}
+--
+2.39.0.1.g6739ec1790
+