1 //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements LexicalScopes analysis.
11 // This pass collects lexical scope information and maps machine instructions
12 // to respective lexical scopes.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/CodeGen/LexicalScopes.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/CodeGen/MachineBasicBlock.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/Config/llvm-config.h"
23 #include "llvm/IR/DebugInfoMetadata.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/Metadata.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/raw_ostream.h"
37 #define DEBUG_TYPE "lexicalscopes"
39 /// reset - Reset the instance so that it's prepared for another function.
40 void LexicalScopes::reset() {
42 CurrentFnLexicalScope
= nullptr;
43 LexicalScopeMap
.clear();
44 AbstractScopeMap
.clear();
45 InlinedLexicalScopeMap
.clear();
46 AbstractScopesList
.clear();
49 /// initialize - Scan machine function and constuct lexical scope nest.
50 void LexicalScopes::initialize(const MachineFunction
&Fn
) {
52 // Don't attempt any lexical scope creation for a NoDebug compile unit.
53 if (Fn
.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
54 DICompileUnit::NoDebug
)
57 SmallVector
<InsnRange
, 4> MIRanges
;
58 DenseMap
<const MachineInstr
*, LexicalScope
*> MI2ScopeMap
;
59 extractLexicalScopes(MIRanges
, MI2ScopeMap
);
60 if (CurrentFnLexicalScope
) {
61 constructScopeNest(CurrentFnLexicalScope
);
62 assignInstructionRanges(MIRanges
, MI2ScopeMap
);
66 /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
67 /// for the given machine function.
68 void LexicalScopes::extractLexicalScopes(
69 SmallVectorImpl
<InsnRange
> &MIRanges
,
70 DenseMap
<const MachineInstr
*, LexicalScope
*> &MI2ScopeMap
) {
71 // Scan each instruction and create scopes. First build working set of scopes.
72 for (const auto &MBB
: *MF
) {
73 const MachineInstr
*RangeBeginMI
= nullptr;
74 const MachineInstr
*PrevMI
= nullptr;
75 const DILocation
*PrevDL
= nullptr;
76 for (const auto &MInsn
: MBB
) {
77 // Check if instruction has valid location information.
78 const DILocation
*MIDL
= MInsn
.getDebugLoc();
84 // If scope has not changed then skip this instruction.
90 // Ignore DBG_VALUE and similar instruction that do not contribute to any
91 // instruction in the output.
92 if (MInsn
.isMetaInstruction())
96 // If we have already seen a beginning of an instruction range and
97 // current instruction scope does not match scope of first instruction
98 // in this range then create a new instruction range.
99 InsnRange
R(RangeBeginMI
, PrevMI
);
100 MI2ScopeMap
[RangeBeginMI
] = getOrCreateLexicalScope(PrevDL
);
101 MIRanges
.push_back(R
);
104 // This is a beginning of a new instruction range.
105 RangeBeginMI
= &MInsn
;
107 // Reset previous markers.
112 // Create last instruction range.
113 if (RangeBeginMI
&& PrevMI
&& PrevDL
) {
114 InsnRange
R(RangeBeginMI
, PrevMI
);
115 MIRanges
.push_back(R
);
116 MI2ScopeMap
[RangeBeginMI
] = getOrCreateLexicalScope(PrevDL
);
121 /// findLexicalScope - Find lexical scope, either regular or inlined, for the
122 /// given DebugLoc. Return NULL if not found.
123 LexicalScope
*LexicalScopes::findLexicalScope(const DILocation
*DL
) {
124 DILocalScope
*Scope
= DL
->getScope();
128 // The scope that we were created with could have an extra file - which
129 // isn't what we care about in this case.
130 Scope
= Scope
->getNonLexicalBlockFileScope();
132 if (auto *IA
= DL
->getInlinedAt()) {
133 auto I
= InlinedLexicalScopeMap
.find(std::make_pair(Scope
, IA
));
134 return I
!= InlinedLexicalScopeMap
.end() ? &I
->second
: nullptr;
136 return findLexicalScope(Scope
);
139 /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
140 /// not available then create new lexical scope.
141 LexicalScope
*LexicalScopes::getOrCreateLexicalScope(const DILocalScope
*Scope
,
142 const DILocation
*IA
) {
144 // Skip scopes inlined from a NoDebug compile unit.
145 if (Scope
->getSubprogram()->getUnit()->getEmissionKind() ==
146 DICompileUnit::NoDebug
)
147 return getOrCreateLexicalScope(IA
);
148 // Create an abstract scope for inlined function.
149 getOrCreateAbstractScope(Scope
);
150 // Create an inlined scope for inlined function.
151 return getOrCreateInlinedScope(Scope
, IA
);
154 return getOrCreateRegularScope(Scope
);
157 /// getOrCreateRegularScope - Find or create a regular lexical scope.
159 LexicalScopes::getOrCreateRegularScope(const DILocalScope
*Scope
) {
160 assert(Scope
&& "Invalid Scope encoding!");
161 Scope
= Scope
->getNonLexicalBlockFileScope();
163 auto I
= LexicalScopeMap
.find(Scope
);
164 if (I
!= LexicalScopeMap
.end())
167 // FIXME: Should the following dyn_cast be DILexicalBlock?
168 LexicalScope
*Parent
= nullptr;
169 if (auto *Block
= dyn_cast
<DILexicalBlockBase
>(Scope
))
170 Parent
= getOrCreateLexicalScope(Block
->getScope());
171 I
= LexicalScopeMap
.emplace(std::piecewise_construct
,
172 std::forward_as_tuple(Scope
),
173 std::forward_as_tuple(Parent
, Scope
, nullptr,
177 assert(cast
<DISubprogram
>(Scope
)->describes(&MF
->getFunction()));
178 assert(!CurrentFnLexicalScope
);
179 CurrentFnLexicalScope
= &I
->second
;
185 /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
187 LexicalScopes::getOrCreateInlinedScope(const DILocalScope
*Scope
,
188 const DILocation
*InlinedAt
) {
189 assert(Scope
&& "Invalid Scope encoding!");
190 Scope
= Scope
->getNonLexicalBlockFileScope();
191 std::pair
<const DILocalScope
*, const DILocation
*> P(Scope
, InlinedAt
);
192 auto I
= InlinedLexicalScopeMap
.find(P
);
193 if (I
!= InlinedLexicalScopeMap
.end())
196 LexicalScope
*Parent
;
197 if (auto *Block
= dyn_cast
<DILexicalBlockBase
>(Scope
))
198 Parent
= getOrCreateInlinedScope(Block
->getScope(), InlinedAt
);
200 Parent
= getOrCreateLexicalScope(InlinedAt
);
202 I
= InlinedLexicalScopeMap
203 .emplace(std::piecewise_construct
, std::forward_as_tuple(P
),
204 std::forward_as_tuple(Parent
, Scope
, InlinedAt
, false))
209 /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
211 LexicalScopes::getOrCreateAbstractScope(const DILocalScope
*Scope
) {
212 assert(Scope
&& "Invalid Scope encoding!");
213 Scope
= Scope
->getNonLexicalBlockFileScope();
214 auto I
= AbstractScopeMap
.find(Scope
);
215 if (I
!= AbstractScopeMap
.end())
218 // FIXME: Should the following isa be DILexicalBlock?
219 LexicalScope
*Parent
= nullptr;
220 if (auto *Block
= dyn_cast
<DILexicalBlockBase
>(Scope
))
221 Parent
= getOrCreateAbstractScope(Block
->getScope());
223 I
= AbstractScopeMap
.emplace(std::piecewise_construct
,
224 std::forward_as_tuple(Scope
),
225 std::forward_as_tuple(Parent
, Scope
,
226 nullptr, true)).first
;
227 if (isa
<DISubprogram
>(Scope
))
228 AbstractScopesList
.push_back(&I
->second
);
232 /// constructScopeNest
233 void LexicalScopes::constructScopeNest(LexicalScope
*Scope
) {
234 assert(Scope
&& "Unable to calculate scope dominance graph!");
235 SmallVector
<LexicalScope
*, 4> WorkStack
;
236 WorkStack
.push_back(Scope
);
237 unsigned Counter
= 0;
238 while (!WorkStack
.empty()) {
239 LexicalScope
*WS
= WorkStack
.back();
240 const SmallVectorImpl
<LexicalScope
*> &Children
= WS
->getChildren();
241 bool visitedChildren
= false;
242 for (auto &ChildScope
: Children
)
243 if (!ChildScope
->getDFSOut()) {
244 WorkStack
.push_back(ChildScope
);
245 visitedChildren
= true;
246 ChildScope
->setDFSIn(++Counter
);
249 if (!visitedChildren
) {
250 WorkStack
.pop_back();
251 WS
->setDFSOut(++Counter
);
256 /// assignInstructionRanges - Find ranges of instructions covered by each
258 void LexicalScopes::assignInstructionRanges(
259 SmallVectorImpl
<InsnRange
> &MIRanges
,
260 DenseMap
<const MachineInstr
*, LexicalScope
*> &MI2ScopeMap
) {
261 LexicalScope
*PrevLexicalScope
= nullptr;
262 for (const auto &R
: MIRanges
) {
263 LexicalScope
*S
= MI2ScopeMap
.lookup(R
.first
);
264 assert(S
&& "Lost LexicalScope for a machine instruction!");
265 if (PrevLexicalScope
&& !PrevLexicalScope
->dominates(S
))
266 PrevLexicalScope
->closeInsnRange(S
);
267 S
->openInsnRange(R
.first
);
268 S
->extendInsnRange(R
.second
);
269 PrevLexicalScope
= S
;
272 if (PrevLexicalScope
)
273 PrevLexicalScope
->closeInsnRange();
276 /// getMachineBasicBlocks - Populate given set using machine basic blocks which
277 /// have machine instructions that belong to lexical scope identified by
279 void LexicalScopes::getMachineBasicBlocks(
280 const DILocation
*DL
, SmallPtrSetImpl
<const MachineBasicBlock
*> &MBBs
) {
281 assert(MF
&& "Method called on a uninitialized LexicalScopes object!");
284 LexicalScope
*Scope
= getOrCreateLexicalScope(DL
);
288 if (Scope
== CurrentFnLexicalScope
) {
289 for (const auto &MBB
: *MF
)
294 SmallVectorImpl
<InsnRange
> &InsnRanges
= Scope
->getRanges();
295 for (auto &R
: InsnRanges
)
296 MBBs
.insert(R
.first
->getParent());
299 /// dominates - Return true if DebugLoc's lexical scope dominates at least one
300 /// machine instruction's lexical scope in a given machine basic block.
301 bool LexicalScopes::dominates(const DILocation
*DL
, MachineBasicBlock
*MBB
) {
302 assert(MF
&& "Unexpected uninitialized LexicalScopes object!");
303 LexicalScope
*Scope
= getOrCreateLexicalScope(DL
);
307 // Current function scope covers all basic blocks in the function.
308 if (Scope
== CurrentFnLexicalScope
&& MBB
->getParent() == MF
)
312 for (auto &I
: *MBB
) {
313 if (const DILocation
*IDL
= I
.getDebugLoc())
314 if (LexicalScope
*IScope
= getOrCreateLexicalScope(IDL
))
315 if (Scope
->dominates(IScope
))
321 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
322 LLVM_DUMP_METHOD
void LexicalScope::dump(unsigned Indent
) const {
323 raw_ostream
&err
= dbgs();
325 err
<< "DFSIn: " << DFSIn
<< " DFSOut: " << DFSOut
<< "\n";
326 const MDNode
*N
= Desc
;
330 err
<< std::string(Indent
, ' ') << "Abstract Scope\n";
332 if (!Children
.empty())
333 err
<< std::string(Indent
+ 2, ' ') << "Children ...\n";
334 for (unsigned i
= 0, e
= Children
.size(); i
!= e
; ++i
)
335 if (Children
[i
] != this)
336 Children
[i
]->dump(Indent
+ 2);