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())))
75 extractLexicalScopes(MIRanges);
76 if (CurrentFnLexicalScope) {
77 constructScopeNest(CurrentFnLexicalScope);
78 assignInstructionRanges(MIRanges);
84void LexicalScopes::extractLexicalScopes(
87 for (
const auto &
MBB : *MF) {
91 for (
const auto &MInsn :
MBB) {
94 if (MInsn.isMetaInstruction())
105 if (MIDL == PrevDL) {
115 {
InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
119 RangeBeginMI = &MInsn;
127 if (RangeBeginMI && PrevMI && PrevDL)
129 {
InsnRange(RangeBeginMI, PrevMI), getOrCreateLexicalScope(PrevDL)});
142 Scope = Scope->getNonLexicalBlockFileScope();
144 if (
auto *IA =
DL->getInlinedAt()) {
145 auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
146 return I != InlinedLexicalScopeMap.end() ? &
I->second :
nullptr;
157 if (
skipUnit(Scope->getSubprogram()->getUnit()))
158 return getOrCreateLexicalScope(IA);
162 return getOrCreateInlinedScope(Scope, IA);
165 return getOrCreateRegularScope(Scope);
170LexicalScopes::getOrCreateRegularScope(
const DILocalScope *Scope) {
171 assert(Scope &&
"Invalid Scope encoding!");
174 auto I = LexicalScopeMap.find(Scope);
175 if (
I != LexicalScopeMap.end())
179 LexicalScope *Parent =
nullptr;
181 Parent = getOrCreateLexicalScope(
Block->getScope());
182 I = LexicalScopeMap.emplace(std::piecewise_construct,
183 std::forward_as_tuple(Scope),
184 std::forward_as_tuple(Parent, Scope,
nullptr,
189 assert(!CurrentFnLexicalScope);
190 CurrentFnLexicalScope = &
I->second;
198LexicalScopes::getOrCreateInlinedScope(
const DILocalScope *Scope,
200 assert(Scope &&
"Invalid Scope encoding!");
202 std::pair<const DILocalScope *, const DILocation *>
P(Scope, InlinedAt);
203 auto I = InlinedLexicalScopeMap.find(
P);
204 if (
I != InlinedLexicalScopeMap.end())
207 LexicalScope *Parent;
209 Parent = getOrCreateInlinedScope(
Block->getScope(), InlinedAt);
211 Parent = getOrCreateLexicalScope(InlinedAt);
213 I = InlinedLexicalScopeMap
214 .emplace(std::piecewise_construct, std::forward_as_tuple(
P),
215 std::forward_as_tuple(Parent, Scope, InlinedAt,
false))
223 assert(Scope &&
"Invalid Scope encoding!");
224 Scope = Scope->getNonLexicalBlockFileScope();
225 auto I = AbstractScopeMap.find(Scope);
226 if (
I != AbstractScopeMap.end())
234 I = AbstractScopeMap.emplace(std::piecewise_construct,
235 std::forward_as_tuple(Scope),
236 std::forward_as_tuple(Parent, Scope,
237 nullptr,
true)).first;
239 AbstractScopesList.push_back(&
I->second);
246void LexicalScopes::constructScopeNest(
LexicalScope *Scope) {
247 assert(Scope &&
"Unable to calculate scope dominance graph!");
249 WorkStack.
push_back(std::make_pair(Scope, 0));
250 unsigned Counter = 0;
251 while (!WorkStack.
empty()) {
252 auto &ScopePosition = WorkStack.
back();
254 size_t ChildNum = ScopePosition.second++;
256 if (ChildNum < Children.size()) {
257 auto &ChildScope = Children[ChildNum];
258 WorkStack.
push_back(std::make_pair(ChildScope, 0));
259 ChildScope->setDFSIn(++Counter);
269void LexicalScopes::assignInstructionRanges(
270 ArrayRef<std::pair<InsnRange, LexicalScope *>> MIRanges) {
271 LexicalScope *PrevLexicalScope =
nullptr;
272 for (
auto [R, S] : MIRanges) {
273 assert(S &&
"Lost LexicalScope for a machine instruction!");
274 if (PrevLexicalScope && !PrevLexicalScope->
dominates(S))
276 S->openInsnRange(
R.first);
277 S->extendInsnRange(
R.second);
278 PrevLexicalScope = S;
281 if (PrevLexicalScope)
290 assert(MF &&
"Method called on a uninitialized LexicalScopes object!");
297 if (Scope == CurrentFnLexicalScope) {
306 for (
auto &R : InsnRanges)
307 for (
auto CurMBBIt = R.first->getParent()->getIterator(),
308 EndBBIt = std::next(R.second->getParent()->getIterator());
309 CurMBBIt != EndBBIt; CurMBBIt++)
314 assert(MF &&
"Unexpected uninitialized LexicalScopes object!");
320 if (Scope == CurrentFnLexicalScope &&
MBB->getParent() == MF)
329 std::unique_ptr<BlockSetT> &Set = DominatedBlocks[
DL];
331 Set = std::make_unique<BlockSetT>();
334 return Set->contains(
MBB);
337#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
341 err <<
"DFSIn: " << DFSIn <<
" DFSOut: " << DFSOut <<
"\n";
346 err << std::string(Indent,
' ') <<
"Abstract Scope\n";
348 if (!Children.empty())
349 err << std::string(Indent + 2,
' ') <<
"Children ...\n";
352 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),...
Subprogram description. Uses SubclassData1.
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 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)