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/// InsnRange - This is used to track range of instructions with identical
38/// lexical scope.
39///
40using InsnRange = std::pair<const MachineInstr *, const MachineInstr *>;
41
42//===----------------------------------------------------------------------===//
43/// LexicalScope - This class is used to track scope information.
44///
46public:
48 bool A)
49 : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) {
50 assert(D);
51 assert(D->getSubprogram()->getUnit()->getEmissionKind() !=
53 "Don't build lexical scopes for non-debug locations");
54 assert(D->isResolved() && "Expected resolved node");
55 assert((!I || I->isResolved()) && "Expected resolved node");
56 if (Parent)
57 Parent->addChild(this);
58 }
59
60 // Accessors.
61 LexicalScope *getParent() const { return Parent; }
62 const MDNode *getDesc() const { return Desc; }
63 const DILocation *getInlinedAt() const { return InlinedAtLocation; }
64 const DILocalScope *getScopeNode() const { return Desc; }
65 bool isAbstractScope() const { return AbstractScope; }
68
69 /// addChild - Add a child scope.
70 void addChild(LexicalScope *S) { Children.push_back(S); }
71
72 /// openInsnRange - This scope covers instruction range starting from MI.
74 if (!FirstInsn)
75 FirstInsn = MI;
76
77 if (Parent)
78 Parent->openInsnRange(MI);
79 }
80
81 /// extendInsnRange - Extend the current instruction range covered by
82 /// this scope.
84 assert(FirstInsn && "MI Range is not open!");
85 LastInsn = MI;
86 if (Parent)
87 Parent->extendInsnRange(MI);
88 }
89
90 /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected
91 /// until now. This is used when a new scope is encountered while walking
92 /// machine instructions.
93 void closeInsnRange(LexicalScope *NewScope = nullptr) {
94 assert(LastInsn && "Last insn missing!");
95 Ranges.push_back(InsnRange(FirstInsn, LastInsn));
96 FirstInsn = nullptr;
97 LastInsn = nullptr;
98 // If Parent dominates NewScope then do not close Parent's instruction
99 // range.
100 if (Parent && (!NewScope || !Parent->dominates(NewScope)))
101 Parent->closeInsnRange(NewScope);
102 }
103
104 /// dominates - Return true if current scope dominates given lexical scope.
105 bool dominates(const LexicalScope *S) const {
106 if (S == this)
107 return true;
108 if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut())
109 return true;
110 return false;
111 }
112
113 // Depth First Search support to walk and manipulate LexicalScope hierarchy.
114 unsigned getDFSOut() const { return DFSOut; }
115 void setDFSOut(unsigned O) { DFSOut = O; }
116 unsigned getDFSIn() const { return DFSIn; }
117 void setDFSIn(unsigned I) { DFSIn = I; }
118
119 /// dump - print lexical scope.
120 LLVM_ABI void dump(unsigned Indent = 0) const;
121
122private:
123 LexicalScope *Parent; // Parent to this scope.
124 const DILocalScope *Desc; // Debug info descriptor.
125 const DILocation *InlinedAtLocation; // Location at which this
126 // scope is inlined.
127 bool AbstractScope; // Abstract Scope
128 SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
129 // Contents not owned.
131
132 const MachineInstr *LastInsn = nullptr; // Last instruction of this scope.
133 const MachineInstr *FirstInsn = nullptr; // First instruction of this scope.
134 unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting.
135 unsigned DFSOut = 0;
136};
137
138//===----------------------------------------------------------------------===//
139/// LexicalScopes - This class provides interface to collect and use lexical
140/// scoping information from machine instruction.
141///
143public:
144 LexicalScopes() = default;
145
146 /// initialize - Scan machine function and constuct lexical scope nest, resets
147 /// the instance if necessary.
148 LLVM_ABI void initialize(const MachineFunction &);
149
150 /// releaseMemory - release memory.
151 LLVM_ABI void reset();
152
153 /// empty - Return true if there is any lexical scope information available.
154 bool empty() { return CurrentFnLexicalScope == nullptr; }
155
156 /// getCurrentFunctionScope - Return lexical scope for the current function.
158 return CurrentFnLexicalScope;
159 }
160
161 /// getMachineBasicBlocks - Populate given set using machine basic blocks
162 /// which have machine instructions that belong to lexical scope identified by
163 /// DebugLoc.
164 LLVM_ABI void
167
168 /// Return true if DebugLoc's lexical scope dominates at least one machine
169 /// instruction's lexical scope in a given machine basic block.
171
172 /// findLexicalScope - Find lexical scope, either regular or inlined, for the
173 /// given DebugLoc. Return NULL if not found.
175
176 /// getAbstractScopesList - Return a reference to list of abstract scopes.
178 return AbstractScopesList;
179 }
180
181 /// findAbstractScope - Find an abstract scope or return null.
183 auto I = AbstractScopeMap.find(N);
184 return I != AbstractScopeMap.end() ? &I->second : nullptr;
185 }
186
187 /// findInlinedScope - Find an inlined scope for the given scope/inlined-at.
189 auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
190 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
191 }
192
193 /// findLexicalScope - Find regular lexical scope or return null.
195 auto I = LexicalScopeMap.find(N);
196 return I != LexicalScopeMap.end() ? &I->second : nullptr;
197 }
198
199 /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
201
202private:
203 /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If
204 /// not available then create new lexical scope.
206 getOrCreateLexicalScope(const DILocalScope *Scope,
207 const DILocation *IA = nullptr);
208 LexicalScope *getOrCreateLexicalScope(const DILocation *DL) {
209 return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt())
210 : nullptr;
211 }
212
213 /// getOrCreateRegularScope - Find or create a regular lexical scope.
214 LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope);
215
216 /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
217 LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope,
218 const DILocation *InlinedAt);
219
220 /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
221 /// for the given machine function.
222 void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
223 DenseMap<const MachineInstr *, LexicalScope *> &M);
224 void constructScopeNest(LexicalScope *Scope);
225 void
226 assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
227 DenseMap<const MachineInstr *, LexicalScope *> &M);
228
229 const MachineFunction *MF = nullptr;
230
231 /// LexicalScopeMap - Tracks the scopes in the current function.
232 // Use an unordered_map to ensure value pointer validity over insertion.
233 std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
234
235 /// InlinedLexicalScopeMap - Tracks inlined function scopes in current
236 /// function.
237 std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
238 LexicalScope,
239 pair_hash<const DILocalScope *, const DILocation *>>
240 InlinedLexicalScopeMap;
241
242 /// AbstractScopeMap - These scopes are not included LexicalScopeMap.
243 // Use an unordered_map to ensure value pointer validity over insertion.
244 std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
245
246 /// AbstractScopesList - Tracks abstract scopes constructed while processing
247 /// a function.
248 SmallVector<LexicalScope *, 4> AbstractScopesList;
249
250 /// CurrentFnLexicalScope - Top level scope for the current function.
251 ///
252 LexicalScope *CurrentFnLexicalScope = nullptr;
253
254 /// Map a location to the set of basic blocks it dominates. This is a cache
255 /// for \ref LexicalScopes::getMachineBasicBlocks results.
256 using BlockSetT = SmallPtrSet<const MachineBasicBlock *, 4>;
257 DenseMap<const DILocation *, std::unique_ptr<BlockSetT>> DominatedBlocks;
258};
259
260} // end namespace llvm
261
262#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.
LexicalScope - This class is used to track scope information.
unsigned getDFSIn() const
void extendInsnRange(const MachineInstr *MI)
extendInsnRange - 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)
openInsnRange - This scope covers instruction range starting from MI.
void addChild(LexicalScope *S)
addChild - Add a child scope.
LLVM_ABI void dump(unsigned Indent=0) const
dump - print lexical scope.
void setDFSIn(unsigned I)
LexicalScope * getParent() const
const MDNode * getDesc() const
bool dominates(const LexicalScope *S) const
dominates - Return true if current scope dominates given lexical scope.
void closeInsnRange(LexicalScope *NewScope=nullptr)
closeInsnRange - Create a range based on FirstInsn and LastInsn collected until now.
bool isAbstractScope() const
LLVM_ABI void reset()
releaseMemory - release memory.
LLVM_ABI LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)
getOrCreateAbstractScope - Find or create an abstract lexical scope.
LLVM_ABI void initialize(const MachineFunction &)
initialize - Scan machine function and constuct lexical scope nest, resets the instance if necessary.
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScopes()=default
LLVM_ABI void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl< const MachineBasicBlock * > &MBBs)
getMachineBasicBlocks - Populate given set using machine basic blocks which have machine instructions...
ArrayRef< LexicalScope * > getAbstractScopesList() const
getAbstractScopesList - Return a reference to list of abstract scopes.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * findAbstractScope(const DILocalScope *N)
findAbstractScope - Find an abstract scope or return null.
LexicalScope * findLexicalScope(const DILocalScope *N)
findLexicalScope - Find regular lexical scope or return null.
bool empty()
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
getCurrentFunctionScope - Return lexical scope for the current function.
Metadata node.
Definition Metadata.h:1077
Representation of each machine instruction.
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
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