22#include "llvm/Config/llvm-config.h"
37#define DEBUG_TYPE "lexicalscopes"
42 CurrentFnLexicalScope =
nullptr;
43 LexicalScopeMap.clear();
44 AbstractScopeMap.clear();
45 InlinedLexicalScopeMap.clear();
46 AbstractScopesList.clear();
47 DominatedBlocks.clear();
60 extractLexicalScopes(MIRanges, MI2ScopeMap);
61 if (CurrentFnLexicalScope) {
62 constructScopeNest(CurrentFnLexicalScope);
63 assignInstructionRanges(MIRanges, MI2ScopeMap);
69void LexicalScopes::extractLexicalScopes(
73 for (
const auto &
MBB : *MF) {
77 for (
const auto &MInsn :
MBB) {
80 if (MInsn.isMetaInstruction())
101 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
106 RangeBeginMI = &MInsn;
114 if (RangeBeginMI && PrevMI && PrevDL) {
117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
131 Scope = Scope->getNonLexicalBlockFileScope();
133 if (
auto *IA =
DL->getInlinedAt()) {
134 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
135 return I != InlinedLexicalScopeMap.end() ? &
I->second :
nullptr;
146 if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
148 return getOrCreateLexicalScope(IA);
152 return getOrCreateInlinedScope(Scope, IA);
155 return getOrCreateRegularScope(Scope);
160LexicalScopes::getOrCreateRegularScope(
const DILocalScope *Scope) {
161 assert(Scope &&
"Invalid Scope encoding!");
164 auto I = LexicalScopeMap.find(Scope);
165 if (
I != LexicalScopeMap.end())
169 LexicalScope *Parent =
nullptr;
171 Parent = getOrCreateLexicalScope(
Block->getScope());
172 I = LexicalScopeMap.emplace(std::piecewise_construct,
173 std::forward_as_tuple(Scope),
174 std::forward_as_tuple(Parent, Scope,
nullptr,
179 assert(!CurrentFnLexicalScope);
180 CurrentFnLexicalScope = &
I->second;
188LexicalScopes::getOrCreateInlinedScope(
const DILocalScope *Scope,
190 assert(Scope &&
"Invalid Scope encoding!");
192 std::pair<const DILocalScope *, const DILocation *>
P(Scope, InlinedAt);
193 auto I = InlinedLexicalScopeMap.find(
P);
194 if (
I != InlinedLexicalScopeMap.end())
197 LexicalScope *Parent;
199 Parent = getOrCreateInlinedScope(
Block->getScope(), InlinedAt);
201 Parent = getOrCreateLexicalScope(InlinedAt);
203 I = InlinedLexicalScopeMap
204 .emplace(std::piecewise_construct, std::forward_as_tuple(
P),
205 std::forward_as_tuple(Parent, Scope, InlinedAt,
false))
213 assert(Scope &&
"Invalid Scope encoding!");
214 Scope = Scope->getNonLexicalBlockFileScope();
215 auto I = AbstractScopeMap.find(Scope);
216 if (
I != AbstractScopeMap.end())
224 I = AbstractScopeMap.emplace(std::piecewise_construct,
225 std::forward_as_tuple(Scope),
226 std::forward_as_tuple(Parent, Scope,
227 nullptr,
true)).first;
229 AbstractScopesList.push_back(&
I->second);
236void LexicalScopes::constructScopeNest(
LexicalScope *Scope) {
237 assert(Scope &&
"Unable to calculate scope dominance graph!");
239 WorkStack.
push_back(std::make_pair(Scope, 0));
240 unsigned Counter = 0;
241 while (!WorkStack.
empty()) {
242 auto &ScopePosition = WorkStack.
back();
244 size_t ChildNum = ScopePosition.second++;
246 if (ChildNum < Children.size()) {
247 auto &ChildScope = Children[ChildNum];
248 WorkStack.
push_back(std::make_pair(ChildScope, 0));
249 ChildScope->setDFSIn(++Counter);
259void LexicalScopes::assignInstructionRanges(
262 LexicalScope *PrevLexicalScope =
nullptr;
263 for (
const auto &R : MIRanges) {
264 LexicalScope *S = MI2ScopeMap.
lookup(
R.first);
265 assert(S &&
"Lost LexicalScope for a machine instruction!");
266 if (PrevLexicalScope && !PrevLexicalScope->
dominates(S))
270 PrevLexicalScope = S;
273 if (PrevLexicalScope)
282 assert(MF &&
"Method called on a uninitialized LexicalScopes object!");
289 if (Scope == CurrentFnLexicalScope) {
298 for (
auto &R : InsnRanges)
299 for (
auto CurMBBIt = R.first->getParent()->getIterator(),
300 EndBBIt = std::next(R.second->getParent()->getIterator());
301 CurMBBIt != EndBBIt; CurMBBIt++)
306 assert(MF &&
"Unexpected uninitialized LexicalScopes object!");
312 if (Scope == CurrentFnLexicalScope &&
MBB->getParent() == MF)
321 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[
DL];
323 Set = std::make_unique<BlockSetT>();
326 return Set->contains(
MBB);
329#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
333 err <<
"DFSIn: " << DFSIn <<
" DFSOut: " << DFSOut <<
"\n";
338 err << std::string(Indent,
' ') <<
"Abstract Scope\n";
340 if (!Children.empty())
341 err << std::string(Indent + 2,
' ') <<
"Children ...\n";
344 Child->dump(Indent + 2);
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.
This file defines the SmallVector class.
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.
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 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.
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 bool dominates(const DILocation *DL, MachineBasicBlock *MBB)
Return true if DebugLoc's lexical scope dominates at least one machine instruction's lexical scope in...
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
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<X> - 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<X> - 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<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)