aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp')
-rw-r--r--llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp
new file mode 100644
index 000000000000..b6003fcb8b93
--- /dev/null
+++ b/llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp
@@ -0,0 +1,158 @@
+//===-- LVRange.cpp -------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements the LVRange class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+
+#define DEBUG_TYPE "Range"
+
+void LVRange::startSearch() {
+ RangesTree.clear();
+
+ LLVM_DEBUG({ dbgs() << "\nRanges Tree entries:\n"; });
+
+ // Traverse the ranges and store them into the interval tree.
+ for (LVRangeEntry &RangeEntry : RangeEntries) {
+ LLVM_DEBUG({
+ LVScope *Scope = RangeEntry.scope();
+ dbgs() << "Scope: " << format_decimal(Scope->getLevel(), 5) << " "
+ << "Range: [" << hexValue(RangeEntry.lower()) << ":"
+ << hexValue(RangeEntry.upper()) << "]\n";
+ });
+
+ RangesTree.insert(RangeEntry.lower(), RangeEntry.upper(),
+ RangeEntry.scope());
+ }
+
+ // Create the interval tree.
+ RangesTree.create();
+
+ LLVM_DEBUG({
+ dbgs() << "\nRanges Tree:\n";
+ RangesTree.print(dbgs());
+ });
+}
+
+// Add the pair in an ascending order, with the smallest ranges at the
+// start; in that way, enclosing scopes ranges are at the end of the
+// list; we assume that low <= high.
+void LVRange::addEntry(LVScope *Scope, LVAddress LowerAddress,
+ LVAddress UpperAddress) {
+ // We assume the low <= high.
+ if (LowerAddress > UpperAddress)
+ std::swap(LowerAddress, UpperAddress);
+
+ // Record the lowest and highest seen addresses.
+ if (LowerAddress < Lower)
+ Lower = LowerAddress;
+ if (UpperAddress > Upper)
+ Upper = UpperAddress;
+
+ // Just add the scope and range pair, in no particular order.
+ RangeEntries.emplace_back(LowerAddress, UpperAddress, Scope);
+}
+
+void LVRange::addEntry(LVScope *Scope) {
+ assert(Scope && "Scope must not be nullptr");
+ // Traverse the ranges and update the ranges set only if the ranges
+ // values are not already recorded.
+ if (const LVLocations *Locations = Scope->getRanges())
+ for (const LVLocation *Location : *Locations) {
+ LVAddress LowPC = Location->getLowerAddress();
+ LVAddress HighPC = Location->getUpperAddress();
+ if (!hasEntry(LowPC, HighPC))
+ // Add the pair of addresses.
+ addEntry(Scope, LowPC, HighPC);
+ }
+}
+
+// Get the scope associated with the input address.
+LVScope *LVRange::getEntry(LVAddress Address) const {
+ LLVM_DEBUG({ dbgs() << format("Searching: 0x%08x\nFound: ", Address); });
+
+ LVScope *Target = nullptr;
+ LVLevel TargetLevel = 0;
+ LVLevel Level = 0;
+ LVScope *Scope = nullptr;
+ for (LVRangesTree::find_iterator Iter = RangesTree.find(Address),
+ End = RangesTree.find_end();
+ Iter != End; ++Iter) {
+ LLVM_DEBUG(
+ { dbgs() << format("[0x%08x,0x%08x] ", Iter->left(), Iter->right()); });
+ Scope = Iter->value();
+ Level = Scope->getLevel();
+ if (Level > TargetLevel) {
+ TargetLevel = Level;
+ Target = Scope;
+ }
+ }
+
+ LLVM_DEBUG({ dbgs() << (Scope ? "\n" : "None\n"); });
+
+ return Target;
+}
+
+// Find the associated Scope for the given ranges values.
+LVScope *LVRange::getEntry(LVAddress LowerAddress,
+ LVAddress UpperAddress) const {
+ for (const LVRangeEntry &RangeEntry : RangeEntries)
+ if (LowerAddress >= RangeEntry.lower() && UpperAddress < RangeEntry.upper())
+ return RangeEntry.scope();
+ return nullptr;
+}
+
+// True if the range addresses contain the pair [LowerAddress, UpperAddress].
+bool LVRange::hasEntry(LVAddress LowerAddress, LVAddress UpperAddress) const {
+ for (const LVRangeEntry &RangeEntry : RangeEntries)
+ if (LowerAddress == RangeEntry.lower() &&
+ UpperAddress == RangeEntry.upper())
+ return true;
+ return false;
+}
+
+// Sort the range elements for the whole Compile Unit.
+void LVRange::sort() {
+ auto CompareRangeEntry = [](const LVRangeEntry &lhs,
+ const LVRangeEntry &rhs) -> bool {
+ if (lhs.lower() < rhs.lower())
+ return true;
+
+ // If the lower address is the same, use the upper address value in
+ // order to put first the smallest interval.
+ if (lhs.lower() == rhs.lower())
+ return lhs.upper() < rhs.upper();
+
+ return false;
+ };
+
+ // Sort the ranges using low address and range size.
+ std::stable_sort(RangeEntries.begin(), RangeEntries.end(), CompareRangeEntry);
+}
+
+void LVRange::print(raw_ostream &OS, bool Full) const {
+ size_t Indentation = 0;
+ for (const LVRangeEntry &RangeEntry : RangeEntries) {
+ LVScope *Scope = RangeEntry.scope();
+ Scope->printAttributes(OS, Full);
+ Indentation = options().indentationSize();
+ if (Indentation)
+ OS << " ";
+ OS << format("[0x%08x,0x%08x] ", RangeEntry.lower(), RangeEntry.upper())
+ << formattedKind(Scope->kind()) << " " << formattedName(Scope->getName())
+ << "\n";
+ }
+ printExtra(OS, Full);
+}