1*3c397c90SCarlos Alberto Enciso //===-- LVRange.cpp -------------------------------------------------------===//
2*3c397c90SCarlos Alberto Enciso //
3*3c397c90SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*3c397c90SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information.
5*3c397c90SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*3c397c90SCarlos Alberto Enciso //
7*3c397c90SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
8*3c397c90SCarlos Alberto Enciso //
9*3c397c90SCarlos Alberto Enciso // This implements the LVRange class.
10*3c397c90SCarlos Alberto Enciso //
11*3c397c90SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
12*3c397c90SCarlos Alberto Enciso
13*3c397c90SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
14*3c397c90SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
15*3c397c90SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
16*3c397c90SCarlos Alberto Enciso
17*3c397c90SCarlos Alberto Enciso using namespace llvm;
18*3c397c90SCarlos Alberto Enciso using namespace llvm::logicalview;
19*3c397c90SCarlos Alberto Enciso
20*3c397c90SCarlos Alberto Enciso #define DEBUG_TYPE "Range"
21*3c397c90SCarlos Alberto Enciso
startSearch()22*3c397c90SCarlos Alberto Enciso void LVRange::startSearch() {
23*3c397c90SCarlos Alberto Enciso RangesTree.clear();
24*3c397c90SCarlos Alberto Enciso
25*3c397c90SCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << "\nRanges Tree entries:\n"; });
26*3c397c90SCarlos Alberto Enciso
27*3c397c90SCarlos Alberto Enciso // Traverse the ranges and store them into the interval tree.
28*3c397c90SCarlos Alberto Enciso for (LVRangeEntry &RangeEntry : RangeEntries) {
29*3c397c90SCarlos Alberto Enciso LLVM_DEBUG({
30*3c397c90SCarlos Alberto Enciso LVScope *Scope = RangeEntry.scope();
31*3c397c90SCarlos Alberto Enciso dbgs() << "Scope: " << format_decimal(Scope->getLevel(), 5) << " "
32*3c397c90SCarlos Alberto Enciso << "Range: [" << hexValue(RangeEntry.lower()) << ":"
33*3c397c90SCarlos Alberto Enciso << hexValue(RangeEntry.upper()) << "]\n";
34*3c397c90SCarlos Alberto Enciso });
35*3c397c90SCarlos Alberto Enciso
36*3c397c90SCarlos Alberto Enciso RangesTree.insert(RangeEntry.lower(), RangeEntry.upper(),
37*3c397c90SCarlos Alberto Enciso RangeEntry.scope());
38*3c397c90SCarlos Alberto Enciso }
39*3c397c90SCarlos Alberto Enciso
40*3c397c90SCarlos Alberto Enciso // Create the interval tree.
41*3c397c90SCarlos Alberto Enciso RangesTree.create();
42*3c397c90SCarlos Alberto Enciso
43*3c397c90SCarlos Alberto Enciso LLVM_DEBUG({
44*3c397c90SCarlos Alberto Enciso dbgs() << "\nRanges Tree:\n";
45*3c397c90SCarlos Alberto Enciso RangesTree.print(dbgs());
46*3c397c90SCarlos Alberto Enciso });
47*3c397c90SCarlos Alberto Enciso }
48*3c397c90SCarlos Alberto Enciso
49*3c397c90SCarlos Alberto Enciso // Add the pair in an ascending order, with the smallest ranges at the
50*3c397c90SCarlos Alberto Enciso // start; in that way, enclosing scopes ranges are at the end of the
51*3c397c90SCarlos Alberto Enciso // list; we assume that low <= high.
addEntry(LVScope * Scope,LVAddress LowerAddress,LVAddress UpperAddress)52*3c397c90SCarlos Alberto Enciso void LVRange::addEntry(LVScope *Scope, LVAddress LowerAddress,
53*3c397c90SCarlos Alberto Enciso LVAddress UpperAddress) {
54*3c397c90SCarlos Alberto Enciso // We assume the low <= high.
55*3c397c90SCarlos Alberto Enciso if (LowerAddress > UpperAddress)
56*3c397c90SCarlos Alberto Enciso std::swap(LowerAddress, UpperAddress);
57*3c397c90SCarlos Alberto Enciso
58*3c397c90SCarlos Alberto Enciso // Record the lowest and highest seen addresses.
59*3c397c90SCarlos Alberto Enciso if (LowerAddress < Lower)
60*3c397c90SCarlos Alberto Enciso Lower = LowerAddress;
61*3c397c90SCarlos Alberto Enciso if (UpperAddress > Upper)
62*3c397c90SCarlos Alberto Enciso Upper = UpperAddress;
63*3c397c90SCarlos Alberto Enciso
64*3c397c90SCarlos Alberto Enciso // Just add the scope and range pair, in no particular order.
65*3c397c90SCarlos Alberto Enciso RangeEntries.emplace_back(LowerAddress, UpperAddress, Scope);
66*3c397c90SCarlos Alberto Enciso }
67*3c397c90SCarlos Alberto Enciso
addEntry(LVScope * Scope)68*3c397c90SCarlos Alberto Enciso void LVRange::addEntry(LVScope *Scope) {
69*3c397c90SCarlos Alberto Enciso assert(Scope && "Scope must not be nullptr");
70*3c397c90SCarlos Alberto Enciso // Traverse the ranges and update the ranges set only if the ranges
71*3c397c90SCarlos Alberto Enciso // values are not already recorded.
72*3c397c90SCarlos Alberto Enciso if (const LVLocations *Locations = Scope->getRanges())
73*3c397c90SCarlos Alberto Enciso for (const LVLocation *Location : *Locations) {
74*3c397c90SCarlos Alberto Enciso LVAddress LowPC = Location->getLowerAddress();
75*3c397c90SCarlos Alberto Enciso LVAddress HighPC = Location->getUpperAddress();
76*3c397c90SCarlos Alberto Enciso if (!hasEntry(LowPC, HighPC))
77*3c397c90SCarlos Alberto Enciso // Add the pair of addresses.
78*3c397c90SCarlos Alberto Enciso addEntry(Scope, LowPC, HighPC);
79*3c397c90SCarlos Alberto Enciso }
80*3c397c90SCarlos Alberto Enciso }
81*3c397c90SCarlos Alberto Enciso
82*3c397c90SCarlos Alberto Enciso // Get the scope associated with the input address.
getEntry(LVAddress Address) const83*3c397c90SCarlos Alberto Enciso LVScope *LVRange::getEntry(LVAddress Address) const {
84*3c397c90SCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << format("Searching: 0x%08x\nFound: ", Address); });
85*3c397c90SCarlos Alberto Enciso
86*3c397c90SCarlos Alberto Enciso LVScope *Target = nullptr;
87*3c397c90SCarlos Alberto Enciso LVLevel TargetLevel = 0;
88*3c397c90SCarlos Alberto Enciso LVLevel Level = 0;
89*3c397c90SCarlos Alberto Enciso LVScope *Scope = nullptr;
90*3c397c90SCarlos Alberto Enciso for (LVRangesTree::find_iterator Iter = RangesTree.find(Address),
91*3c397c90SCarlos Alberto Enciso End = RangesTree.find_end();
92*3c397c90SCarlos Alberto Enciso Iter != End; ++Iter) {
93*3c397c90SCarlos Alberto Enciso LLVM_DEBUG(
94*3c397c90SCarlos Alberto Enciso { dbgs() << format("[0x%08x,0x%08x] ", Iter->left(), Iter->right()); });
95*3c397c90SCarlos Alberto Enciso Scope = Iter->value();
96*3c397c90SCarlos Alberto Enciso Level = Scope->getLevel();
97*3c397c90SCarlos Alberto Enciso if (Level > TargetLevel) {
98*3c397c90SCarlos Alberto Enciso TargetLevel = Level;
99*3c397c90SCarlos Alberto Enciso Target = Scope;
100*3c397c90SCarlos Alberto Enciso }
101*3c397c90SCarlos Alberto Enciso }
102*3c397c90SCarlos Alberto Enciso
103*3c397c90SCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << (Scope ? "\n" : "None\n"); });
104*3c397c90SCarlos Alberto Enciso
105*3c397c90SCarlos Alberto Enciso return Target;
106*3c397c90SCarlos Alberto Enciso }
107*3c397c90SCarlos Alberto Enciso
108*3c397c90SCarlos Alberto Enciso // Find the associated Scope for the given ranges values.
getEntry(LVAddress LowerAddress,LVAddress UpperAddress) const109*3c397c90SCarlos Alberto Enciso LVScope *LVRange::getEntry(LVAddress LowerAddress,
110*3c397c90SCarlos Alberto Enciso LVAddress UpperAddress) const {
111*3c397c90SCarlos Alberto Enciso for (const LVRangeEntry &RangeEntry : RangeEntries)
112*3c397c90SCarlos Alberto Enciso if (LowerAddress >= RangeEntry.lower() && UpperAddress < RangeEntry.upper())
113*3c397c90SCarlos Alberto Enciso return RangeEntry.scope();
114*3c397c90SCarlos Alberto Enciso return nullptr;
115*3c397c90SCarlos Alberto Enciso }
116*3c397c90SCarlos Alberto Enciso
117*3c397c90SCarlos Alberto Enciso // True if the range addresses contain the pair [LowerAddress, UpperAddress].
hasEntry(LVAddress LowerAddress,LVAddress UpperAddress) const118*3c397c90SCarlos Alberto Enciso bool LVRange::hasEntry(LVAddress LowerAddress, LVAddress UpperAddress) const {
119*3c397c90SCarlos Alberto Enciso for (const LVRangeEntry &RangeEntry : RangeEntries)
120*3c397c90SCarlos Alberto Enciso if (LowerAddress == RangeEntry.lower() &&
121*3c397c90SCarlos Alberto Enciso UpperAddress == RangeEntry.upper())
122*3c397c90SCarlos Alberto Enciso return true;
123*3c397c90SCarlos Alberto Enciso return false;
124*3c397c90SCarlos Alberto Enciso }
125*3c397c90SCarlos Alberto Enciso
126*3c397c90SCarlos Alberto Enciso // Sort the range elements for the whole Compile Unit.
sort()127*3c397c90SCarlos Alberto Enciso void LVRange::sort() {
128*3c397c90SCarlos Alberto Enciso auto CompareRangeEntry = [](const LVRangeEntry &lhs,
129*3c397c90SCarlos Alberto Enciso const LVRangeEntry &rhs) -> bool {
130*3c397c90SCarlos Alberto Enciso if (lhs.lower() < rhs.lower())
131*3c397c90SCarlos Alberto Enciso return true;
132*3c397c90SCarlos Alberto Enciso
133*3c397c90SCarlos Alberto Enciso // If the lower address is the same, use the upper address value in
134*3c397c90SCarlos Alberto Enciso // order to put first the smallest interval.
135*3c397c90SCarlos Alberto Enciso if (lhs.lower() == rhs.lower())
136*3c397c90SCarlos Alberto Enciso return lhs.upper() < rhs.upper();
137*3c397c90SCarlos Alberto Enciso
138*3c397c90SCarlos Alberto Enciso return false;
139*3c397c90SCarlos Alberto Enciso };
140*3c397c90SCarlos Alberto Enciso
141*3c397c90SCarlos Alberto Enciso // Sort the ranges using low address and range size.
142*3c397c90SCarlos Alberto Enciso std::stable_sort(RangeEntries.begin(), RangeEntries.end(), CompareRangeEntry);
143*3c397c90SCarlos Alberto Enciso }
144*3c397c90SCarlos Alberto Enciso
print(raw_ostream & OS,bool Full) const145*3c397c90SCarlos Alberto Enciso void LVRange::print(raw_ostream &OS, bool Full) const {
146*3c397c90SCarlos Alberto Enciso size_t Indentation = 0;
147*3c397c90SCarlos Alberto Enciso for (const LVRangeEntry &RangeEntry : RangeEntries) {
148*3c397c90SCarlos Alberto Enciso LVScope *Scope = RangeEntry.scope();
149*3c397c90SCarlos Alberto Enciso Scope->printAttributes(OS, Full);
150*3c397c90SCarlos Alberto Enciso Indentation = options().indentationSize();
151*3c397c90SCarlos Alberto Enciso if (Indentation)
152*3c397c90SCarlos Alberto Enciso OS << " ";
153*3c397c90SCarlos Alberto Enciso OS << format("[0x%08x,0x%08x] ", RangeEntry.lower(), RangeEntry.upper())
154*3c397c90SCarlos Alberto Enciso << formattedKind(Scope->kind()) << " " << formattedName(Scope->getName())
155*3c397c90SCarlos Alberto Enciso << "\n";
156*3c397c90SCarlos Alberto Enciso }
157*3c397c90SCarlos Alberto Enciso printExtra(OS, Full);
158*3c397c90SCarlos Alberto Enciso }
159