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