Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
LexicalScopes.cpp
Go to the documentation of this file.
1//===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements LexicalScopes analysis.
10//
11// This pass collects lexical scope information and maps machine instructions
12// to respective lexical scopes.
13//
14//===----------------------------------------------------------------------===//
15
17#include "llvm/ADT/DenseMap.h"
22#include "llvm/Config/llvm-config.h"
24#include "llvm/IR/Function.h"
25#include "llvm/IR/Metadata.h"
28#include "llvm/Support/Debug.h"
30#include <cassert>
31#include <string>
32#include <tuple>
33#include <utility>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "lexicalscopes"
38
39/// reset - Reset the instance so that it's prepared for another function.
41 MF = nullptr;
42 CurrentFnLexicalScope = nullptr;
43 LexicalScopeMap.clear();
44 AbstractScopeMap.clear();
45 InlinedLexicalScopeMap.clear();
46 AbstractScopesList.clear();
47 DominatedBlocks.clear();
48}
49
50/// initialize - Scan machine function and constuct lexical scope nest.
52 reset();
53 // Don't attempt any lexical scope creation for a NoDebug compile unit.
54 if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
56 return;
57 MF = &Fn;
60 extractLexicalScopes(MIRanges, MI2ScopeMap);
61 if (CurrentFnLexicalScope) {
62 constructScopeNest(CurrentFnLexicalScope);
63 assignInstructionRanges(MIRanges, MI2ScopeMap);
64 }
65}
66
67/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
68/// for the given machine function.
69void LexicalScopes::extractLexicalScopes(
72 // Scan each instruction and create scopes. First build working set of scopes.
73 for (const auto &MBB : *MF) {
74 const MachineInstr *RangeBeginMI = nullptr;
75 const MachineInstr *PrevMI = nullptr;
76 const DILocation *PrevDL = nullptr;
77 for (const auto &MInsn : MBB) {
78 // Ignore DBG_VALUE and similar instruction that do not contribute to any
79 // instruction in the output.
80 if (MInsn.isMetaInstruction())
81 continue;
82
83 // Check if instruction has valid location information.
84 const DILocation *MIDL = MInsn.getDebugLoc();
85 if (!MIDL) {
86 PrevMI = &MInsn;
87 continue;
88 }
89
90 // If scope has not changed then skip this instruction.
91 if (MIDL == PrevDL) {
92 PrevMI = &MInsn;
93 continue;
94 }
95
96 if (RangeBeginMI) {
97 // If we have already seen a beginning of an instruction range and
98 // current instruction scope does not match scope of first instruction
99 // in this range then create a new instruction range.
100 InsnRange R(RangeBeginMI, PrevMI);
101 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
102 MIRanges.push_back(R);
103 }
104
105 // This is a beginning of a new instruction range.
106 RangeBeginMI = &MInsn;
107
108 // Reset previous markers.
109 PrevMI = &MInsn;
110 PrevDL = MIDL;
111 }
112
113 // Create last instruction range.
114 if (RangeBeginMI && PrevMI && PrevDL) {
115 InsnRange R(RangeBeginMI, PrevMI);
116 MIRanges.push_back(R);
117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
118 }
119 }
120}
121
122/// findLexicalScope - Find lexical scope, either regular or inlined, for the
123/// given DebugLoc. Return NULL if not found.
125 DILocalScope *Scope = DL->getScope();
126 if (!Scope)
127 return nullptr;
128
129 // The scope that we were created with could have an extra file - which
130 // isn't what we care about in this case.
131 Scope = Scope->getNonLexicalBlockFileScope();
132
133 if (auto *IA = DL->getInlinedAt()) {
134 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
135 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
136 }
137 return findLexicalScope(Scope);
138}
139
140/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
141/// not available then create new lexical scope.
142LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
143 const DILocation *IA) {
144 if (IA) {
145 // Skip scopes inlined from a NoDebug compile unit.
146 if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
148 return getOrCreateLexicalScope(IA);
149 // Create an abstract scope for inlined function.
151 // Create an inlined scope for inlined function.
152 return getOrCreateInlinedScope(Scope, IA);
153 }
154
155 return getOrCreateRegularScope(Scope);
156}
157
158/// getOrCreateRegularScope - Find or create a regular lexical scope.
160LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
161 assert(Scope && "Invalid Scope encoding!");
162 Scope = Scope->getNonLexicalBlockFileScope();
163
164 auto I = LexicalScopeMap.find(Scope);
165 if (I != LexicalScopeMap.end())
166 return &I->second;
167
168 // FIXME: Should the following dyn_cast be DILexicalBlock?
169 LexicalScope *Parent = nullptr;
170 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
171 Parent = getOrCreateLexicalScope(Block->getScope());
172 I = LexicalScopeMap.emplace(std::piecewise_construct,
173 std::forward_as_tuple(Scope),
174 std::forward_as_tuple(Parent, Scope, nullptr,
175 false)).first;
176
177 if (!Parent) {
178 assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
179 assert(!CurrentFnLexicalScope);
180 CurrentFnLexicalScope = &I->second;
181 }
182
183 return &I->second;
184}
185
186/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
188LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
189 const DILocation *InlinedAt) {
190 assert(Scope && "Invalid Scope encoding!");
191 Scope = Scope->getNonLexicalBlockFileScope();
192 std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
193 auto I = InlinedLexicalScopeMap.find(P);
194 if (I != InlinedLexicalScopeMap.end())
195 return &I->second;
196
197 LexicalScope *Parent;
198 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
199 Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
200 else
201 Parent = getOrCreateLexicalScope(InlinedAt);
202
203 I = InlinedLexicalScopeMap
204 .emplace(std::piecewise_construct, std::forward_as_tuple(P),
205 std::forward_as_tuple(Parent, Scope, InlinedAt, false))
206 .first;
207 return &I->second;
208}
209
210/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
213 assert(Scope && "Invalid Scope encoding!");
214 Scope = Scope->getNonLexicalBlockFileScope();
215 auto I = AbstractScopeMap.find(Scope);
216 if (I != AbstractScopeMap.end())
217 return &I->second;
218
219 // FIXME: Should the following isa be DILexicalBlock?
220 LexicalScope *Parent = nullptr;
221 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
222 Parent = getOrCreateAbstractScope(Block->getScope());
223
224 I = AbstractScopeMap.emplace(std::piecewise_construct,
225 std::forward_as_tuple(Scope),
226 std::forward_as_tuple(Parent, Scope,
227 nullptr, true)).first;
228 if (isa<DISubprogram>(Scope))
229 AbstractScopesList.push_back(&I->second);
230 return &I->second;
231}
232
233/// constructScopeNest - Traverse the Scope tree depth-first, storing
234/// traversal state in WorkStack and recording the depth-first
235/// numbering (setDFSIn, setDFSOut) for edge classification.
236void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
237 assert(Scope && "Unable to calculate scope dominance graph!");
239 WorkStack.push_back(std::make_pair(Scope, 0));
240 unsigned Counter = 0;
241 while (!WorkStack.empty()) {
242 auto &ScopePosition = WorkStack.back();
243 LexicalScope *WS = ScopePosition.first;
244 size_t ChildNum = ScopePosition.second++;
245 const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
246 if (ChildNum < Children.size()) {
247 auto &ChildScope = Children[ChildNum];
248 WorkStack.push_back(std::make_pair(ChildScope, 0));
249 ChildScope->setDFSIn(++Counter);
250 } else {
251 WorkStack.pop_back();
252 WS->setDFSOut(++Counter);
253 }
254 }
255}
256
257/// assignInstructionRanges - Find ranges of instructions covered by each
258/// lexical scope.
259void LexicalScopes::assignInstructionRanges(
262 LexicalScope *PrevLexicalScope = nullptr;
263 for (const auto &R : MIRanges) {
264 LexicalScope *S = MI2ScopeMap.lookup(R.first);
265 assert(S && "Lost LexicalScope for a machine instruction!");
266 if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
267 PrevLexicalScope->closeInsnRange(S);
268 S->openInsnRange(R.first);
269 S->extendInsnRange(R.second);
270 PrevLexicalScope = S;
271 }
272
273 if (PrevLexicalScope)
274 PrevLexicalScope->closeInsnRange();
275}
276
277/// getMachineBasicBlocks - Populate given set using machine basic blocks which
278/// have machine instructions that belong to lexical scope identified by
279/// DebugLoc.
282 assert(MF && "Method called on a uninitialized LexicalScopes object!");
283 MBBs.clear();
284
285 LexicalScope *Scope = getOrCreateLexicalScope(DL);
286 if (!Scope)
287 return;
288
289 if (Scope == CurrentFnLexicalScope) {
291 return;
292 }
293
294 // The scope ranges can cover multiple basic blocks in each span. Iterate over
295 // all blocks (in the order they are in the function) until we reach the one
296 // containing the end of the span.
297 SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
298 for (auto &R : InsnRanges)
299 for (auto CurMBBIt = R.first->getParent()->getIterator(),
300 EndBBIt = std::next(R.second->getParent()->getIterator());
301 CurMBBIt != EndBBIt; CurMBBIt++)
302 MBBs.insert(&*CurMBBIt);
303}
304
306 assert(MF && "Unexpected uninitialized LexicalScopes object!");
307 LexicalScope *Scope = getOrCreateLexicalScope(DL);
308 if (!Scope)
309 return false;
310
311 // Current function scope covers all basic blocks in the function.
312 if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
313 return true;
314
315 // Fetch all the blocks in DLs scope. Because the range / block list also
316 // contain any subscopes, any instruction that DL dominates can be found in
317 // the block set.
318 //
319 // Cache the set of fetched blocks to avoid repeatedly recomputing the set in
320 // the LiveDebugValues pass.
321 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL];
322 if (!Set) {
323 Set = std::make_unique<BlockSetT>();
325 }
326 return Set->contains(MBB);
327}
328
329#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
330LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
331 raw_ostream &err = dbgs();
332 err.indent(Indent);
333 err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
334 const MDNode *N = Desc;
335 err.indent(Indent);
336 N->dump();
337 if (AbstractScope)
338 err << std::string(Indent, ' ') << "Abstract Scope\n";
339
340 if (!Children.empty())
341 err << std::string(Indent + 2, ' ') << "Children ...\n";
342 for (const LexicalScope *Child : Children)
343 if (Child != this)
344 Child->dump(Indent + 2);
345}
346#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:58
This file contains the declarations for metadata subclasses.
#define P(N)
This file defines the SmallVector class.
A scope for locals.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition DenseMap.h:187
DISubprogram * getSubprogram() const
Get the attached subprogram.
This class is used to track scope information.
void extendInsnRange(const MachineInstr *MI)
Extend the current instruction range covered by this scope.
SmallVectorImpl< LexicalScope * > & getChildren()
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)
void setDFSOut(unsigned O)
void openInsnRange(const MachineInstr *MI)
This scope covers instruction range starting from MI.
LLVM_ABI void dump(unsigned Indent=0) const
Print lexical scope.
bool dominates(const LexicalScope *S) const
Return true if current scope dominates given lexical scope.
void closeInsnRange(LexicalScope *NewScope=nullptr)
Create a range based on FirstInsn and LastInsn collected until now.
LLVM_ABI void reset()
Release memory.
LLVM_ABI LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)
Find or create an abstract lexical scope.
LLVM_ABI void initialize(const MachineFunction &)
Scan machine function and constuct lexical scope nest, resets the instance if necessary.
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
LLVM_ABI void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock * > &MBBs)
Populate given set using machine basic blocks which have machine instructions that belong to lexical ...
LLVM_ABI bool dominates(const DILocation *DL, MachineBasicBlock *MBB)
Return true if DebugLoc's lexical scope dominates at least one machine instruction's lexical scope in...
Metadata node.
Definition Metadata.h:1077
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
This is used to track range of instructions with identical lexical scope.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:363
#define N