| //===-- 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" | |
| #include "llvm/Support/FormatVariadic.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() << formatv("Searching: {0:x8}\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() << formatv("[{0:x8},{1:x8}] ", 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. | |
| llvm::stable_sort(RangeEntries, 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 << formatv("[{0:x8},{1:x8}] ", RangeEntry.lower(), RangeEntry.upper()) | |
| << formattedKind(Scope->kind()) << " " << formattedName(Scope->getName()) | |
| << "\n"; | |
| } | |
| printExtra(OS, Full); | |
| } |