22#include "llvm/Config/llvm-config.h"
38#define DEBUG_TYPE "lexicalscopes"
46 CurrentFnLexicalScope =
nullptr;
47 LexicalScopeMap.clear();
48 AbstractScopeMap.clear();
49 InlinedLexicalScopeMap.clear();
50 AbstractScopesList.clear();
51 DominatedBlocks.clear();
61 extractLexicalScopes(MIRanges);
62 if (CurrentFnLexicalScope) {
63 constructScopeNest(CurrentFnLexicalScope);
64 assignInstructionRanges(MIRanges);
70void LexicalScopes::extractLexicalScopes(
73 for (
const auto &
MBB : *MF) {
77 for (
const auto &MInsn :
MBB) {
80 if (MInsn.isMetaInstruction())
101 {
InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
105 RangeBeginMI = &MInsn;
113 if (RangeBeginMI && PrevMI && PrevDL)
115 {
InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
128 Scope = Scope->getNonLexicalBlockFileScope();
130 if (
auto *IA =
DL->getInlinedAt()) {
131 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
132 return I != InlinedLexicalScopeMap.end() ? &
I->second :
nullptr;
143 if (
skipUnit(Scope->getSubprogram()->getUnit()))
144 return getOrCreateLexicalScope(IA);
148 return getOrCreateInlinedScope(Scope, IA);
151 return getOrCreateRegularScope(Scope);
156LexicalScopes::getOrCreateRegularScope(
const DILocalScope *Scope) {
157 assert(Scope &&
"Invalid Scope encoding!");
160 auto I = LexicalScopeMap.find(Scope);
161 if (
I != LexicalScopeMap.end())
165 LexicalScope *Parent =
nullptr;
167 Parent = getOrCreateLexicalScope(
Block->getScope());
168 I = LexicalScopeMap.emplace(std::piecewise_construct,
169 std::forward_as_tuple(Scope),
170 std::forward_as_tuple(Parent, Scope,
nullptr,
175 assert(!CurrentFnLexicalScope);
176 CurrentFnLexicalScope = &
I->second;
184LexicalScopes::getOrCreateInlinedScope(
const DILocalScope *Scope,
186 assert(Scope &&
"Invalid Scope encoding!");
188 std::pair<const DILocalScope *, const DILocation *>
P(Scope, InlinedAt);
189 auto I = InlinedLexicalScopeMap.find(
P);
190 if (
I != InlinedLexicalScopeMap.end())
193 LexicalScope *Parent;
195 Parent = getOrCreateInlinedScope(
Block->getScope(), InlinedAt);
197 Parent = getOrCreateLexicalScope(InlinedAt);
199 I = InlinedLexicalScopeMap
200 .emplace(std::piecewise_construct, std::forward_as_tuple(
P),
201 std::forward_as_tuple(Parent, Scope, InlinedAt,
false))
209 assert(Scope &&
"Invalid Scope encoding!");
210 Scope = Scope->getNonLexicalBlockFileScope();
211 auto I = AbstractScopeMap.find(Scope);
212 if (
I != AbstractScopeMap.end())
220 I = AbstractScopeMap.emplace(std::piecewise_construct,
221 std::forward_as_tuple(Scope),
222 std::forward_as_tuple(Parent, Scope,
223 nullptr,
true)).first;
225 AbstractScopesList.push_back(&
I->second);
232void LexicalScopes::constructScopeNest(
LexicalScope *Scope) {
233 assert(Scope &&
"Unable to calculate scope dominance graph!");
235 WorkStack.
push_back(std::make_pair(Scope, 0));
236 unsigned Counter = 0;
237 while (!WorkStack.
empty()) {
238 auto &ScopePosition = WorkStack.
back();
240 size_t ChildNum = ScopePosition.second++;
242 if (ChildNum < Children.size()) {
243 auto &ChildScope = Children[ChildNum];
244 WorkStack.
push_back(std::make_pair(ChildScope, 0));
245 ChildScope->setDFSIn(++Counter);
255void LexicalScopes::assignInstructionRanges(
256 ArrayRef<std::pair<InsnRange, LexicalScope *>> MIRanges) {
257 LexicalScope *PrevLexicalScope =
nullptr;
258 for (
auto [R, S] : MIRanges) {
259 assert(S &&
"Lost LexicalScope for a machine instruction!");
260 if (PrevLexicalScope && !PrevLexicalScope->
dominates(S))
262 S->openInsnRange(
R.first);
263 S->extendInsnRange(
R.second);
264 PrevLexicalScope = S;
267 if (PrevLexicalScope)
276 assert(MF &&
"Method called on a uninitialized LexicalScopes object!");
283 if (Scope == CurrentFnLexicalScope) {
292 for (
auto &R : InsnRanges)
293 for (
auto CurMBBIt = R.first->getParent()->getIterator(),
294 EndBBIt = std::next(R.second->getParent()->getIterator());
295 CurMBBIt != EndBBIt; CurMBBIt++)
300 assert(MF &&
"Unexpected uninitialized LexicalScopes object!");
306 if (Scope == CurrentFnLexicalScope &&
MBB->getParent() == MF)
315 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[
DL];
317 Set = std::make_unique<BlockSetT>();
320 return Set->contains(
MBB);
323#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
327 err <<
"DFSIn: " << DFSIn <<
" DFSOut: " << DFSOut <<
"\n";
332 err << std::string(Indent,
' ') <<
"Abstract Scope\n";
334 if (!Children.empty())
335 err << std::string(Indent + 2,
' ') <<
"Children ...\n";
338 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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
DISubprogram * getSubprogram() const
Get the attached subprogram.
This class is used to track scope information.
SmallVectorImpl< LexicalScope * > & getChildren()
LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A)
void setDFSOut(unsigned O)
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 resetFunction()
Reset the instance so that it's prepared for another function.
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)