22#include "llvm/Config/llvm-config.h"
38#define DEBUG_TYPE "lexicalscopes"
51 CurrentFnLexicalScope =
nullptr;
52 LexicalScopeMap.clear();
53 AbstractScopeMap.clear();
54 InlinedLexicalScopeMap.clear();
55 AbstractScopesList.clear();
56 DominatedBlocks.clear();
63 if (SP && (!SP->getUnit() || !
skipUnit(SP->getUnit())))
76 extractLexicalScopes(MIRanges, MI2ScopeMap);
77 if (CurrentFnLexicalScope) {
78 constructScopeNest(CurrentFnLexicalScope);
79 assignInstructionRanges(MIRanges, MI2ScopeMap);
85void LexicalScopes::extractLexicalScopes(
89 for (
const auto &
MBB : *MF) {
93 for (
const auto &MInsn :
MBB) {
96 if (MInsn.isMetaInstruction())
107 if (MIDL == PrevDL) {
117 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
122 RangeBeginMI = &MInsn;
130 if (RangeBeginMI && PrevMI && PrevDL) {
133 MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
147 Scope = Scope->getNonLexicalBlockFileScope();
149 if (
auto *IA =
DL->getInlinedAt()) {
150 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
151 return I != InlinedLexicalScopeMap.end() ? &
I->second :
nullptr;
162 if (
skipUnit(Scope->getSubprogram()->getUnit()))
163 return getOrCreateLexicalScope(IA);
167 return getOrCreateInlinedScope(Scope, IA);
170 return getOrCreateRegularScope(Scope);
175LexicalScopes::getOrCreateRegularScope(
const DILocalScope *Scope) {
176 assert(Scope &&
"Invalid Scope encoding!");
179 auto I = LexicalScopeMap.find(Scope);
180 if (
I != LexicalScopeMap.end())
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,
194 assert(!CurrentFnLexicalScope);
195 CurrentFnLexicalScope = &
I->second;
203LexicalScopes::getOrCreateInlinedScope(
const DILocalScope *Scope,
205 assert(Scope &&
"Invalid Scope encoding!");
207 std::pair<const DILocalScope *, const DILocation *>
P(Scope, InlinedAt);
208 auto I = InlinedLexicalScopeMap.find(
P);
209 if (
I != InlinedLexicalScopeMap.end())
212 LexicalScope *Parent;
214 Parent = getOrCreateInlinedScope(
Block->getScope(), InlinedAt);
216 Parent = getOrCreateLexicalScope(InlinedAt);
218 I = InlinedLexicalScopeMap
219 .emplace(std::piecewise_construct, std::forward_as_tuple(
P),
220 std::forward_as_tuple(Parent, Scope, InlinedAt,
false))
228 assert(Scope &&
"Invalid Scope encoding!");
229 Scope = Scope->getNonLexicalBlockFileScope();
230 auto I = AbstractScopeMap.find(Scope);
231 if (
I != AbstractScopeMap.end())
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);
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);
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;
288 if (PrevLexicalScope)
297 assert(MF &&
"Method called on a uninitialized LexicalScopes object!");
304 if (Scope == CurrentFnLexicalScope) {
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++)
321 assert(MF &&
"Unexpected uninitialized LexicalScopes object!");
327 if (Scope == CurrentFnLexicalScope &&
MBB->getParent() == MF)
336 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[
DL];
338 Set = std::make_unique<BlockSetT>();
341 return Set->contains(
MBB);
344#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
348 err <<
"DFSIn: " << DFSIn <<
" DFSOut: " << DFSOut <<
"\n";
353 err << std::string(Indent,
' ') <<
"Abstract Scope\n";
355 if (!Children.empty())
356 err << std::string(Indent + 2,
' ') <<
"Children ...\n";
359 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.
Module.h This file contains the declarations for the Module class.
static bool skipUnit(const DICompileUnit *CU)
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.
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.
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.
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.
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.
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 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<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)