1 //===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements LexicalScopes analysis.
11 // This pass collects lexical scope information and maps machine instructions
12 // to respective lexical scopes.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CODEGEN_LEXICALSCOPES_H
17 #define LLVM_CODEGEN_LEXICALSCOPES_H
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallPtrSet.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/IR/DebugInfoMetadata.h"
25 #include <unordered_map>
30 class MachineBasicBlock
;
31 class MachineFunction
;
35 //===----------------------------------------------------------------------===//
36 /// InsnRange - This is used to track range of instructions with identical
39 using InsnRange
= std::pair
<const MachineInstr
*, const MachineInstr
*>;
41 //===----------------------------------------------------------------------===//
42 /// LexicalScope - This class is used to track scope information.
46 LexicalScope(LexicalScope
*P
, const DILocalScope
*D
, const DILocation
*I
,
48 : Parent(P
), Desc(D
), InlinedAtLocation(I
), AbstractScope(A
) {
50 assert(D
->getSubprogram()->getUnit()->getEmissionKind() !=
51 DICompileUnit::NoDebug
&&
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");
56 Parent
->addChild(this);
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
; }
65 SmallVectorImpl
<LexicalScope
*> &getChildren() { return Children
; }
66 SmallVectorImpl
<InsnRange
> &getRanges() { return Ranges
; }
68 /// addChild - Add a child scope.
69 void addChild(LexicalScope
*S
) { Children
.push_back(S
); }
71 /// openInsnRange - This scope covers instruction range starting from MI.
72 void openInsnRange(const MachineInstr
*MI
) {
77 Parent
->openInsnRange(MI
);
80 /// extendInsnRange - Extend the current instruction range covered by
82 void extendInsnRange(const MachineInstr
*MI
) {
83 assert(FirstInsn
&& "MI Range is not open!");
86 Parent
->extendInsnRange(MI
);
89 /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected
90 /// until now. This is used when a new scope is encountered while walking
91 /// machine instructions.
92 void closeInsnRange(LexicalScope
*NewScope
= nullptr) {
93 assert(LastInsn
&& "Last insn missing!");
94 Ranges
.push_back(InsnRange(FirstInsn
, LastInsn
));
97 // If Parent dominates NewScope then do not close Parent's instruction
99 if (Parent
&& (!NewScope
|| !Parent
->dominates(NewScope
)))
100 Parent
->closeInsnRange(NewScope
);
103 /// dominates - Return true if current scope dominates given lexical scope.
104 bool dominates(const LexicalScope
*S
) const {
107 if (DFSIn
< S
->getDFSIn() && DFSOut
> S
->getDFSOut())
112 // Depth First Search support to walk and manipulate LexicalScope hierarchy.
113 unsigned getDFSOut() const { return DFSOut
; }
114 void setDFSOut(unsigned O
) { DFSOut
= O
; }
115 unsigned getDFSIn() const { return DFSIn
; }
116 void setDFSIn(unsigned I
) { DFSIn
= I
; }
118 /// dump - print lexical scope.
119 void dump(unsigned Indent
= 0) const;
122 LexicalScope
*Parent
; // Parent to this scope.
123 const DILocalScope
*Desc
; // Debug info descriptor.
124 const DILocation
*InlinedAtLocation
; // Location at which this
126 bool AbstractScope
; // Abstract Scope
127 SmallVector
<LexicalScope
*, 4> Children
; // Scopes defined in scope.
128 // Contents not owned.
129 SmallVector
<InsnRange
, 4> Ranges
;
131 const MachineInstr
*LastInsn
= nullptr; // Last instruction of this scope.
132 const MachineInstr
*FirstInsn
= nullptr; // First instruction of this scope.
133 unsigned DFSIn
= 0; // In & Out Depth use to determine scope nesting.
137 //===----------------------------------------------------------------------===//
138 /// LexicalScopes - This class provides interface to collect and use lexical
139 /// scoping information from machine instruction.
141 class LexicalScopes
{
143 LexicalScopes() = default;
145 /// initialize - Scan machine function and constuct lexical scope nest, resets
146 /// the instance if necessary.
147 void initialize(const MachineFunction
&);
149 /// releaseMemory - release memory.
152 /// empty - Return true if there is any lexical scope information available.
153 bool empty() { return CurrentFnLexicalScope
== nullptr; }
155 /// getCurrentFunctionScope - Return lexical scope for the current function.
156 LexicalScope
*getCurrentFunctionScope() const {
157 return CurrentFnLexicalScope
;
160 /// getMachineBasicBlocks - Populate given set using machine basic blocks
161 /// which have machine instructions that belong to lexical scope identified by
163 void getMachineBasicBlocks(const DILocation
*DL
,
164 SmallPtrSetImpl
<const MachineBasicBlock
*> &MBBs
);
166 /// dominates - Return true if DebugLoc's lexical scope dominates at least one
167 /// machine instruction's lexical scope in a given machine basic block.
168 bool dominates(const DILocation
*DL
, MachineBasicBlock
*MBB
);
170 /// findLexicalScope - Find lexical scope, either regular or inlined, for the
171 /// given DebugLoc. Return NULL if not found.
172 LexicalScope
*findLexicalScope(const DILocation
*DL
);
174 /// getAbstractScopesList - Return a reference to list of abstract scopes.
175 ArrayRef
<LexicalScope
*> getAbstractScopesList() const {
176 return AbstractScopesList
;
179 /// findAbstractScope - Find an abstract scope or return null.
180 LexicalScope
*findAbstractScope(const DILocalScope
*N
) {
181 auto I
= AbstractScopeMap
.find(N
);
182 return I
!= AbstractScopeMap
.end() ? &I
->second
: nullptr;
185 /// findInlinedScope - Find an inlined scope for the given scope/inlined-at.
186 LexicalScope
*findInlinedScope(const DILocalScope
*N
, const DILocation
*IA
) {
187 auto I
= InlinedLexicalScopeMap
.find(std::make_pair(N
, IA
));
188 return I
!= InlinedLexicalScopeMap
.end() ? &I
->second
: nullptr;
191 /// findLexicalScope - Find regular lexical scope or return null.
192 LexicalScope
*findLexicalScope(const DILocalScope
*N
) {
193 auto I
= LexicalScopeMap
.find(N
);
194 return I
!= LexicalScopeMap
.end() ? &I
->second
: nullptr;
197 /// dump - Print data structures to dbgs().
200 /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
201 LexicalScope
*getOrCreateAbstractScope(const DILocalScope
*Scope
);
204 /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If
205 /// not available then create new lexical scope.
206 LexicalScope
*getOrCreateLexicalScope(const DILocalScope
*Scope
,
207 const DILocation
*IA
= nullptr);
208 LexicalScope
*getOrCreateLexicalScope(const DILocation
*DL
) {
209 return DL
? getOrCreateLexicalScope(DL
->getScope(), DL
->getInlinedAt())
213 /// getOrCreateRegularScope - Find or create a regular lexical scope.
214 LexicalScope
*getOrCreateRegularScope(const DILocalScope
*Scope
);
216 /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
217 LexicalScope
*getOrCreateInlinedScope(const DILocalScope
*Scope
,
218 const DILocation
*InlinedAt
);
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
);
226 assignInstructionRanges(SmallVectorImpl
<InsnRange
> &MIRanges
,
227 DenseMap
<const MachineInstr
*, LexicalScope
*> &M
);
229 const MachineFunction
*MF
= nullptr;
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
;
235 /// InlinedLexicalScopeMap - Tracks inlined function scopes in current
237 std::unordered_map
<std::pair
<const DILocalScope
*, const DILocation
*>,
239 pair_hash
<const DILocalScope
*, const DILocation
*>>
240 InlinedLexicalScopeMap
;
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
;
246 /// AbstractScopesList - Tracks abstract scopes constructed while processing
248 SmallVector
<LexicalScope
*, 4> AbstractScopesList
;
250 /// CurrentFnLexicalScope - Top level scope for the current function.
252 LexicalScope
*CurrentFnLexicalScope
= nullptr;
255 } // end namespace llvm
257 #endif // LLVM_CODEGEN_LEXICALSCOPES_H