1e1649c31SDevang Patel //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
2e1649c31SDevang Patel //
3e1649c31SDevang Patel //                     The LLVM Compiler Infrastructure
4e1649c31SDevang Patel //
5e1649c31SDevang Patel // This file is distributed under the University of Illinois Open Source
6e1649c31SDevang Patel // License. See LICENSE.TXT for details.
7e1649c31SDevang Patel //
8e1649c31SDevang Patel //===----------------------------------------------------------------------===//
9e1649c31SDevang Patel //
10e1649c31SDevang Patel // This file implements LexicalScopes analysis.
11e1649c31SDevang Patel //
12e1649c31SDevang Patel // This pass collects lexical scope information and maps machine instructions
13e1649c31SDevang Patel // to respective lexical scopes.
14e1649c31SDevang Patel //
15e1649c31SDevang Patel //===----------------------------------------------------------------------===//
16e1649c31SDevang Patel 
17*5db84df7SEugene Zelenko #include "llvm/ADT/DenseMap.h"
18*5db84df7SEugene Zelenko #include "llvm/ADT/SmallVector.h"
19e1649c31SDevang Patel #include "llvm/CodeGen/LexicalScopes.h"
20*5db84df7SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h"
21e1649c31SDevang Patel #include "llvm/CodeGen/MachineFunction.h"
22e1649c31SDevang Patel #include "llvm/CodeGen/MachineInstr.h"
23*5db84df7SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h"
24*5db84df7SEugene Zelenko #include "llvm/IR/Metadata.h"
25*5db84df7SEugene Zelenko #include "llvm/Support/Casting.h"
26*5db84df7SEugene Zelenko #include "llvm/Support/Compiler.h"
27e1649c31SDevang Patel #include "llvm/Support/Debug.h"
28*5db84df7SEugene Zelenko #include "llvm/Support/raw_ostream.h"
29*5db84df7SEugene Zelenko #include <cassert>
30*5db84df7SEugene Zelenko #include <string>
31*5db84df7SEugene Zelenko #include <tuple>
32*5db84df7SEugene Zelenko #include <utility>
33*5db84df7SEugene Zelenko 
34e1649c31SDevang Patel using namespace llvm;
35e1649c31SDevang Patel 
361b9dde08SChandler Carruth #define DEBUG_TYPE "lexicalscopes"
371b9dde08SChandler Carruth 
38b7dee8a6SEric Christopher /// reset - Reset the instance so that it's prepared for another function.
39b7dee8a6SEric Christopher void LexicalScopes::reset() {
40c0196b1bSCraig Topper   MF = nullptr;
41c0196b1bSCraig Topper   CurrentFnLexicalScope = nullptr;
422f143e0cSDavid Blaikie   LexicalScopeMap.clear();
432f143e0cSDavid Blaikie   AbstractScopeMap.clear();
44e1649c31SDevang Patel   InlinedLexicalScopeMap.clear();
45e1649c31SDevang Patel   AbstractScopesList.clear();
46e1649c31SDevang Patel }
47e1649c31SDevang Patel 
48e1649c31SDevang Patel /// initialize - Scan machine function and constuct lexical scope nest.
49e1649c31SDevang Patel void LexicalScopes::initialize(const MachineFunction &Fn) {
5076b5b749STeresa Johnson   // Don't attempt any lexical scope creation for a NoDebug compile unit.
5176b5b749STeresa Johnson   if (Fn.getFunction()->getSubprogram()->getUnit()->getEmissionKind() ==
5276b5b749STeresa Johnson       DICompileUnit::NoDebug)
5376b5b749STeresa Johnson     return;
54b7dee8a6SEric Christopher   reset();
55e1649c31SDevang Patel   MF = &Fn;
56e1649c31SDevang Patel   SmallVector<InsnRange, 4> MIRanges;
57e1649c31SDevang Patel   DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
58e1649c31SDevang Patel   extractLexicalScopes(MIRanges, MI2ScopeMap);
59e1649c31SDevang Patel   if (CurrentFnLexicalScope) {
60e1649c31SDevang Patel     constructScopeNest(CurrentFnLexicalScope);
61e1649c31SDevang Patel     assignInstructionRanges(MIRanges, MI2ScopeMap);
62e1649c31SDevang Patel   }
63e1649c31SDevang Patel }
64e1649c31SDevang Patel 
65e1649c31SDevang Patel /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
66e1649c31SDevang Patel /// for the given machine function.
676211e4b9SEric Christopher void LexicalScopes::extractLexicalScopes(
686211e4b9SEric Christopher     SmallVectorImpl<InsnRange> &MIRanges,
69e1649c31SDevang Patel     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
70e1649c31SDevang Patel   // Scan each instruction and create scopes. First build working set of scopes.
7141b977dfSAlexey Samsonov   for (const auto &MBB : *MF) {
72c0196b1bSCraig Topper     const MachineInstr *RangeBeginMI = nullptr;
73c0196b1bSCraig Topper     const MachineInstr *PrevMI = nullptr;
74a9308c49SDuncan P. N. Exon Smith     const DILocation *PrevDL = nullptr;
75f74bde67SAlexey Samsonov     for (const auto &MInsn : MBB) {
76e1649c31SDevang Patel       // Check if instruction has valid location information.
77a9308c49SDuncan P. N. Exon Smith       const DILocation *MIDL = MInsn.getDebugLoc();
789dffcd04SDuncan P. N. Exon Smith       if (!MIDL) {
79f74bde67SAlexey Samsonov         PrevMI = &MInsn;
80e1649c31SDevang Patel         continue;
81e1649c31SDevang Patel       }
82e1649c31SDevang Patel 
83e1649c31SDevang Patel       // If scope has not changed then skip this instruction.
84e1649c31SDevang Patel       if (MIDL == PrevDL) {
85f74bde67SAlexey Samsonov         PrevMI = &MInsn;
86e1649c31SDevang Patel         continue;
87e1649c31SDevang Patel       }
88e1649c31SDevang Patel 
89e1649c31SDevang Patel       // Ignore DBG_VALUE. It does not contribute to any instruction in output.
90f74bde67SAlexey Samsonov       if (MInsn.isDebugValue())
91e1649c31SDevang Patel         continue;
92e1649c31SDevang Patel 
93e1649c31SDevang Patel       if (RangeBeginMI) {
94e1649c31SDevang Patel         // If we have already seen a beginning of an instruction range and
95e1649c31SDevang Patel         // current instruction scope does not match scope of first instruction
96e1649c31SDevang Patel         // in this range then create a new instruction range.
97e1649c31SDevang Patel         InsnRange R(RangeBeginMI, PrevMI);
98e1649c31SDevang Patel         MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
99e1649c31SDevang Patel         MIRanges.push_back(R);
100e1649c31SDevang Patel       }
101e1649c31SDevang Patel 
102e1649c31SDevang Patel       // This is a beginning of a new instruction range.
103f74bde67SAlexey Samsonov       RangeBeginMI = &MInsn;
104e1649c31SDevang Patel 
105e1649c31SDevang Patel       // Reset previous markers.
106f74bde67SAlexey Samsonov       PrevMI = &MInsn;
107e1649c31SDevang Patel       PrevDL = MIDL;
108e1649c31SDevang Patel     }
109e1649c31SDevang Patel 
110e1649c31SDevang Patel     // Create last instruction range.
1119dffcd04SDuncan P. N. Exon Smith     if (RangeBeginMI && PrevMI && PrevDL) {
112e1649c31SDevang Patel       InsnRange R(RangeBeginMI, PrevMI);
113e1649c31SDevang Patel       MIRanges.push_back(R);
114e1649c31SDevang Patel       MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
115e1649c31SDevang Patel     }
116e1649c31SDevang Patel   }
117e1649c31SDevang Patel }
118e1649c31SDevang Patel 
119e1649c31SDevang Patel /// findLexicalScope - Find lexical scope, either regular or inlined, for the
120e1649c31SDevang Patel /// given DebugLoc. Return NULL if not found.
121a9308c49SDuncan P. N. Exon Smith LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
122a9308c49SDuncan P. N. Exon Smith   DILocalScope *Scope = DL->getScope();
1236211e4b9SEric Christopher   if (!Scope)
124c0196b1bSCraig Topper     return nullptr;
1256647b830SEric Christopher 
1266647b830SEric Christopher   // The scope that we were created with could have an extra file - which
1276647b830SEric Christopher   // isn't what we care about in this case.
128a5ba9914SAmjad Aboud   Scope = Scope->getNonLexicalBlockFileScope();
1296647b830SEric Christopher 
1305a227fffSDuncan P. N. Exon Smith   if (auto *IA = DL->getInlinedAt()) {
1319b8c8cdaSDavid Blaikie     auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
1329b8c8cdaSDavid Blaikie     return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
1339b8c8cdaSDavid Blaikie   }
1342f143e0cSDavid Blaikie   return findLexicalScope(Scope);
135e1649c31SDevang Patel }
136e1649c31SDevang Patel 
137e1649c31SDevang Patel /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
138e1649c31SDevang Patel /// not available then create new lexical scope.
139a9308c49SDuncan P. N. Exon Smith LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
140a9308c49SDuncan P. N. Exon Smith                                                      const DILocation *IA) {
14182eba746SDuncan P. N. Exon Smith   if (IA) {
14276b5b749STeresa Johnson     // Skip scopes inlined from a NoDebug compile unit.
14376b5b749STeresa Johnson     if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
14476b5b749STeresa Johnson         DICompileUnit::NoDebug)
14576b5b749STeresa Johnson       return getOrCreateLexicalScope(IA);
146e1649c31SDevang Patel     // Create an abstract scope for inlined function.
147e1649c31SDevang Patel     getOrCreateAbstractScope(Scope);
148e1649c31SDevang Patel     // Create an inlined scope for inlined function.
14982eba746SDuncan P. N. Exon Smith     return getOrCreateInlinedScope(Scope, IA);
150e1649c31SDevang Patel   }
151e1649c31SDevang Patel 
152e1649c31SDevang Patel   return getOrCreateRegularScope(Scope);
153e1649c31SDevang Patel }
154e1649c31SDevang Patel 
155e1649c31SDevang Patel /// getOrCreateRegularScope - Find or create a regular lexical scope.
15633af7a8fSDuncan P. N. Exon Smith LexicalScope *
157a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
158a5ba9914SAmjad Aboud   assert(Scope && "Invalid Scope encoding!");
159a5ba9914SAmjad Aboud   Scope = Scope->getNonLexicalBlockFileScope();
1606647b830SEric Christopher 
1612f143e0cSDavid Blaikie   auto I = LexicalScopeMap.find(Scope);
1622f143e0cSDavid Blaikie   if (I != LexicalScopeMap.end())
1632f143e0cSDavid Blaikie     return &I->second;
164e1649c31SDevang Patel 
165a9308c49SDuncan P. N. Exon Smith   // FIXME: Should the following dyn_cast be DILexicalBlock?
166c0196b1bSCraig Topper   LexicalScope *Parent = nullptr;
167a9308c49SDuncan P. N. Exon Smith   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
16882eba746SDuncan P. N. Exon Smith     Parent = getOrCreateLexicalScope(Block->getScope());
169f17583eeSAaron Ballman   I = LexicalScopeMap.emplace(std::piecewise_construct,
170f17583eeSAaron Ballman                               std::forward_as_tuple(Scope),
17133af7a8fSDuncan P. N. Exon Smith                               std::forward_as_tuple(Parent, Scope, nullptr,
17233af7a8fSDuncan P. N. Exon Smith                                                     false)).first;
1732f143e0cSDavid Blaikie 
1743dfe4788SDavid Blaikie   if (!Parent) {
175a9308c49SDuncan P. N. Exon Smith     assert(cast<DISubprogram>(Scope)->describes(MF->getFunction()));
1763dfe4788SDavid Blaikie     assert(!CurrentFnLexicalScope);
1772f143e0cSDavid Blaikie     CurrentFnLexicalScope = &I->second;
1783dfe4788SDavid Blaikie   }
179e1649c31SDevang Patel 
1802f143e0cSDavid Blaikie   return &I->second;
181e1649c31SDevang Patel }
182e1649c31SDevang Patel 
183e1649c31SDevang Patel /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
18433af7a8fSDuncan P. N. Exon Smith LexicalScope *
185a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
186a9308c49SDuncan P. N. Exon Smith                                        const DILocation *InlinedAt) {
187a5ba9914SAmjad Aboud   assert(Scope && "Invalid Scope encoding!");
188a5ba9914SAmjad Aboud   Scope = Scope->getNonLexicalBlockFileScope();
189a9308c49SDuncan P. N. Exon Smith   std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
1909b8c8cdaSDavid Blaikie   auto I = InlinedLexicalScopeMap.find(P);
1919b8c8cdaSDavid Blaikie   if (I != InlinedLexicalScopeMap.end())
1922f143e0cSDavid Blaikie     return &I->second;
193e1649c31SDevang Patel 
1949b8c8cdaSDavid Blaikie   LexicalScope *Parent;
195a9308c49SDuncan P. N. Exon Smith   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
19633af7a8fSDuncan P. N. Exon Smith     Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
1979b8c8cdaSDavid Blaikie   else
19833af7a8fSDuncan P. N. Exon Smith     Parent = getOrCreateLexicalScope(InlinedAt);
1999b8c8cdaSDavid Blaikie 
20014303d18SEric Christopher   I = InlinedLexicalScopeMap
20114303d18SEric Christopher           .emplace(std::piecewise_construct, std::forward_as_tuple(P),
20214303d18SEric Christopher                    std::forward_as_tuple(Parent, Scope, InlinedAt, false))
203f17583eeSAaron Ballman           .first;
2042f143e0cSDavid Blaikie   return &I->second;
205e1649c31SDevang Patel }
206e1649c31SDevang Patel 
207e1649c31SDevang Patel /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
20833af7a8fSDuncan P. N. Exon Smith LexicalScope *
209a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
21033af7a8fSDuncan P. N. Exon Smith   assert(Scope && "Invalid Scope encoding!");
211a5ba9914SAmjad Aboud   Scope = Scope->getNonLexicalBlockFileScope();
212ea862267SDavid Blaikie   auto I = AbstractScopeMap.find(Scope);
2132f143e0cSDavid Blaikie   if (I != AbstractScopeMap.end())
2142f143e0cSDavid Blaikie     return &I->second;
215e1649c31SDevang Patel 
216a9308c49SDuncan P. N. Exon Smith   // FIXME: Should the following isa be DILexicalBlock?
217c0196b1bSCraig Topper   LexicalScope *Parent = nullptr;
218a9308c49SDuncan P. N. Exon Smith   if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
21933af7a8fSDuncan P. N. Exon Smith     Parent = getOrCreateAbstractScope(Block->getScope());
22033af7a8fSDuncan P. N. Exon Smith 
2212f143e0cSDavid Blaikie   I = AbstractScopeMap.emplace(std::piecewise_construct,
222ea862267SDavid Blaikie                                std::forward_as_tuple(Scope),
223ea862267SDavid Blaikie                                std::forward_as_tuple(Parent, Scope,
2242f143e0cSDavid Blaikie                                                      nullptr, true)).first;
225a9308c49SDuncan P. N. Exon Smith   if (isa<DISubprogram>(Scope))
2262f143e0cSDavid Blaikie     AbstractScopesList.push_back(&I->second);
2272f143e0cSDavid Blaikie   return &I->second;
228e1649c31SDevang Patel }
229e1649c31SDevang Patel 
230e1649c31SDevang Patel /// constructScopeNest
231e1649c31SDevang Patel void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
232e1649c31SDevang Patel   assert(Scope && "Unable to calculate scope dominance graph!");
233e1649c31SDevang Patel   SmallVector<LexicalScope *, 4> WorkStack;
234e1649c31SDevang Patel   WorkStack.push_back(Scope);
235e1649c31SDevang Patel   unsigned Counter = 0;
236e1649c31SDevang Patel   while (!WorkStack.empty()) {
237e1649c31SDevang Patel     LexicalScope *WS = WorkStack.back();
23880170e54SCraig Topper     const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
239e1649c31SDevang Patel     bool visitedChildren = false;
24016b2ace0SAdrian Prantl     for (auto &ChildScope : Children)
241e1649c31SDevang Patel       if (!ChildScope->getDFSOut()) {
242e1649c31SDevang Patel         WorkStack.push_back(ChildScope);
243e1649c31SDevang Patel         visitedChildren = true;
244e1649c31SDevang Patel         ChildScope->setDFSIn(++Counter);
245e1649c31SDevang Patel         break;
246e1649c31SDevang Patel       }
247e1649c31SDevang Patel     if (!visitedChildren) {
248e1649c31SDevang Patel       WorkStack.pop_back();
249e1649c31SDevang Patel       WS->setDFSOut(++Counter);
250e1649c31SDevang Patel     }
251e1649c31SDevang Patel   }
252e1649c31SDevang Patel }
253e1649c31SDevang Patel 
254784077ebSDevang Patel /// assignInstructionRanges - Find ranges of instructions covered by each
255784077ebSDevang Patel /// lexical scope.
2566211e4b9SEric Christopher void LexicalScopes::assignInstructionRanges(
2576211e4b9SEric Christopher     SmallVectorImpl<InsnRange> &MIRanges,
2586211e4b9SEric Christopher     DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
259c0196b1bSCraig Topper   LexicalScope *PrevLexicalScope = nullptr;
26016b2ace0SAdrian Prantl   for (const auto &R : MIRanges) {
261e1649c31SDevang Patel     LexicalScope *S = MI2ScopeMap.lookup(R.first);
262e1649c31SDevang Patel     assert(S && "Lost LexicalScope for a machine instruction!");
263e1649c31SDevang Patel     if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
264e1649c31SDevang Patel       PrevLexicalScope->closeInsnRange(S);
265e1649c31SDevang Patel     S->openInsnRange(R.first);
266e1649c31SDevang Patel     S->extendInsnRange(R.second);
267e1649c31SDevang Patel     PrevLexicalScope = S;
268e1649c31SDevang Patel   }
269e1649c31SDevang Patel 
270e1649c31SDevang Patel   if (PrevLexicalScope)
271e1649c31SDevang Patel     PrevLexicalScope->closeInsnRange();
272e1649c31SDevang Patel }
273e1649c31SDevang Patel 
274e1649c31SDevang Patel /// getMachineBasicBlocks - Populate given set using machine basic blocks which
275e1649c31SDevang Patel /// have machine instructions that belong to lexical scope identified by
276e1649c31SDevang Patel /// DebugLoc.
2776211e4b9SEric Christopher void LexicalScopes::getMachineBasicBlocks(
278a9308c49SDuncan P. N. Exon Smith     const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
279e1649c31SDevang Patel   MBBs.clear();
280e1649c31SDevang Patel   LexicalScope *Scope = getOrCreateLexicalScope(DL);
281e1649c31SDevang Patel   if (!Scope)
282e1649c31SDevang Patel     return;
283e1649c31SDevang Patel 
284db4374a2SDevang Patel   if (Scope == CurrentFnLexicalScope) {
28541b977dfSAlexey Samsonov     for (const auto &MBB : *MF)
28641b977dfSAlexey Samsonov       MBBs.insert(&MBB);
287db4374a2SDevang Patel     return;
288db4374a2SDevang Patel   }
289db4374a2SDevang Patel 
29080170e54SCraig Topper   SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
29116b2ace0SAdrian Prantl   for (auto &R : InsnRanges)
292e1649c31SDevang Patel     MBBs.insert(R.first->getParent());
293e1649c31SDevang Patel }
294e1649c31SDevang Patel 
295e1649c31SDevang Patel /// dominates - Return true if DebugLoc's lexical scope dominates at least one
296e1649c31SDevang Patel /// machine instruction's lexical scope in a given machine basic block.
297a9308c49SDuncan P. N. Exon Smith bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
298e1649c31SDevang Patel   LexicalScope *Scope = getOrCreateLexicalScope(DL);
299e1649c31SDevang Patel   if (!Scope)
300e1649c31SDevang Patel     return false;
301db4374a2SDevang Patel 
302db4374a2SDevang Patel   // Current function scope covers all basic blocks in the function.
303db4374a2SDevang Patel   if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
304db4374a2SDevang Patel     return true;
305db4374a2SDevang Patel 
306e1649c31SDevang Patel   bool Result = false;
30716b2ace0SAdrian Prantl   for (auto &I : *MBB) {
30816b2ace0SAdrian Prantl     if (const DILocation *IDL = I.getDebugLoc())
309e1649c31SDevang Patel       if (LexicalScope *IScope = getOrCreateLexicalScope(IDL))
310e1649c31SDevang Patel         if (Scope->dominates(IScope))
311e1649c31SDevang Patel           return true;
312e1649c31SDevang Patel   }
313e1649c31SDevang Patel   return Result;
314e1649c31SDevang Patel }
315e1649c31SDevang Patel 
3168c209aa8SMatthias Braun #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3178c209aa8SMatthias Braun LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
318e1649c31SDevang Patel   raw_ostream &err = dbgs();
319e498b25bSManman Ren   err.indent(Indent);
320e1649c31SDevang Patel   err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
321e1649c31SDevang Patel   const MDNode *N = Desc;
322e498b25bSManman Ren   err.indent(Indent);
323e1649c31SDevang Patel   N->dump();
324e1649c31SDevang Patel   if (AbstractScope)
325e498b25bSManman Ren     err << std::string(Indent, ' ') << "Abstract Scope\n";
326e1649c31SDevang Patel 
327e1649c31SDevang Patel   if (!Children.empty())
328e498b25bSManman Ren     err << std::string(Indent + 2, ' ') << "Children ...\n";
329e1649c31SDevang Patel   for (unsigned i = 0, e = Children.size(); i != e; ++i)
330e1649c31SDevang Patel     if (Children[i] != this)
331e498b25bSManman Ren       Children[i]->dump(Indent + 2);
332e1649c31SDevang Patel }
3338c209aa8SMatthias Braun #endif
334