LLVM 22.0.0git
LexicalScopes.h
Go to the documentation of this file.
1//===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===//
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
16#ifndef LLVM_CODEGEN_LEXICALSCOPES_H
17#define LLVM_CODEGEN_LEXICALSCOPES_H
18
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/DenseMap.h"
25#include <cassert>
26#include <unordered_map>
27#include <utility>
28
29namespace llvm {
30
32class MachineFunction;
33class MachineInstr;
34class MDNode;
35
36//===----------------------------------------------------------------------===//
37/// This is used to track range of instructions with identical lexical scope.
38///
39using InsnRange = std::pair<const MachineInstr *, const MachineInstr *>;
40
41//===----------------------------------------------------------------------===//
42/// This class is used to track scope information.
43///
45public:
47 bool A)
48 : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) {
49 assert(D);
50 assert(D->getSubprogram()->getUnit()->getEmissionKind() !=
52 "Don't build lexical scopes for non-debug locations");
53 assert(D->isResolved() && "Expected resolved node");
54 assert((!I || I->isResolved()) && "Expected resolved node");
55 if (Parent)
56 Parent->addChild(this);
57 }
58
59 // Accessors.
60 LexicalScope *getParent() const { return Parent; }
61 const MDNode *getDesc() const { return Desc; }
62 const DILocation *getInlinedAt() const { return InlinedAtLocation; }
63 const DILocalScope *getScopeNode() const { return Desc; }
64 bool isAbstractScope() const { return AbstractScope; }
67
68 /// Add a child scope.
69 void addChild(LexicalScope *S) { Children.push_back(S); }
70
71 /// This scope covers instruction range starting from MI.
73 if (!FirstInsn)
74 FirstInsn = MI;
75
76 if (Parent)
77 Parent->openInsnRange(MI);
78 }
79
80 /// Extend the current instruction range covered by this scope.
82 assert(FirstInsn && "MI Range is not open!");
83 LastInsn = MI;
84 if (Parent)
85 Parent->extendInsnRange(MI);
86 }
87
88 /// Create a range based on FirstInsn and LastInsn collected until now.
89 /// This is used when a new scope is encountered while walking machine
90 /// instructions.
91 void closeInsnRange(LexicalScope *NewScope = nullptr) {
92 assert(LastInsn && "Last insn missing!");
93 Ranges.push_back(InsnRange(FirstInsn, LastInsn));
94 FirstInsn = nullptr;
95 LastInsn = nullptr;
96 // If Parent dominates NewScope then do not close Parent's instruction
97 // range.
98 if (Parent && (!NewScope || !Parent->dominates(NewScope)))
99 Parent->closeInsnRange(NewScope);
100 }
101
102 /// Return true if current scope dominates given lexical scope.
103 bool dominates(const LexicalScope *S) const {
104 if (S == this)
105 return true;
106 if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut())
107 return true;
108 return false;
109 }
110
111 // Depth First Search support to walk and manipulate LexicalScope hierarchy.
112 unsigned getDFSOut() const { return DFSOut; }
113 void setDFSOut(unsigned O) { DFSOut = O; }
114 unsigned getDFSIn() const { return DFSIn; }
115 void setDFSIn(unsigned I) { DFSIn = I; }
116
117 /// Print lexical scope.
118 LLVM_ABI void dump(unsigned Indent = 0) const;
119
120private:
121 LexicalScope *Parent; // Parent to this scope.
122 const DILocalScope *Desc; // Debug info descriptor.
123 const DILocation *InlinedAtLocation; // Location at which this
124 // scope is inlined.
125 bool AbstractScope; // Abstract Scope
126 SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
127 // Contents not owned.
129
130 const MachineInstr *LastInsn = nullptr; // Last instruction of this scope.
131 const MachineInstr *FirstInsn = nullptr; // First instruction of this scope.
132 unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting.
133 unsigned DFSOut = 0;
134};
135
136//===----------------------------------------------------------------------===//
137/// This class provides interface to collect and use lexical scoping information
138/// from machine instruction.
139///
141public:
142 LexicalScopes() = default;
143
144 /// Scan module to build subprogram-to-function map.
145 LLVM_ABI void initialize(const Module &);
146
147 /// Scan machine function and constuct lexical scope nest, resets
148 /// the instance if necessary.
150
151 /// Reset the instance so that it's prepared for another module.
152 LLVM_ABI void resetModule();
153
154 /// Reset the instance so that it's prepared for another function.
155 LLVM_ABI void resetFunction();
156
157 /// Return true if there is any lexical scope information available.
158 bool empty() { return CurrentFnLexicalScope == nullptr; }
159
160 /// Return lexical scope for the current function.
162 return CurrentFnLexicalScope;
163 }
164
165 /// Populate given set using machine basic blocks which have machine
166 /// instructions that belong to lexical scope identified by DebugLoc.
167 LLVM_ABI void
170
171 /// Return true if DebugLoc's lexical scope dominates at least one machine
172 /// instruction's lexical scope in a given machine basic block.
174
175 /// Find lexical scope, either regular or inlined, for the given DebugLoc.
176 /// Return NULL if not found.
178
179 /// Return a reference to list of abstract scopes.
181 return AbstractScopesList;
182 }
183
184 /// Find an abstract scope or return null.
186 auto I = AbstractScopeMap.find(N);
187 return I != AbstractScopeMap.end() ? &I->second : nullptr;
188 }
189
190 /// Find an inlined scope for the given scope/inlined-at.
192 auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
193 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
194 }
195
196 /// Find regular lexical scope or return null.
198 auto I = LexicalScopeMap.find(N);
199 return I != LexicalScopeMap.end() ? &I->second : nullptr;
200 }
201
202 /// Find or create an abstract lexical scope.
204
205 /// Get function to which the given subprogram is attached, if exists.
206 const Function *getFunction(const DISubprogram *SP) const {
207 return FunctionMap.lookup(SP);
208 }
209
210private:
211 /// Find lexical scope for the given Scope/IA. If not available
212 /// then create new lexical scope.
214 getOrCreateLexicalScope(const DILocalScope *Scope,
215 const DILocation *IA = nullptr);
216 LexicalScope *getOrCreateLexicalScope(const DILocation *DL) {
217 return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt())
218 : nullptr;
219 }
220
221 /// Find or create a regular lexical scope.
222 LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope);
223
224 /// Find or create an inlined lexical scope.
225 LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope,
226 const DILocation *InlinedAt);
227
228 /// Extract instruction ranges for each lexical scopes
229 /// for the given machine function.
230 void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
231 DenseMap<const MachineInstr *, LexicalScope *> &M);
232 void constructScopeNest(LexicalScope *Scope);
233 void
234 assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
235 DenseMap<const MachineInstr *, LexicalScope *> &M);
236
237 const MachineFunction *MF = nullptr;
238
239 /// Mapping between DISubprograms and IR functions.
240 DenseMap<const DISubprogram *, const Function *> FunctionMap;
241
242 /// Tracks the scopes in the current function.
243 // Use an unordered_map to ensure value pointer validity over insertion.
244 std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
245
246 /// Tracks inlined function scopes in current function.
247 std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
248 LexicalScope,
249 pair_hash<const DILocalScope *, const DILocation *>>
250 InlinedLexicalScopeMap;
251
252 /// These scopes are not included LexicalScopeMap.
253 // Use an unordered_map to ensure value pointer validity over insertion.
254 std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
255
256 /// Tracks abstract scopes constructed while processing a function.
257 SmallVector<LexicalScope *, 4> AbstractScopesList;
258
259 /// Top level scope for the current function.
260 LexicalScope *CurrentFnLexicalScope = nullptr;
261
262 /// Map a location to the set of basic blocks it dominates. This is a cache
263 /// for \ref LexicalScopes::getMachineBasicBlocks results.
264 using BlockSetT = SmallPtrSet<const MachineBasicBlock *, 4>;
265 DenseMap<const DILocation *, std::unique_ptr<BlockSetT>> DominatedBlocks;
266};
267
268} // end namespace llvm
269
270#endif // LLVM_CODEGEN_LEXICALSCOPES_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_ABI
Definition Compiler.h:213
This file defines the DenseMap class.
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
#define P(N)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
A scope for locals.
Subprogram description. Uses SubclassData1.
This class is used to track scope information.
unsigned getDFSIn() const
void extendInsnRange(const MachineInstr *MI)
Extend the current instruction range covered by this scope.
SmallVectorImpl< LexicalScope * > & getChildren()
const DILocation * getInlinedAt() const
SmallVectorImpl< InsnRange > & getRanges()
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)
const DILocalScope * getScopeNode() const
void setDFSOut(unsigned O)
unsigned getDFSOut() const
void openInsnRange(const MachineInstr *MI)
This scope covers instruction range starting from MI.
void addChild(LexicalScope *S)
Add a child scope.
LLVM_ABI void dump(unsigned Indent=0) const
Print lexical scope.
void setDFSIn(unsigned I)
LexicalScope * getParent() const
const MDNode * getDesc() const
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.
bool isAbstractScope() const
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.
LexicalScopes()=default
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.
const Function * getFunction(const DISubprogram *SP) const
Get function to which the given subprogram is attached, if exists.
ArrayRef< LexicalScope * > getAbstractScopesList() const
Return a reference to list of abstract scopes.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
Find an inlined scope for the given scope/inlined-at.
LexicalScope * findAbstractScope(const DILocalScope *N)
Find an abstract scope or return null.
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.
LexicalScope * findLexicalScope(const DILocalScope *N)
Find regular lexical scope or return null.
bool empty()
Return true if there is any lexical scope information available.
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...
LexicalScope * getCurrentFunctionScope() const
Return lexical scope for the current function.
Metadata node.
Definition Metadata.h:1077
Representation of each machine instruction.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
Op::Description Desc
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
This is used to track range of instructions with identical lexical scope.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
#define N