xref: /llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVRange.cpp (revision 3c397c90c18377b1996783b994fba42d0b1649a2)
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