LLVM 23.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 LexicalScope(const LexicalScope &) = delete;
61
62 // Accessors.
63 LexicalScope *getParent() const { return Parent; }
64 const MDNode *getDesc() const { return Desc; }
65 const DILocation *getInlinedAt() const { return InlinedAtLocation; }
66 const DILocalScope *getScopeNode() const { return Desc; }
67 bool isAbstractScope() const { return AbstractScope; }
70
71 /// Add a child scope.
72 void addChild(LexicalScope *S) { Children.push_back(S); }
73
74 /// This scope covers instruction range starting from MI.
76 if (!FirstInsn)
77 FirstInsn = MI;
78
79 if (Parent)
80 Parent->openInsnRange(MI);
81 }
82
83 /// Extend the current instruction range covered by this scope.
85 assert(FirstInsn && "MI Range is not open!");
86 LastInsn = MI;
87 if (Parent)
88 Parent->extendInsnRange(MI);
89 }
90
91 /// Create a range based on FirstInsn and LastInsn collected until now.
92 /// This is used when a new scope is encountered while walking machine
93 /// instructions.
94 void closeInsnRange(LexicalScope *NewScope = nullptr) {
95 assert(LastInsn && "Last insn missing!");
96 Ranges.push_back(InsnRange(FirstInsn, LastInsn));
97 FirstInsn = nullptr;
98 LastInsn = nullptr;
99 // If Parent dominates NewScope then do not close Parent's instruction
100 // range.
101 if (Parent && (!NewScope || !Parent->dominates(NewScope)))
102 Parent->closeInsnRange(NewScope);
103 }
104
105 /// Return true if current scope dominates given lexical scope.
106 bool dominates(const LexicalScope *S) const {
107 if (S == this)
108 return true;
109 if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut())
110 return true;
111 return false;
112 }
113
114 // Depth First Search support to walk and manipulate LexicalScope hierarchy.
115 unsigned getDFSOut() const { return DFSOut; }
116 void setDFSOut(unsigned O) { DFSOut = O; }
117 unsigned getDFSIn() const { return DFSIn; }
118 void setDFSIn(unsigned I) { DFSIn = I; }
119
120 /// Print lexical scope.
121 LLVM_ABI void dump(unsigned Indent = 0) const;
122
123private:
124 LexicalScope *Parent; // Parent to this scope.
125 const DILocalScope *Desc; // Debug info descriptor.
126 const DILocation *InlinedAtLocation; // Location at which this
127 // scope is inlined.
128 bool AbstractScope; // Abstract Scope
129 SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
130 // Contents not owned.
132
133 const MachineInstr *LastInsn = nullptr; // Last instruction of this scope.
134 const MachineInstr *FirstInsn = nullptr; // First instruction of this scope.
135 unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting.
136 unsigned DFSOut = 0;
137};
138
139//===----------------------------------------------------------------------===//
140/// This class provides interface to collect and use lexical scoping information
141/// from machine instruction.
142///
144public:
145 LexicalScopes() = default;
146
147 LexicalScopes(const LexicalScopes &) = delete;
149
150 /// Scan module to build subprogram-to-function map.
151 LLVM_ABI void initialize(const Module &);
152
153 /// Scan machine function and constuct lexical scope nest, resets
154 /// the instance if necessary.
156
157 /// Reset the instance so that it's prepared for another module.
158 LLVM_ABI void resetModule();
159
160 /// Reset the instance so that it's prepared for another function.
161 LLVM_ABI void resetFunction();
162
163 /// Return true if there is any lexical scope information available.
164 bool empty() { return CurrentFnLexicalScope == nullptr; }
165
166 /// Return lexical scope for the current function.
168 return CurrentFnLexicalScope;
169 }
170
171 /// Populate given set using machine basic blocks which have machine
172 /// instructions that belong to lexical scope identified by DebugLoc.
173 LLVM_ABI void
176
177 /// Return true if DebugLoc's lexical scope dominates at least one machine
178 /// instruction's lexical scope in a given machine basic block.
180
181 /// Find lexical scope, either regular or inlined, for the given DebugLoc.
182 /// Return NULL if not found.
184
185 /// Return a reference to list of abstract scopes.
187 return AbstractScopesList;
188 }
189
190 /// Find an abstract scope or return null.
192 auto I = AbstractScopeMap.find(N);
193 return I != AbstractScopeMap.end() ? &I->second : nullptr;
194 }
195
196 /// Find an inlined scope for the given scope/inlined-at.
198 auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
199 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
200 }
201
202 /// Find regular lexical scope or return null.
204 auto I = LexicalScopeMap.find(N);
205 return I != LexicalScopeMap.end() ? &I->second : nullptr;
206 }
207
208 /// Find or create an abstract lexical scope.
210
211 /// Get function to which the given subprogram is attached, if exists.
212 const Function *getFunction(const DISubprogram *SP) const {
213 return FunctionMap.lookup(SP);
214 }
215
216private:
217 /// Find lexical scope for the given Scope/IA. If not available
218 /// then create new lexical scope.
220 getOrCreateLexicalScope(const DILocalScope *Scope,
221 const DILocation *IA = nullptr);
222 LexicalScope *getOrCreateLexicalScope(const DILocation *DL) {
223 return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt())
224 : nullptr;
225 }
226
227 /// Find or create a regular lexical scope.
228 LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope);
229
230 /// Find or create an inlined lexical scope.
231 LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope,
232 const DILocation *InlinedAt);
233
234 /// Extract instruction ranges for each lexical scopes
235 /// for the given machine function.
236 void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
237 DenseMap<const MachineInstr *, LexicalScope *> &M);
238 void constructScopeNest(LexicalScope *Scope);
239 void
240 assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
241 DenseMap<const MachineInstr *, LexicalScope *> &M);
242
243 const MachineFunction *MF = nullptr;
244
245 /// Mapping between DISubprograms and IR functions.
246 DenseMap<const DISubprogram *, const Function *> FunctionMap;
247
248 /// Tracks the scopes in the current function.
249 // Use an unordered_map to ensure value pointer validity over insertion.
250 std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
251
252 /// Tracks inlined function scopes in current function.
253 std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
254 LexicalScope,
255 pair_hash<const DILocalScope *, const DILocation *>>
256 InlinedLexicalScopeMap;
257
258 /// These scopes are not included LexicalScopeMap.
259 // Use an unordered_map to ensure value pointer validity over insertion.
260 std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
261
262 /// Tracks abstract scopes constructed while processing a function.
263 SmallVector<LexicalScope *, 4> AbstractScopesList;
264
265 /// Top level scope for the current function.
266 LexicalScope *CurrentFnLexicalScope = nullptr;
267
268 /// Map a location to the set of basic blocks it dominates. This is a cache
269 /// for \ref LexicalScopes::getMachineBasicBlocks results.
270 using BlockSetT = SmallPtrSet<const MachineBasicBlock *, 4>;
271 DenseMap<const DILocation *, std::unique_ptr<BlockSetT>> DominatedBlocks;
272};
273
274} // end namespace llvm
275
276#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:57
#define P(N)
This file defines the SmallPtrSet class.
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.
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()
LexicalScope(const LexicalScope &)=delete
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 & operator=(const LexicalScope &)=delete
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
LexicalScopes & operator=(const LexicalScopes &)=delete
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...
LexicalScopes(const LexicalScopes &)=delete
LexicalScope * getCurrentFunctionScope() const
Return lexical scope for the current function.
Metadata node.
Definition Metadata.h:1080
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...
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