LLVM: lib/CodeGen/LexicalScopes.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
22#include "llvm/Config/llvm-config.h"
31#include
32#include
33#include
34#include
35
36using namespace llvm;
37
38#define DEBUG_TYPE "lexicalscopes"
39
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
63 if (SP && (!SP->getUnit() || (SP->getUnit())))
64 FunctionMap[SP] = &F;
65 }
66}
67
70
72 return;
73 MF = &Fn;
76 extractLexicalScopes(MIRanges, MI2ScopeMap);
77 if (CurrentFnLexicalScope) {
78 constructScopeNest(CurrentFnLexicalScope);
79 assignInstructionRanges(MIRanges, MI2ScopeMap);
80 }
81}
82
83
84
85void LexicalScopes::extractLexicalScopes(
88
89 for (const auto &MBB : *MF) {
93 for (const auto &MInsn : MBB) {
94
95
96 if (MInsn.isMetaInstruction())
97 continue;
98
99
100 const DILocation *MIDL = MInsn.getDebugLoc();
101 if (!MIDL) {
102 PrevMI = &MInsn;
103 continue;
104 }
105
106
107 if (MIDL == PrevDL) {
108 PrevMI = &MInsn;
109 continue;
110 }
111
112 if (RangeBeginMI) {
113
114
115
117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
119 }
120
121
122 RangeBeginMI = &MInsn;
123
124
125 PrevMI = &MInsn;
126 PrevDL = MIDL;
127 }
128
129
130 if (RangeBeginMI && PrevMI && PrevDL) {
133 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
134 }
135 }
136}
137
138
139
142 if (!Scope)
143 return nullptr;
144
145
146
147 Scope = Scope->getNonLexicalBlockFileScope();
148
149 if (auto *IA = DL->getInlinedAt()) {
150 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
151 return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
152 }
154}
155
156
157
160 if (IA) {
161
162 if (skipUnit(Scope->getSubprogram()->getUnit()))
163 return getOrCreateLexicalScope(IA);
164
166
167 return getOrCreateInlinedScope(Scope, IA);
168 }
169
170 return getOrCreateRegularScope(Scope);
171}
172
173
175LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
176 assert(Scope && "Invalid Scope encoding!");
177 Scope = Scope->getNonLexicalBlockFileScope();
178
179 auto I = LexicalScopeMap.find(Scope);
180 if (I != LexicalScopeMap.end())
181 return &I->second;
182
183
184 LexicalScope *Parent = nullptr;
186 Parent = getOrCreateLexicalScope(Block->getScope());
187 I = LexicalScopeMap.emplace(std::piecewise_construct,
188 std::forward_as_tuple(Scope),
189 std::forward_as_tuple(Parent, Scope, nullptr,
190 false)).first;
191
192 if (!Parent) {
194 assert(!CurrentFnLexicalScope);
195 CurrentFnLexicalScope = &I->second;
196 }
197
198 return &I->second;
199}
200
201
203LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
205 assert(Scope && "Invalid Scope encoding!");
206 Scope = Scope->getNonLexicalBlockFileScope();
207 std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
208 auto I = InlinedLexicalScopeMap.find(P);
209 if (I != InlinedLexicalScopeMap.end())
210 return &I->second;
211
212 LexicalScope *Parent;
214 Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
215 else
216 Parent = getOrCreateLexicalScope(InlinedAt);
217
218 I = InlinedLexicalScopeMap
219 .emplace(std::piecewise_construct, std::forward_as_tuple(P),
220 std::forward_as_tuple(Parent, Scope, InlinedAt, false))
221 .first;
222 return &I->second;
223}
224
225
228 assert(Scope && "Invalid Scope encoding!");
229 Scope = Scope->getNonLexicalBlockFileScope();
230 auto I = AbstractScopeMap.find(Scope);
231 if (I != AbstractScopeMap.end())
232 return &I->second;
233
234
238
239 I = AbstractScopeMap.emplace(std::piecewise_construct,
240 std::forward_as_tuple(Scope),
241 std::forward_as_tuple(Parent, Scope,
242 nullptr, true)).first;
244 AbstractScopesList.push_back(&I->second);
245 return &I->second;
246}
247
248
249
250
251void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
252 assert(Scope && "Unable to calculate scope dominance graph!");
254 WorkStack.push_back(std::make_pair(Scope, 0));
255 unsigned Counter = 0;
256 while (!WorkStack.empty()) {
257 auto &ScopePosition = WorkStack.back();
259 size_t ChildNum = ScopePosition.second++;
261 if (ChildNum < Children.size()) {
262 auto &ChildScope = Children[ChildNum];
263 WorkStack.push_back(std::make_pair(ChildScope, 0));
264 ChildScope->setDFSIn(++Counter);
265 } else {
268 }
269 }
270}
271
272
273
274void LexicalScopes::assignInstructionRanges(
277 LexicalScope *PrevLexicalScope = nullptr;
278 for (const auto &R : MIRanges) {
279 LexicalScope *S = MI2ScopeMap.lookup(R.first);
280 assert(S && "Lost LexicalScope for a machine instruction!");
281 if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
285 PrevLexicalScope = S;
286 }
287
288 if (PrevLexicalScope)
290}
291
292
293
294
297 assert(MF && "Method called on a uninitialized LexicalScopes object!");
299
301 if (!Scope)
302 return;
303
304 if (Scope == CurrentFnLexicalScope) {
306 return;
307 }
308
309
310
311
313 for (auto &R : InsnRanges)
314 for (auto CurMBBIt = R.first->getParent()->getIterator(),
315 EndBBIt = std::next(R.second->getParent()->getIterator());
316 CurMBBIt != EndBBIt; CurMBBIt++)
317 MBBs.insert(&*CurMBBIt);
318}
319
321 assert(MF && "Unexpected uninitialized LexicalScopes object!");
323 if (!Scope)
324 return false;
325
326
327 if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
328 return true;
329
330
331
332
333
334
335
336 std::unique_ptr &Set = DominatedBlocks[DL];
337 if (!Set) {
338 Set = std::make_unique();
340 }
341 return Set->contains(MBB);
342}
343
344#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
348 err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
351 N->dump();
352 if (AbstractScope)
353 err << std::string(Indent, ' ') << "Abstract Scope\n";
354
355 if (!Children.empty())
356 err << std::string(Indent + 2, ' ') << "Children ...\n";
358 if (Child != this)
359 Child->dump(Indent + 2);
360}
361#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
static bool skipUnit(const DICompileUnit *CU)
Definition LexicalScopes.cpp:40
This file defines the SmallVector class.
Subprogram description. Uses SubclassData1.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
DISubprogram * getSubprogram() const
Get the attached subprogram.
This class is used to track scope information.
void extendInsnRange(const MachineInstr *MI)
Extend the current instruction range covered by this scope.
SmallVectorImpl< LexicalScope * > & getChildren()
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)
void setDFSOut(unsigned O)
void openInsnRange(const MachineInstr *MI)
This scope covers instruction range starting from MI.
LLVM_ABI void dump(unsigned Indent=0) const
Print lexical scope.
Definition LexicalScopes.cpp:345
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.
Definition LexicalScopes.cpp:68
LLVM_ABI LexicalScope * getOrCreateAbstractScope(const DILocalScope *Scope)
Find or create an abstract lexical scope.
Definition LexicalScopes.cpp:227
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
Definition LexicalScopes.cpp:140
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 ...
Definition LexicalScopes.cpp:295
LLVM_ABI void initialize(const Module &)
Scan module to build subprogram-to-function map.
Definition LexicalScopes.cpp:59
LLVM_ABI void resetFunction()
Reset the instance so that it's prepared for another function.
Definition LexicalScopes.cpp:49
LLVM_ABI void resetModule()
Reset the instance so that it's prepared for another module.
Definition LexicalScopes.cpp:44
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...
Definition LexicalScopes.cpp:320
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.
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.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
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.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)