diff options
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.patch | 1323 |
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 + |