llvm-project/llvm/lib/Support/AddressRanges.cpp
Alexey Lapshin 8bb4451a65 [Reland][DebugInfo][llvm-dwarfutil] Combine overlapped address ranges.
DWARF files may contain overlapping address ranges. f.e. it can happen if the two
copies of the function have identical instruction sequences and they end up sharing.
That looks incorrect from the point of view of DWARF spec. Current implementation
of DWARFLinker does not combine overlapped address ranges. It would be good if such
ranges would be handled in some useful way. Thus, this patch allows DWARFLinker
to combine overlapped ranges in a single one.

Depends on D86539

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D123469
2022-07-21 14:15:39 +03:00

71 lines
1.8 KiB
C++

//===- AddressRanges.cpp ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/AddressRanges.h"
#include "llvm/ADT/STLExtras.h"
#include <inttypes.h>
using namespace llvm;
AddressRanges::Collection::const_iterator
AddressRanges::insert(AddressRange Range) {
if (Range.size() == 0)
return Ranges.end();
auto It = llvm::upper_bound(Ranges, Range);
auto It2 = It;
while (It2 != Ranges.end() && It2->start() <= Range.end())
++It2;
if (It != It2) {
Range = {Range.start(), std::max(Range.end(), std::prev(It2)->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);
}
AddressRanges::Collection::const_iterator
AddressRanges::find(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;
}
AddressRanges::Collection::const_iterator
AddressRanges::find(AddressRange Range) const {
if (Range.size() == 0)
return Ranges.end();
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 It;
}