159 lines
5.2 KiB
C++
159 lines
5.2 KiB
C++
//===-- 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);
|
|
}
|