1*0b57cec5SDimitry Andric //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file implements LexicalScopes analysis.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric // This pass collects lexical scope information and maps machine instructions
12*0b57cec5SDimitry Andric // to respective lexical scopes.
13*0b57cec5SDimitry Andric //
14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
22*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
23*0b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
24*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
25*0b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
29*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
30*0b57cec5SDimitry Andric #include <cassert>
31*0b57cec5SDimitry Andric #include <string>
32*0b57cec5SDimitry Andric #include <tuple>
33*0b57cec5SDimitry Andric #include <utility>
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric using namespace llvm;
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric #define DEBUG_TYPE "lexicalscopes"
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric /// reset - Reset the instance so that it's prepared for another function.
reset()40*0b57cec5SDimitry Andric void LexicalScopes::reset() {
41*0b57cec5SDimitry Andric   MF = nullptr;
42*0b57cec5SDimitry Andric   CurrentFnLexicalScope = nullptr;
43*0b57cec5SDimitry Andric   LexicalScopeMap.clear();
44*0b57cec5SDimitry Andric   AbstractScopeMap.clear();
45*0b57cec5SDimitry Andric   InlinedLexicalScopeMap.clear();
46*0b57cec5SDimitry Andric   AbstractScopesList.clear();
47*0b57cec5SDimitry Andric   DominatedBlocks.clear();
48*0b57cec5SDimitry Andric }
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric /// initialize - Scan machine function and constuct lexical scope nest.
initialize(const MachineFunction & Fn)51*0b57cec5SDimitry Andric void LexicalScopes::initialize(const MachineFunction &Fn) {
52*0b57cec5SDimitry Andric   reset();
53*0b57cec5SDimitry Andric   // Don't attempt any lexical scope creation for a NoDebug compile unit.
54*0b57cec5SDimitry Andric   if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
55*0b57cec5SDimitry Andric       DICompileUnit::NoDebug)
56*0b57cec5SDimitry Andric     return;
57*0b57cec5SDimitry Andric   MF = &Fn;
58*0b57cec5SDimitry Andric   SmallVector<InsnRange, 4> MIRanges;
59*0b57cec5SDimitry Andric   DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
60*0b57cec5SDimitry Andric   extractLexicalScopes(MIRanges, MI2ScopeMap);
61*0b57cec5SDimitry Andric   if (CurrentFnLexicalScope) {
62*0b57cec5SDimitry Andric     constructScopeNest(CurrentFnLexicalScope);
63*0b57cec5SDimitry Andric     assignInstructionRanges(MIRanges, MI2ScopeMap);
64*0b57cec5SDimitry Andric   }
65*0b57cec5SDimitry Andric }
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
68*0b57cec5SDimitry Andric /// for the given machine function.
extractLexicalScopes(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)69*0b57cec5SDimitry Andric void LexicalScopes::extractLexicalScopes(
70*0b57cec5SDimitry Andric     SmallVectorImpl<InsnRange> &MIRanges,
71*0b57cec5SDimitry Andric     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
72*0b57cec5SDimitry Andric   // Scan each instruction and create scopes. First build working set of scopes.
73*0b57cec5SDimitry Andric   for (const auto &MBB : *MF) {
74*0b57cec5SDimitry Andric     const MachineInstr *RangeBeginMI = nullptr;
75*0b57cec5SDimitry Andric     const MachineInstr *PrevMI = nullptr;
76*0b57cec5SDimitry Andric     const DILocation *PrevDL = nullptr;
77*0b57cec5SDimitry Andric     for (const auto &MInsn : MBB) {
78*0b57cec5SDimitry Andric       // Ignore DBG_VALUE and similar instruction that do not contribute to any
79*0b57cec5SDimitry Andric       // instruction in the output.
80*0b57cec5SDimitry Andric       if (MInsn.isMetaInstruction())
81*0b57cec5SDimitry Andric         continue;
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric       // Check if instruction has valid location information.
84*0b57cec5SDimitry Andric       const DILocation *MIDL = MInsn.getDebugLoc();
85*0b57cec5SDimitry Andric       if (!MIDL) {
86*0b57cec5SDimitry Andric         PrevMI = &MInsn;
87*0b57cec5SDimitry Andric         continue;
88*0b57cec5SDimitry Andric       }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric       // If scope has not changed then skip this instruction.
91*0b57cec5SDimitry Andric       if (MIDL == PrevDL) {
92*0b57cec5SDimitry Andric         PrevMI = &MInsn;
93*0b57cec5SDimitry Andric         continue;
94*0b57cec5SDimitry Andric       }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric       if (RangeBeginMI) {
97*0b57cec5SDimitry Andric         // If we have already seen a beginning of an instruction range and
98*0b57cec5SDimitry Andric         // current instruction scope does not match scope of first instruction
99*0b57cec5SDimitry Andric         // in this range then create a new instruction range.
100*0b57cec5SDimitry Andric         InsnRange R(RangeBeginMI, PrevMI);
101*0b57cec5SDimitry Andric         MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
102*0b57cec5SDimitry Andric         MIRanges.push_back(R);
103*0b57cec5SDimitry Andric       }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric       // This is a beginning of a new instruction range.
106*0b57cec5SDimitry Andric       RangeBeginMI = &MInsn;
107*0b57cec5SDimitry Andric 
108*0b57cec5SDimitry Andric       // Reset previous markers.
109*0b57cec5SDimitry Andric       PrevMI = &MInsn;
110*0b57cec5SDimitry Andric       PrevDL = MIDL;
111*0b57cec5SDimitry Andric     }
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric     // Create last instruction range.
114*0b57cec5SDimitry Andric     if (RangeBeginMI && PrevMI && PrevDL) {
115*0b57cec5SDimitry Andric       InsnRange R(RangeBeginMI, PrevMI);
116*0b57cec5SDimitry Andric       MIRanges.push_back(R);
117*0b57cec5SDimitry Andric       MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
118*0b57cec5SDimitry Andric     }
119*0b57cec5SDimitry Andric   }
120*0b57cec5SDimitry Andric }
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric /// findLexicalScope - Find lexical scope, either regular or inlined, for the
123*0b57cec5SDimitry Andric /// given DebugLoc. Return NULL if not found.
findLexicalScope(const DILocation * DL)124*0b57cec5SDimitry Andric LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
125*0b57cec5SDimitry Andric   DILocalScope *Scope = DL->getScope();
126*0b57cec5SDimitry Andric   if (!Scope)
127*0b57cec5SDimitry Andric     return nullptr;
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric   // The scope that we were created with could have an extra file - which
130*0b57cec5SDimitry Andric   // isn't what we care about in this case.
131*0b57cec5SDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
132*0b57cec5SDimitry Andric 
133*0b57cec5SDimitry Andric   if (auto *IA = DL->getInlinedAt()) {
134*0b57cec5SDimitry Andric     auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
135*0b57cec5SDimitry Andric     return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
136*0b57cec5SDimitry Andric   }
137*0b57cec5SDimitry Andric   return findLexicalScope(Scope);
138*0b57cec5SDimitry Andric }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
141*0b57cec5SDimitry Andric /// not available then create new lexical scope.
getOrCreateLexicalScope(const DILocalScope * Scope,const DILocation * IA)142*0b57cec5SDimitry Andric LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
143*0b57cec5SDimitry Andric                                                      const DILocation *IA) {
144*0b57cec5SDimitry Andric   if (IA) {
145*0b57cec5SDimitry Andric     // Skip scopes inlined from a NoDebug compile unit.
146*0b57cec5SDimitry Andric     if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
147*0b57cec5SDimitry Andric         DICompileUnit::NoDebug)
148*0b57cec5SDimitry Andric       return getOrCreateLexicalScope(IA);
149*0b57cec5SDimitry Andric     // Create an abstract scope for inlined function.
150*0b57cec5SDimitry Andric     getOrCreateAbstractScope(Scope);
151*0b57cec5SDimitry Andric     // Create an inlined scope for inlined function.
152*0b57cec5SDimitry Andric     return getOrCreateInlinedScope(Scope, IA);
153*0b57cec5SDimitry Andric   }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric   return getOrCreateRegularScope(Scope);
156*0b57cec5SDimitry Andric }
157*0b57cec5SDimitry Andric 
158*0b57cec5SDimitry Andric /// getOrCreateRegularScope - Find or create a regular lexical scope.
159*0b57cec5SDimitry Andric LexicalScope *
getOrCreateRegularScope(const DILocalScope * Scope)160*0b57cec5SDimitry Andric LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
161*0b57cec5SDimitry Andric   assert(Scope && "Invalid Scope encoding!");
162*0b57cec5SDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
163*0b57cec5SDimitry Andric 
164*0b57cec5SDimitry Andric   auto I = LexicalScopeMap.find(Scope);
165*0b57cec5SDimitry Andric   if (I != LexicalScopeMap.end())
166*0b57cec5SDimitry Andric     return &I->second;
167*0b57cec5SDimitry Andric 
168*0b57cec5SDimitry Andric   // FIXME: Should the following dyn_cast be DILexicalBlock?
169*0b57cec5SDimitry Andric   LexicalScope *Parent = nullptr;
170*0b57cec5SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
171*0b57cec5SDimitry Andric     Parent = getOrCreateLexicalScope(Block->getScope());
172*0b57cec5SDimitry Andric   I = LexicalScopeMap.emplace(std::piecewise_construct,
173*0b57cec5SDimitry Andric                               std::forward_as_tuple(Scope),
174*0b57cec5SDimitry Andric                               std::forward_as_tuple(Parent, Scope, nullptr,
175*0b57cec5SDimitry Andric                                                     false)).first;
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric   if (!Parent) {
178*0b57cec5SDimitry Andric     assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
179*0b57cec5SDimitry Andric     assert(!CurrentFnLexicalScope);
180*0b57cec5SDimitry Andric     CurrentFnLexicalScope = &I->second;
181*0b57cec5SDimitry Andric   }
182*0b57cec5SDimitry Andric 
183*0b57cec5SDimitry Andric   return &I->second;
184*0b57cec5SDimitry Andric }
185*0b57cec5SDimitry Andric 
186*0b57cec5SDimitry Andric /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
187*0b57cec5SDimitry Andric LexicalScope *
getOrCreateInlinedScope(const DILocalScope * Scope,const DILocation * InlinedAt)188*0b57cec5SDimitry Andric LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
189*0b57cec5SDimitry Andric                                        const DILocation *InlinedAt) {
190*0b57cec5SDimitry Andric   assert(Scope && "Invalid Scope encoding!");
191*0b57cec5SDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
192*0b57cec5SDimitry Andric   std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
193*0b57cec5SDimitry Andric   auto I = InlinedLexicalScopeMap.find(P);
194*0b57cec5SDimitry Andric   if (I != InlinedLexicalScopeMap.end())
195*0b57cec5SDimitry Andric     return &I->second;
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric   LexicalScope *Parent;
198*0b57cec5SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
199*0b57cec5SDimitry Andric     Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
200*0b57cec5SDimitry Andric   else
201*0b57cec5SDimitry Andric     Parent = getOrCreateLexicalScope(InlinedAt);
202*0b57cec5SDimitry Andric 
203*0b57cec5SDimitry Andric   I = InlinedLexicalScopeMap
204*0b57cec5SDimitry Andric           .emplace(std::piecewise_construct, std::forward_as_tuple(P),
205*0b57cec5SDimitry Andric                    std::forward_as_tuple(Parent, Scope, InlinedAt, false))
206*0b57cec5SDimitry Andric           .first;
207*0b57cec5SDimitry Andric   return &I->second;
208*0b57cec5SDimitry Andric }
209*0b57cec5SDimitry Andric 
210*0b57cec5SDimitry Andric /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
211*0b57cec5SDimitry Andric LexicalScope *
getOrCreateAbstractScope(const DILocalScope * Scope)212*0b57cec5SDimitry Andric LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
213*0b57cec5SDimitry Andric   assert(Scope && "Invalid Scope encoding!");
214*0b57cec5SDimitry Andric   Scope = Scope->getNonLexicalBlockFileScope();
215*0b57cec5SDimitry Andric   auto I = AbstractScopeMap.find(Scope);
216*0b57cec5SDimitry Andric   if (I != AbstractScopeMap.end())
217*0b57cec5SDimitry Andric     return &I->second;
218*0b57cec5SDimitry Andric 
219*0b57cec5SDimitry Andric   // FIXME: Should the following isa be DILexicalBlock?
220*0b57cec5SDimitry Andric   LexicalScope *Parent = nullptr;
221*0b57cec5SDimitry Andric   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
222*0b57cec5SDimitry Andric     Parent = getOrCreateAbstractScope(Block->getScope());
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric   I = AbstractScopeMap.emplace(std::piecewise_construct,
225*0b57cec5SDimitry Andric                                std::forward_as_tuple(Scope),
226*0b57cec5SDimitry Andric                                std::forward_as_tuple(Parent, Scope,
227*0b57cec5SDimitry Andric                                                      nullptr, true)).first;
228*0b57cec5SDimitry Andric   if (isa<DISubprogram>(Scope))
229*0b57cec5SDimitry Andric     AbstractScopesList.push_back(&I->second);
230*0b57cec5SDimitry Andric   return &I->second;
231*0b57cec5SDimitry Andric }
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric /// constructScopeNest - Traverse the Scope tree depth-first, storing
234*0b57cec5SDimitry Andric /// traversal state in WorkStack and recording the depth-first
235*0b57cec5SDimitry Andric /// numbering (setDFSIn, setDFSOut) for edge classification.
constructScopeNest(LexicalScope * Scope)236*0b57cec5SDimitry Andric void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
237*0b57cec5SDimitry Andric   assert(Scope && "Unable to calculate scope dominance graph!");
238*0b57cec5SDimitry Andric   SmallVector<std::pair<LexicalScope *, size_t>, 4> WorkStack;
239*0b57cec5SDimitry Andric   WorkStack.push_back(std::make_pair(Scope, 0));
240*0b57cec5SDimitry Andric   unsigned Counter = 0;
241*0b57cec5SDimitry Andric   while (!WorkStack.empty()) {
242*0b57cec5SDimitry Andric     auto &ScopePosition = WorkStack.back();
243*0b57cec5SDimitry Andric     LexicalScope *WS = ScopePosition.first;
244*0b57cec5SDimitry Andric     size_t ChildNum = ScopePosition.second++;
245*0b57cec5SDimitry Andric     const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
246*0b57cec5SDimitry Andric     if (ChildNum < Children.size()) {
247*0b57cec5SDimitry Andric       auto &ChildScope = Children[ChildNum];
248*0b57cec5SDimitry Andric       WorkStack.push_back(std::make_pair(ChildScope, 0));
249*0b57cec5SDimitry Andric       ChildScope->setDFSIn(++Counter);
250*0b57cec5SDimitry Andric     } else {
251*0b57cec5SDimitry Andric       WorkStack.pop_back();
252*0b57cec5SDimitry Andric       WS->setDFSOut(++Counter);
253*0b57cec5SDimitry Andric     }
254*0b57cec5SDimitry Andric   }
255*0b57cec5SDimitry Andric }
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric /// assignInstructionRanges - Find ranges of instructions covered by each
258*0b57cec5SDimitry Andric /// lexical scope.
assignInstructionRanges(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)259*0b57cec5SDimitry Andric void LexicalScopes::assignInstructionRanges(
260*0b57cec5SDimitry Andric     SmallVectorImpl<InsnRange> &MIRanges,
261*0b57cec5SDimitry Andric     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
262*0b57cec5SDimitry Andric   LexicalScope *PrevLexicalScope = nullptr;
263*0b57cec5SDimitry Andric   for (const auto &R : MIRanges) {
264*0b57cec5SDimitry Andric     LexicalScope *S = MI2ScopeMap.lookup(R.first);
265*0b57cec5SDimitry Andric     assert(S && "Lost LexicalScope for a machine instruction!");
266*0b57cec5SDimitry Andric     if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
267*0b57cec5SDimitry Andric       PrevLexicalScope->closeInsnRange(S);
268*0b57cec5SDimitry Andric     S->openInsnRange(R.first);
269*0b57cec5SDimitry Andric     S->extendInsnRange(R.second);
270*0b57cec5SDimitry Andric     PrevLexicalScope = S;
271*0b57cec5SDimitry Andric   }
272*0b57cec5SDimitry Andric 
273*0b57cec5SDimitry Andric   if (PrevLexicalScope)
274*0b57cec5SDimitry Andric     PrevLexicalScope->closeInsnRange();
275*0b57cec5SDimitry Andric }
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric /// getMachineBasicBlocks - Populate given set using machine basic blocks which
278*0b57cec5SDimitry Andric /// have machine instructions that belong to lexical scope identified by
279*0b57cec5SDimitry Andric /// DebugLoc.
getMachineBasicBlocks(const DILocation * DL,SmallPtrSetImpl<const MachineBasicBlock * > & MBBs)280*0b57cec5SDimitry Andric void LexicalScopes::getMachineBasicBlocks(
281*0b57cec5SDimitry Andric     const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
282*0b57cec5SDimitry Andric   assert(MF && "Method called on a uninitialized LexicalScopes object!");
283*0b57cec5SDimitry Andric   MBBs.clear();
284*0b57cec5SDimitry Andric 
285*0b57cec5SDimitry Andric   LexicalScope *Scope = getOrCreateLexicalScope(DL);
286*0b57cec5SDimitry Andric   if (!Scope)
287*0b57cec5SDimitry Andric     return;
288*0b57cec5SDimitry Andric 
289*0b57cec5SDimitry Andric   if (Scope == CurrentFnLexicalScope) {
290*0b57cec5SDimitry Andric     for (const auto &MBB : *MF)
291*0b57cec5SDimitry Andric       MBBs.insert(&MBB);
292*0b57cec5SDimitry Andric     return;
293*0b57cec5SDimitry Andric   }
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric   // The scope ranges can cover multiple basic blocks in each span. Iterate over
296*0b57cec5SDimitry Andric   // all blocks (in the order they are in the function) until we reach the one
297*0b57cec5SDimitry Andric   // containing the end of the span.
298*0b57cec5SDimitry Andric   SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
299*0b57cec5SDimitry Andric   for (auto &R : InsnRanges)
300*0b57cec5SDimitry Andric     for (auto CurMBBIt = R.first->getParent()->getIterator(),
301*0b57cec5SDimitry Andric               EndBBIt = std::next(R.second->getParent()->getIterator());
302*0b57cec5SDimitry Andric          CurMBBIt != EndBBIt; CurMBBIt++)
303*0b57cec5SDimitry Andric       MBBs.insert(&*CurMBBIt);
304*0b57cec5SDimitry Andric }
305*0b57cec5SDimitry Andric 
dominates(const DILocation * DL,MachineBasicBlock * MBB)306*0b57cec5SDimitry Andric bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
307*0b57cec5SDimitry Andric   assert(MF && "Unexpected uninitialized LexicalScopes object!");
308*0b57cec5SDimitry Andric   LexicalScope *Scope = getOrCreateLexicalScope(DL);
309*0b57cec5SDimitry Andric   if (!Scope)
310*0b57cec5SDimitry Andric     return false;
311*0b57cec5SDimitry Andric 
312*0b57cec5SDimitry Andric   // Current function scope covers all basic blocks in the function.
313*0b57cec5SDimitry Andric   if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
314*0b57cec5SDimitry Andric     return true;
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric   // Fetch all the blocks in DLs scope. Because the range / block list also
317*0b57cec5SDimitry Andric   // contain any subscopes, any instruction that DL dominates can be found in
318*0b57cec5SDimitry Andric   // the block set.
319*0b57cec5SDimitry Andric   //
320*0b57cec5SDimitry Andric   // Cache the set of fetched blocks to avoid repeatedly recomputing the set in
321*0b57cec5SDimitry Andric   // the LiveDebugValues pass.
322*0b57cec5SDimitry Andric   std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL];
323*0b57cec5SDimitry Andric   if (!Set) {
324*0b57cec5SDimitry Andric     Set = std::make_unique<BlockSetT>();
325*0b57cec5SDimitry Andric     getMachineBasicBlocks(DL, *Set);
326*0b57cec5SDimitry Andric   }
327*0b57cec5SDimitry Andric   return Set->contains(MBB);
328*0b57cec5SDimitry Andric }
329*0b57cec5SDimitry Andric 
330*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump(unsigned Indent) const331*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
332*0b57cec5SDimitry Andric   raw_ostream &err = dbgs();
333*0b57cec5SDimitry Andric   err.indent(Indent);
334*0b57cec5SDimitry Andric   err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
335*0b57cec5SDimitry Andric   const MDNode *N = Desc;
336*0b57cec5SDimitry Andric   err.indent(Indent);
337*0b57cec5SDimitry Andric   N->dump();
338   if (AbstractScope)
339     err << std::string(Indent, ' ') << "Abstract Scope\n";
340 
341   if (!Children.empty())
342     err << std::string(Indent + 2, ' ') << "Children ...\n";
343   for (unsigned i = 0, e = Children.size(); i != e; ++i)
344     if (Children[i] != this)
345       Children[i]->dump(Indent + 2);
346 }
347 #endif
348