LLVM 24.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"
26#include "llvm/IR/Module.h"
29#include "llvm/Support/Debug.h"
31#include <cassert>
32#include <string>
33#include <tuple>
34#include <utility>
35
36using namespace llvm;
37
38#define DEBUG_TYPE "lexicalscopes"
39
40static bool skipUnit(const DICompileUnit *CU) {
41 return CU->getEmissionKind() == DICompileUnit::NoDebug;
42}
43
45 FunctionMap.clear();
47}
48
50 MF = nullptr;
51 CurrentFnLexicalScope = nullptr;
52 LexicalScopeMap.clear();
53 AbstractScopeMap.clear();
54 InlinedLexicalScopeMap.clear();
55 AbstractScopesList.clear();
56 DominatedBlocks.clear();
57}
58
61 for (const Function &F : M) {
62 DISubprogram *SP = F.getSubprogram();
63 if (SP && (!SP->getUnit() || !skipUnit(SP->getUnit())))
64 FunctionMap[SP] = &F;
65 }
66}
67
70 // Don't attempt any lexical scope creation for a NoDebug compile unit.
71 if (skipUnit(Fn.getFunction().getSubprogram()->getUnit()))
72 return;
73 MF = &Fn;
75 extractLexicalScopes(MIRanges);
76 if (CurrentFnLexicalScope) {
77 constructScopeNest(CurrentFnLexicalScope);
78 assignInstructionRanges(MIRanges);
79 }
80}
81
82/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
83/// for the given machine function.
84void LexicalScopes::extractLexicalScopes(
85 SmallVectorImpl<std::pair<InsnRange, LexicalScope *>> &MIRanges) {
86 // Scan each instruction and create scopes. First build working set of scopes.
87 for (const auto &MBB : *MF) {
88 const MachineInstr *RangeBeginMI = nullptr;
89 const MachineInstr *PrevMI = nullptr;
90 const DILocation *PrevDL = nullptr;
91 for (const auto &MInsn : MBB) {
92 // Ignore DBG_VALUE and similar instruction that do not contribute to any
93 // instruction in the output.
94 if (MInsn.isMetaInstruction())
95 continue;
96
97 // Check if instruction has valid location information.
98 const DILocation *MIDL = MInsn.getDebugLoc();
99 if (!MIDL) {
100 PrevMI = &MInsn;
101 continue;
102 }
103
104 // If scope has not changed then skip this instruction.
105 if (MIDL == PrevDL) {
106 PrevMI = &MInsn;
107 continue;
108 }
109
110 if (RangeBeginMI) {
111 // If we have already seen a beginning of an instruction range and
112 // current instruction scope does not match scope of first instruction
113 // in this range then create a new instruction range.
114 MIRanges.push_back(
115 {InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
116 }
117
118 // This is a beginning of a new instruction range.
119 RangeBeginMI = &MInsn;
120
121 // Reset previous markers.
122 PrevMI = &MInsn;
123 PrevDL = MIDL;
124 }
125
126 // Create last instruction range.
127 if (RangeBeginMI && PrevMI && PrevDL)
128 MIRanges.push_back(
129 {InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
130 }
131}
132
133/// findLexicalScope - Find lexical scope, either regular or inlined, for the
134/// given DebugLoc. Return NULL if not found.
136 DILocalScope *Scope = DL->getScope();
137 if (!Scope)
138 return nullptr;
139
140 // The scope that we were created with could have an extra file - which
141 // isn't what we care about in this case.
142 Scope = Scope->getNonLexicalBlockFileScope();
143
144 if (auto *IA = DL->getInlinedAt()) {
145 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
146 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
147 }
148 return findLexicalScope(Scope);
149}
150
151/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
152/// not available then create new lexical scope.
153LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
154 const DILocation *IA) {
155 if (IA) {
156 // Skip scopes inlined from a NoDebug compile unit.
157 if (skipUnit(Scope->getSubprogram()->getUnit()))
158 return getOrCreateLexicalScope(IA);
159 // Create an abstract scope for inlined function.
161 // Create an inlined scope for inlined function.
162 return getOrCreateInlinedScope(Scope, IA);
163 }
164
165 return getOrCreateRegularScope(Scope);
166}
167
168/// getOrCreateRegularScope - Find or create a regular lexical scope.
170LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
171 assert(Scope && "Invalid Scope encoding!");
172 Scope = Scope->getNonLexicalBlockFileScope();
173
174 auto I = LexicalScopeMap.find(Scope);
175 if (I != LexicalScopeMap.end())
176 return &I->second;
177
178 // FIXME: Should the following dyn_cast be DILexicalBlock?
179 LexicalScope *Parent = nullptr;
180 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
181 Parent = getOrCreateLexicalScope(Block->getScope());
182 I = LexicalScopeMap.emplace(std::piecewise_construct,
183 std::forward_as_tuple(Scope),
184 std::forward_as_tuple(Parent, Scope, nullptr,
185 false)).first;
186
187 if (!Parent) {
188 assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
189 assert(!CurrentFnLexicalScope);
190 CurrentFnLexicalScope = &I->second;
191 }
192
193 return &I->second;
194}
195
196/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
198LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
199 const DILocation *InlinedAt) {
200 assert(Scope && "Invalid Scope encoding!");
201 Scope = Scope->getNonLexicalBlockFileScope();
202 std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
203 auto I = InlinedLexicalScopeMap.find(P);
204 if (I != InlinedLexicalScopeMap.end())
205 return &I->second;
206
207 LexicalScope *Parent;
208 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
209 Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
210 else
211 Parent = getOrCreateLexicalScope(InlinedAt);
212
213 I = InlinedLexicalScopeMap
214 .emplace(std::piecewise_construct, std::forward_as_tuple(P),
215 std::forward_as_tuple(Parent, Scope, InlinedAt, false))
216 .first;
217 return &I->second;
218}
219
220/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
223 assert(Scope && "Invalid Scope encoding!");
224 Scope = Scope->getNonLexicalBlockFileScope();
225 auto I = AbstractScopeMap.find(Scope);
226 if (I != AbstractScopeMap.end())
227 return &I->second;
228
229 // FIXME: Should the following isa be DILexicalBlock?
230 LexicalScope *Parent = nullptr;
231 if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
232 Parent = getOrCreateAbstractScope(Block->getScope());
233
234 I = AbstractScopeMap.emplace(std::piecewise_construct,
235 std::forward_as_tuple(Scope),
236 std::forward_as_tuple(Parent, Scope,
237 nullptr, true)).first;
238 if (isa<DISubprogram>(Scope))
239 AbstractScopesList.push_back(&I->second);
240 return &I->second;
241}
242
243/// constructScopeNest - Traverse the Scope tree depth-first, storing
244/// traversal state in WorkStack and recording the depth-first
245/// numbering (setDFSIn, setDFSOut) for edge classification.
246void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
247 assert(Scope && "Unable to calculate scope dominance graph!");
249 WorkStack.push_back(std::make_pair(Scope, 0));
250 unsigned Counter = 0;
251 while (!WorkStack.empty()) {
252 auto &ScopePosition = WorkStack.back();
253 LexicalScope *WS = ScopePosition.first;
254 size_t ChildNum = ScopePosition.second++;
255 const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
256 if (ChildNum < Children.size()) {
257 auto &ChildScope = Children[ChildNum];
258 WorkStack.push_back(std::make_pair(ChildScope, 0));
259 ChildScope->setDFSIn(++Counter);
260 } else {
261 WorkStack.pop_back();
262 WS->setDFSOut(++Counter);
263 }
264 }
265}
266
267/// assignInstructionRanges - Find ranges of instructions covered by each
268/// lexical scope.
269void LexicalScopes::assignInstructionRanges(
270 ArrayRef<std::pair<InsnRange, LexicalScope *>> MIRanges) {
271 LexicalScope *PrevLexicalScope = nullptr;
272 for (auto [R, S] : MIRanges) {
273 assert(S && "Lost LexicalScope for a machine instruction!");
274 if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
275 PrevLexicalScope->closeInsnRange(S);
276 S->openInsnRange(R.first);
277 S->extendInsnRange(R.second);
278 PrevLexicalScope = S;
279 }
280
281 if (PrevLexicalScope)
282 PrevLexicalScope->closeInsnRange();
283}
284
285/// getMachineBasicBlocks - Populate given set using machine basic blocks which
286/// have machine instructions that belong to lexical scope identified by
287/// DebugLoc.
290 assert(MF && "Method called on a uninitialized LexicalScopes object!");
291 MBBs.clear();
292
293 LexicalScope *Scope = getOrCreateLexicalScope(DL);
294 if (!Scope)
295 return;
296
297 if (Scope == CurrentFnLexicalScope) {
299 return;
300 }
301
302 // The scope ranges can cover multiple basic blocks in each span. Iterate over
303 // all blocks (in the order they are in the function) until we reach the one
304 // containing the end of the span.
305 SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
306 for (auto &R : InsnRanges)
307 for (auto CurMBBIt = R.first->getParent()->getIterator(),
308 EndBBIt = std::next(R.second->getParent()->getIterator());
309 CurMBBIt != EndBBIt; CurMBBIt++)
310 MBBs.insert(&*CurMBBIt);
311}
312
314 assert(MF && "Unexpected uninitialized LexicalScopes object!");
315 LexicalScope *Scope = getOrCreateLexicalScope(DL);
316 if (!Scope)
317 return false;
318
319 // Current function scope covers all basic blocks in the function.
320 if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
321 return true;
322
323 // Fetch all the blocks in DLs scope. Because the range / block list also
324 // contain any subscopes, any instruction that DL dominates can be found in
325 // the block set.
326 //
327 // Cache the set of fetched blocks to avoid repeatedly recomputing the set in
328 // the LiveDebugValues pass.
329 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL];
330 if (!Set) {
331 Set = std::make_unique<BlockSetT>();
333 }
334 return Set->contains(MBB);
335}
336
337#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
338LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
339 raw_ostream &err = dbgs();
340 err.indent(Indent);
341 err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
342 const MDNode *N = Desc;
343 err.indent(Indent);
344 N->dump();
345 if (AbstractScope)
346 err << std::string(Indent, ' ') << "Abstract Scope\n";
347
348 if (!Children.empty())
349 err << std::string(Indent + 2, ' ') << "Children ...\n";
350 for (const LexicalScope *Child : Children)
351 if (Child != this)
352 Child->dump(Indent + 2);
353}
354#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:682
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
static bool skipUnit(const DICompileUnit *CU)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
#define P(N)
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A scope for locals.
Subprogram description. Uses SubclassData1.
DISubprogram * getSubprogram() const
Get the attached subprogram.
This class is used to track scope information.
SmallVectorImpl< LexicalScope * > & getChildren()
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)
void setDFSOut(unsigned O)
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 scanFunction(const MachineFunction &)
Scan machine function and constuct lexical scope nest, resets the instance if necessary.
LLVM_ABI LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)
Find or create an abstract lexical scope.
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 void initialize(const Module &)
Scan module to build subprogram-to-function map.
LLVM_ABI void resetFunction()
Reset the instance so that it's prepared for another function.
LLVM_ABI void resetModule()
Reset the instance so that it's prepared for another module.
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:1081
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
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:643
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:209
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:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
#define N