diff --git a/include/llvm/DebugInfo/GSYM/FunctionInfo.h b/include/llvm/DebugInfo/GSYM/FunctionInfo.h index 1a7a365cf1a..5916a4feaee 100644 --- a/include/llvm/DebugInfo/GSYM/FunctionInfo.h +++ b/include/llvm/DebugInfo/GSYM/FunctionInfo.h @@ -56,15 +56,15 @@ struct FunctionInfo { return Name != 0; } - uint64_t startAddress() const { return Range.startAddress(); } - uint64_t endAddress() const { return Range.endAddress(); } + uint64_t startAddress() const { return Range.Start; } + uint64_t endAddress() const { return Range.End; } uint64_t size() const { return Range.size(); } - void setStartAddress(uint64_t Addr) { Range.setStartAddress(Addr); } - void setEndAddress(uint64_t Addr) { Range.setEndAddress(Addr); } - void setSize(uint64_t Size) { Range.setSize(Size); } + void setStartAddress(uint64_t Addr) { Range.End = Addr; } + void setEndAddress(uint64_t Addr) { Range.End = Addr; } + void setSize(uint64_t Size) { Range.End = Range.Start + Size; } void clear() { - Range.clear(); + Range = {0, 0}; Name = 0; Lines.clear(); Inline.clear(); diff --git a/include/llvm/DebugInfo/GSYM/Range.h b/include/llvm/DebugInfo/GSYM/Range.h index 23c3660d7e9..772ff244c5b 100644 --- a/include/llvm/DebugInfo/GSYM/Range.h +++ b/include/llvm/DebugInfo/GSYM/Range.h @@ -27,58 +27,28 @@ namespace gsym { /// A class that represents an address range. The range is specified using /// a start and an end address. -class AddressRange { +struct AddressRange { uint64_t Start; uint64_t End; -public: - AddressRange(uint64_t S = 0, uint64_t E = 0) : Start(S), End(E) {} - /// Access to the size must use the size() accessor to ensure the correct - /// answer. This allows an AddressRange to be constructed with invalid - /// address ranges where the end address is less that the start address - /// either because it was not set, or because of incorrect data. - uint64_t size() const { return Start < End ? End - Start : 0; } - void setStartAddress(uint64_t Addr) { Start = Addr; } - void setEndAddress(uint64_t Addr) { End = Addr; } - void setSize(uint64_t Size) { End = Start + Size; } - uint64_t startAddress() const { return Start; } - /// Access to the end address must use the size() accessor to ensure the - /// correct answer. This allows an AddressRange to be constructed with - /// invalid address ranges where the end address is less that the start - /// address either because it was not set, or because of incorrect data. - uint64_t endAddress() const { return Start + size(); } - void clear() { - Start = 0; - End = 0; - } - bool contains(uint64_t Addr) const { return Start <= Addr && Addr < endAddress(); } - bool isContiguousWith(const AddressRange &R) const { - return (Start <= R.endAddress()) && (endAddress() >= R.Start); - } + AddressRange() : Start(0), End(0) {} + AddressRange(uint64_t S, uint64_t E) : Start(S), End(E) {} + uint64_t size() const { return End - Start; } + bool contains(uint64_t Addr) const { return Start <= Addr && Addr < End; } bool intersects(const AddressRange &R) const { - return (Start < R.endAddress()) && (endAddress() > R.Start); + return Start < R.End && R.Start < End; } - bool intersect(const AddressRange &R) { - if (intersects(R)) { - Start = std::min(Start, R.Start); - End = std::max(endAddress(), R.endAddress()); - return true; - } - return false; + + bool operator==(const AddressRange &R) const { + return Start == R.Start && End == R.End; + } + bool operator!=(const AddressRange &R) const { + return !(*this == R); + } + bool operator<(const AddressRange &R) const { + return std::make_pair(Start, End) < std::make_pair(R.Start, R.End); } }; -inline bool operator==(const AddressRange &LHS, const AddressRange &RHS) { - return LHS.startAddress() == RHS.startAddress() && LHS.endAddress() == RHS.endAddress(); -} -inline bool operator!=(const AddressRange &LHS, const AddressRange &RHS) { - return LHS.startAddress() != RHS.startAddress() || LHS.endAddress() != RHS.endAddress(); -} -inline bool operator<(const AddressRange &LHS, const AddressRange &RHS) { - if (LHS.startAddress() == RHS.startAddress()) - return LHS.endAddress() < RHS.endAddress(); - return LHS.startAddress() < RHS.startAddress(); -} - raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R); /// The AddressRanges class helps normalize address range collections. @@ -96,7 +66,7 @@ public: void clear() { Ranges.clear(); } bool empty() const { return Ranges.empty(); } bool contains(uint64_t Addr) const; - void insert(const AddressRange &R); + void insert(AddressRange Range); size_t size() const { return Ranges.size(); } bool operator==(const AddressRanges &RHS) const { return Ranges == RHS.Ranges; diff --git a/lib/DebugInfo/GSYM/FunctionInfo.cpp b/lib/DebugInfo/GSYM/FunctionInfo.cpp index bd0c8bc51f5..55c36a55b4b 100644 --- a/lib/DebugInfo/GSYM/FunctionInfo.cpp +++ b/lib/DebugInfo/GSYM/FunctionInfo.cpp @@ -13,8 +13,7 @@ using namespace llvm; using namespace gsym; raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const FunctionInfo &FI) { - OS << '[' << HEX64(FI.Range.startAddress()) << '-' - << HEX64(FI.Range.endAddress()) << "): " + OS << '[' << HEX64(FI.Range.Start) << '-' << HEX64(FI.Range.End) << "): " << "Name=" << HEX32(FI.Name) << '\n'; for (const auto &Line : FI.Lines) OS << Line << '\n'; diff --git a/lib/DebugInfo/GSYM/InlineInfo.cpp b/lib/DebugInfo/GSYM/InlineInfo.cpp index 78e6ed46274..781c1755241 100644 --- a/lib/DebugInfo/GSYM/InlineInfo.cpp +++ b/lib/DebugInfo/GSYM/InlineInfo.cpp @@ -34,7 +34,7 @@ raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const InlineInfo &II) { return OS; } -static bool getInlineStackHelper(const InlineInfo &II, uint64_t Addr, +static bool getInlineStackHelper(const InlineInfo &II, uint64_t Addr, std::vector &InlineStack) { if (II.Ranges.contains(Addr)) { // If this is the top level that represents the concrete function, diff --git a/lib/DebugInfo/GSYM/Range.cpp b/lib/DebugInfo/GSYM/Range.cpp index 57e664d825a..ca61984dacb 100644 --- a/lib/DebugInfo/GSYM/Range.cpp +++ b/lib/DebugInfo/GSYM/Range.cpp @@ -15,53 +15,41 @@ using namespace llvm; using namespace gsym; -void AddressRanges::insert(const AddressRange &Range) { +void AddressRanges::insert(AddressRange Range) { if (Range.size() == 0) return; - // Ranges.insert(std::upper_bound(Ranges.begin(), Ranges.end(), Range), Range); - // // Check if an existing range intersects with this range, and if so, - // // grow the intersecting ranges instead of adding a new one. - auto Begin = Ranges.begin(); - auto End = Ranges.end(); - const auto Iter = std::upper_bound(Begin, End, Range); - if (Iter != Begin) { - auto PrevIter = Iter - 1; - // If the previous range itersects with "Range" they will be combined. - if (PrevIter->intersect(Range)) { - // Now check if the previous range intersects with the next range since - // the previous range was combined. If so, combine them and remove the - // next range. - if (Iter != End && PrevIter->intersect(*Iter)) - Ranges.erase(Iter); - return; - } + auto It = llvm::upper_bound(Ranges, Range); + auto It2 = It; + while (It2 != Ranges.end() && It2->Start < Range.End) + ++It2; + if (It != It2) { + Range.End = std::max(Range.End, It2[-1].End); + It = Ranges.erase(It, It2); } - // If the next range intersects with "Range", combined and return. - if (Iter != End && Iter->intersect(Range)) - return; - Ranges.insert(Iter, Range); + if (It != Ranges.begin() && Range.Start < It[-1].End) + It[-1].End = std::max(It[-1].End, Range.End); + else + Ranges.insert(It, Range); } bool AddressRanges::contains(uint64_t Addr) const { auto It = std::partition_point( Ranges.begin(), Ranges.end(), - [=](const AddressRange &R) { return R.startAddress() <= Addr; }); - return It != Ranges.begin() && It[-1].contains(Addr); + [=](const AddressRange &R) { return R.Start <= Addr; }); + return It != Ranges.begin() && Addr < It[-1].End; } raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) { - return OS << '[' << HEX64(R.startAddress()) << " - " << HEX64(R.endAddress()) - << ")"; + return OS << '[' << HEX64(R.Start) << " - " << HEX64(R.End) << ")"; } raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRanges &AR) { size_t Size = AR.size(); - for (size_t I=0; Isize(), 1u); ASSERT_EQ(*InlineInfos->at(0), Inline1); - InlineInfos = Root.getInlineStack(Inline1.Ranges[0].endAddress() - 1); + InlineInfos = Root.getInlineStack(Inline1.Ranges[0].End - 1); EXPECT_TRUE(InlineInfos); ASSERT_EQ(InlineInfos->size(), 1u); ASSERT_EQ(*InlineInfos->at(0), Inline1); // Verify we get two inline stack entries for addresses that are in // [0x152-0x155) - InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].startAddress()); + InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].Start); EXPECT_TRUE(InlineInfos); ASSERT_EQ(InlineInfos->size(), 2u); ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1); ASSERT_EQ(*InlineInfos->at(1), Inline1); - InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].endAddress() - 1); + InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].End - 1); EXPECT_TRUE(InlineInfos); ASSERT_EQ(InlineInfos->size(), 2u); ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1); @@ -213,12 +213,12 @@ TEST(GSYMTest, TestInlineInfo) { // Verify we get two inline stack entries for addresses that are in // [0x157-0x158) - InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].startAddress()); + InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].Start); EXPECT_TRUE(InlineInfos); ASSERT_EQ(InlineInfos->size(), 2u); ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2); ASSERT_EQ(*InlineInfos->at(1), Inline1); - InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].endAddress() - 1); + InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].End - 1); EXPECT_TRUE(InlineInfos); ASSERT_EQ(InlineInfos->size(), 2u); ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2); @@ -257,8 +257,6 @@ TEST(GSYMTest, TestRanges) { const uint64_t EndAddr = 0x2000; // Verify constructor and API to ensure it takes start and end address. const AddressRange Range(StartAddr, EndAddr); - EXPECT_EQ(Range.startAddress(), StartAddr); - EXPECT_EQ(Range.endAddress(), EndAddr); EXPECT_EQ(Range.size(), EndAddr - StartAddr); // Verify llvm::gsym::AddressRange::contains(). @@ -291,9 +289,9 @@ TEST(GSYMTest, TestRanges) { EXPECT_LT(Range, RangeDifferentEnd); EXPECT_LT(Range, RangeDifferentStartEnd); // Test "bool operator<(const AddressRange &, uint64_t)" - EXPECT_LT(Range, StartAddr + 1); + EXPECT_LT(Range.Start, StartAddr + 1); // Test "bool operator<(uint64_t, const AddressRange &)" - EXPECT_LT(StartAddr - 1, Range); + EXPECT_LT(StartAddr - 1, Range.Start); // Verify llvm::gsym::AddressRange::isContiguousWith() and // llvm::gsym::AddressRange::intersects(). @@ -305,14 +303,6 @@ TEST(GSYMTest, TestRanges) { const AddressRange StartsAtRangeEnd(EndAddr, EndAddr + 0x100); const AddressRange StartsAfterRangeEnd(EndAddr + 1, EndAddr + 0x100); - EXPECT_FALSE(Range.isContiguousWith(EndsBeforeRangeStart)); - EXPECT_TRUE(Range.isContiguousWith(EndsAtRangeStart)); - EXPECT_TRUE(Range.isContiguousWith(OverlapsRangeStart)); - EXPECT_TRUE(Range.isContiguousWith(InsideRange)); - EXPECT_TRUE(Range.isContiguousWith(OverlapsRangeEnd)); - EXPECT_TRUE(Range.isContiguousWith(StartsAtRangeEnd)); - EXPECT_FALSE(Range.isContiguousWith(StartsAfterRangeEnd)); - EXPECT_FALSE(Range.intersects(EndsBeforeRangeStart)); EXPECT_FALSE(Range.intersects(EndsAtRangeStart)); EXPECT_TRUE(Range.intersects(OverlapsRangeStart)); @@ -350,12 +340,12 @@ TEST(GSYMTest, TestRanges) { EXPECT_EQ(Ranges[0], AddressRange(0x1100, 0x1F00)); // Verify a range that starts before and intersects gets combined. - Ranges.insert(AddressRange(0x1000, Ranges[0].startAddress() + 1)); + Ranges.insert(AddressRange(0x1000, Ranges[0].Start + 1)); EXPECT_EQ(Ranges.size(), 1u); EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x1F00)); // Verify a range that starts inside and extends ranges gets combined. - Ranges.insert(AddressRange(Ranges[0].endAddress() - 1, 0x2000)); + Ranges.insert(AddressRange(Ranges[0].End - 1, 0x2000)); EXPECT_EQ(Ranges.size(), 1u); EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000)); @@ -366,10 +356,15 @@ TEST(GSYMTest, TestRanges) { 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].endAddress() - 1, Ranges[1].startAddress() + 1)); + Ranges.insert(AddressRange(Ranges[0].End - 1, Ranges[1].Start + 1)); EXPECT_EQ(Ranges.size(), 1u); EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x3000)); + + Ranges.insert(AddressRange(0x3000, 0x4000)); + Ranges.insert(AddressRange(0x4000, 0x5000)); + Ranges.insert(AddressRange(0x2000, 0x4500)); + EXPECT_EQ(Ranges.size(), 1u); + EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x5000)); } TEST(GSYMTest, TestStringTable) {