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

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 machine function and constuct lexical scope nest, resets
145 /// the instance if necessary.
146 LLVM_ABI void initialize(const MachineFunction &);
147
148 /// Release memory.
149 LLVM_ABI void reset();
150
151 /// Return true if there is any lexical scope information available.
152 bool empty() { return CurrentFnLexicalScope == nullptr; }
153
154 /// Return lexical scope for the current function.
156 return CurrentFnLexicalScope;
157 }
158
159 /// Populate given set using machine basic blocks which have machine
160 /// instructions that belong to lexical scope identified by DebugLoc.
161 LLVM_ABI void
164
165 /// Return true if DebugLoc's lexical scope dominates at least one machine
166 /// instruction's lexical scope in a given machine basic block.
168
169 /// Find lexical scope, either regular or inlined, for the given DebugLoc.
170 /// Return NULL if not found.
172
173 /// Return a reference to list of abstract scopes.
175 return AbstractScopesList;
176 }
177
178 /// Find an abstract scope or return null.
180 auto I = AbstractScopeMap.find(N);
181 return I != AbstractScopeMap.end() ? &I->second : nullptr;
182 }
183
184 /// Find an inlined scope for the given scope/inlined-at.
186 auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
187 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
188 }
189
190 /// Find regular lexical scope or return null.
192 auto I = LexicalScopeMap.find(N);
193 return I != LexicalScopeMap.end() ? &I->second : nullptr;
194 }
195
196 /// Find or create an abstract lexical scope.
198
199private:
200 /// Find lexical scope for the given Scope/IA. If not available
201 /// then create new lexical scope.
203 getOrCreateLexicalScope(const DILocalScope *Scope,
204 const DILocation *IA = nullptr);
205 LexicalScope *getOrCreateLexicalScope(const DILocation *DL) {
206 return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt())
207 : nullptr;
208 }
209
210 /// Find or create a regular lexical scope.
211 LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope);
212
213 /// Find or create an inlined lexical scope.
214 LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope,
215 const DILocation *InlinedAt);
216
217 /// Extract instruction ranges for each lexical scopes
218 /// for the given machine function.
219 void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
220 DenseMap<const MachineInstr *, LexicalScope *> &M);
221 void constructScopeNest(LexicalScope *Scope);
222 void
223 assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
224 DenseMap<const MachineInstr *, LexicalScope *> &M);
225
226 const MachineFunction *MF = nullptr;
227
228 /// Tracks the scopes in the current function.
229 // Use an unordered_map to ensure value pointer validity over insertion.
230 std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
231
232 /// Tracks inlined function scopes in current function.
233 std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
234 LexicalScope,
235 pair_hash<const DILocalScope *, const DILocation *>>
236 InlinedLexicalScopeMap;
237
238 /// These scopes are not included LexicalScopeMap.
239 // Use an unordered_map to ensure value pointer validity over insertion.
240 std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
241
242 /// Tracks abstract scopes constructed while processing a function.
243 SmallVector<LexicalScope *, 4> AbstractScopesList;
244
245 /// Top level scope for the current function.
246 LexicalScope *CurrentFnLexicalScope = nullptr;
247
248 /// Map a location to the set of basic blocks it dominates. This is a cache
249 /// for \ref LexicalScopes::getMachineBasicBlocks results.
250 using BlockSetT = SmallPtrSet<const MachineBasicBlock *, 4>;
251 DenseMap<const DILocation *, std::unique_ptr<BlockSetT>> DominatedBlocks;
252};
253
254} // end namespace llvm
255
256#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.
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 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.
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 ...
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.
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 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