1e1649c31SDevang Patel //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===// 2e1649c31SDevang Patel // 3e1649c31SDevang Patel // The LLVM Compiler Infrastructure 4e1649c31SDevang Patel // 5e1649c31SDevang Patel // This file is distributed under the University of Illinois Open Source 6e1649c31SDevang Patel // License. See LICENSE.TXT for details. 7e1649c31SDevang Patel // 8e1649c31SDevang Patel //===----------------------------------------------------------------------===// 9e1649c31SDevang Patel // 10e1649c31SDevang Patel // This file implements LexicalScopes analysis. 11e1649c31SDevang Patel // 12e1649c31SDevang Patel // This pass collects lexical scope information and maps machine instructions 13e1649c31SDevang Patel // to respective lexical scopes. 14e1649c31SDevang Patel // 15e1649c31SDevang Patel //===----------------------------------------------------------------------===// 16e1649c31SDevang Patel 17*5db84df7SEugene Zelenko #include "llvm/ADT/DenseMap.h" 18*5db84df7SEugene Zelenko #include "llvm/ADT/SmallVector.h" 19e1649c31SDevang Patel #include "llvm/CodeGen/LexicalScopes.h" 20*5db84df7SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h" 21e1649c31SDevang Patel #include "llvm/CodeGen/MachineFunction.h" 22e1649c31SDevang Patel #include "llvm/CodeGen/MachineInstr.h" 23*5db84df7SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h" 24*5db84df7SEugene Zelenko #include "llvm/IR/Metadata.h" 25*5db84df7SEugene Zelenko #include "llvm/Support/Casting.h" 26*5db84df7SEugene Zelenko #include "llvm/Support/Compiler.h" 27e1649c31SDevang Patel #include "llvm/Support/Debug.h" 28*5db84df7SEugene Zelenko #include "llvm/Support/raw_ostream.h" 29*5db84df7SEugene Zelenko #include <cassert> 30*5db84df7SEugene Zelenko #include <string> 31*5db84df7SEugene Zelenko #include <tuple> 32*5db84df7SEugene Zelenko #include <utility> 33*5db84df7SEugene Zelenko 34e1649c31SDevang Patel using namespace llvm; 35e1649c31SDevang Patel 361b9dde08SChandler Carruth #define DEBUG_TYPE "lexicalscopes" 371b9dde08SChandler Carruth 38b7dee8a6SEric Christopher /// reset - Reset the instance so that it's prepared for another function. 39b7dee8a6SEric Christopher void LexicalScopes::reset() { 40c0196b1bSCraig Topper MF = nullptr; 41c0196b1bSCraig Topper CurrentFnLexicalScope = nullptr; 422f143e0cSDavid Blaikie LexicalScopeMap.clear(); 432f143e0cSDavid Blaikie AbstractScopeMap.clear(); 44e1649c31SDevang Patel InlinedLexicalScopeMap.clear(); 45e1649c31SDevang Patel AbstractScopesList.clear(); 46e1649c31SDevang Patel } 47e1649c31SDevang Patel 48e1649c31SDevang Patel /// initialize - Scan machine function and constuct lexical scope nest. 49e1649c31SDevang Patel void LexicalScopes::initialize(const MachineFunction &Fn) { 5076b5b749STeresa Johnson // Don't attempt any lexical scope creation for a NoDebug compile unit. 5176b5b749STeresa Johnson if (Fn.getFunction()->getSubprogram()->getUnit()->getEmissionKind() == 5276b5b749STeresa Johnson DICompileUnit::NoDebug) 5376b5b749STeresa Johnson return; 54b7dee8a6SEric Christopher reset(); 55e1649c31SDevang Patel MF = &Fn; 56e1649c31SDevang Patel SmallVector<InsnRange, 4> MIRanges; 57e1649c31SDevang Patel DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap; 58e1649c31SDevang Patel extractLexicalScopes(MIRanges, MI2ScopeMap); 59e1649c31SDevang Patel if (CurrentFnLexicalScope) { 60e1649c31SDevang Patel constructScopeNest(CurrentFnLexicalScope); 61e1649c31SDevang Patel assignInstructionRanges(MIRanges, MI2ScopeMap); 62e1649c31SDevang Patel } 63e1649c31SDevang Patel } 64e1649c31SDevang Patel 65e1649c31SDevang Patel /// extractLexicalScopes - Extract instruction ranges for each lexical scopes 66e1649c31SDevang Patel /// for the given machine function. 676211e4b9SEric Christopher void LexicalScopes::extractLexicalScopes( 686211e4b9SEric Christopher SmallVectorImpl<InsnRange> &MIRanges, 69e1649c31SDevang Patel DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { 70e1649c31SDevang Patel // Scan each instruction and create scopes. First build working set of scopes. 7141b977dfSAlexey Samsonov for (const auto &MBB : *MF) { 72c0196b1bSCraig Topper const MachineInstr *RangeBeginMI = nullptr; 73c0196b1bSCraig Topper const MachineInstr *PrevMI = nullptr; 74a9308c49SDuncan P. N. Exon Smith const DILocation *PrevDL = nullptr; 75f74bde67SAlexey Samsonov for (const auto &MInsn : MBB) { 76e1649c31SDevang Patel // Check if instruction has valid location information. 77a9308c49SDuncan P. N. Exon Smith const DILocation *MIDL = MInsn.getDebugLoc(); 789dffcd04SDuncan P. N. Exon Smith if (!MIDL) { 79f74bde67SAlexey Samsonov PrevMI = &MInsn; 80e1649c31SDevang Patel continue; 81e1649c31SDevang Patel } 82e1649c31SDevang Patel 83e1649c31SDevang Patel // If scope has not changed then skip this instruction. 84e1649c31SDevang Patel if (MIDL == PrevDL) { 85f74bde67SAlexey Samsonov PrevMI = &MInsn; 86e1649c31SDevang Patel continue; 87e1649c31SDevang Patel } 88e1649c31SDevang Patel 89e1649c31SDevang Patel // Ignore DBG_VALUE. It does not contribute to any instruction in output. 90f74bde67SAlexey Samsonov if (MInsn.isDebugValue()) 91e1649c31SDevang Patel continue; 92e1649c31SDevang Patel 93e1649c31SDevang Patel if (RangeBeginMI) { 94e1649c31SDevang Patel // If we have already seen a beginning of an instruction range and 95e1649c31SDevang Patel // current instruction scope does not match scope of first instruction 96e1649c31SDevang Patel // in this range then create a new instruction range. 97e1649c31SDevang Patel InsnRange R(RangeBeginMI, PrevMI); 98e1649c31SDevang Patel MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); 99e1649c31SDevang Patel MIRanges.push_back(R); 100e1649c31SDevang Patel } 101e1649c31SDevang Patel 102e1649c31SDevang Patel // This is a beginning of a new instruction range. 103f74bde67SAlexey Samsonov RangeBeginMI = &MInsn; 104e1649c31SDevang Patel 105e1649c31SDevang Patel // Reset previous markers. 106f74bde67SAlexey Samsonov PrevMI = &MInsn; 107e1649c31SDevang Patel PrevDL = MIDL; 108e1649c31SDevang Patel } 109e1649c31SDevang Patel 110e1649c31SDevang Patel // Create last instruction range. 1119dffcd04SDuncan P. N. Exon Smith if (RangeBeginMI && PrevMI && PrevDL) { 112e1649c31SDevang Patel InsnRange R(RangeBeginMI, PrevMI); 113e1649c31SDevang Patel MIRanges.push_back(R); 114e1649c31SDevang Patel MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); 115e1649c31SDevang Patel } 116e1649c31SDevang Patel } 117e1649c31SDevang Patel } 118e1649c31SDevang Patel 119e1649c31SDevang Patel /// findLexicalScope - Find lexical scope, either regular or inlined, for the 120e1649c31SDevang Patel /// given DebugLoc. Return NULL if not found. 121a9308c49SDuncan P. N. Exon Smith LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) { 122a9308c49SDuncan P. N. Exon Smith DILocalScope *Scope = DL->getScope(); 1236211e4b9SEric Christopher if (!Scope) 124c0196b1bSCraig Topper return nullptr; 1256647b830SEric Christopher 1266647b830SEric Christopher // The scope that we were created with could have an extra file - which 1276647b830SEric Christopher // isn't what we care about in this case. 128a5ba9914SAmjad Aboud Scope = Scope->getNonLexicalBlockFileScope(); 1296647b830SEric Christopher 1305a227fffSDuncan P. N. Exon Smith if (auto *IA = DL->getInlinedAt()) { 1319b8c8cdaSDavid Blaikie auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA)); 1329b8c8cdaSDavid Blaikie return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; 1339b8c8cdaSDavid Blaikie } 1342f143e0cSDavid Blaikie return findLexicalScope(Scope); 135e1649c31SDevang Patel } 136e1649c31SDevang Patel 137e1649c31SDevang Patel /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If 138e1649c31SDevang Patel /// not available then create new lexical scope. 139a9308c49SDuncan P. N. Exon Smith LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope, 140a9308c49SDuncan P. N. Exon Smith const DILocation *IA) { 14182eba746SDuncan P. N. Exon Smith if (IA) { 14276b5b749STeresa Johnson // Skip scopes inlined from a NoDebug compile unit. 14376b5b749STeresa Johnson if (Scope->getSubprogram()->getUnit()->getEmissionKind() == 14476b5b749STeresa Johnson DICompileUnit::NoDebug) 14576b5b749STeresa Johnson return getOrCreateLexicalScope(IA); 146e1649c31SDevang Patel // Create an abstract scope for inlined function. 147e1649c31SDevang Patel getOrCreateAbstractScope(Scope); 148e1649c31SDevang Patel // Create an inlined scope for inlined function. 14982eba746SDuncan P. N. Exon Smith return getOrCreateInlinedScope(Scope, IA); 150e1649c31SDevang Patel } 151e1649c31SDevang Patel 152e1649c31SDevang Patel return getOrCreateRegularScope(Scope); 153e1649c31SDevang Patel } 154e1649c31SDevang Patel 155e1649c31SDevang Patel /// getOrCreateRegularScope - Find or create a regular lexical scope. 15633af7a8fSDuncan P. N. Exon Smith LexicalScope * 157a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) { 158a5ba9914SAmjad Aboud assert(Scope && "Invalid Scope encoding!"); 159a5ba9914SAmjad Aboud Scope = Scope->getNonLexicalBlockFileScope(); 1606647b830SEric Christopher 1612f143e0cSDavid Blaikie auto I = LexicalScopeMap.find(Scope); 1622f143e0cSDavid Blaikie if (I != LexicalScopeMap.end()) 1632f143e0cSDavid Blaikie return &I->second; 164e1649c31SDevang Patel 165a9308c49SDuncan P. N. Exon Smith // FIXME: Should the following dyn_cast be DILexicalBlock? 166c0196b1bSCraig Topper LexicalScope *Parent = nullptr; 167a9308c49SDuncan P. N. Exon Smith if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 16882eba746SDuncan P. N. Exon Smith Parent = getOrCreateLexicalScope(Block->getScope()); 169f17583eeSAaron Ballman I = LexicalScopeMap.emplace(std::piecewise_construct, 170f17583eeSAaron Ballman std::forward_as_tuple(Scope), 17133af7a8fSDuncan P. N. Exon Smith std::forward_as_tuple(Parent, Scope, nullptr, 17233af7a8fSDuncan P. N. Exon Smith false)).first; 1732f143e0cSDavid Blaikie 1743dfe4788SDavid Blaikie if (!Parent) { 175a9308c49SDuncan P. N. Exon Smith assert(cast<DISubprogram>(Scope)->describes(MF->getFunction())); 1763dfe4788SDavid Blaikie assert(!CurrentFnLexicalScope); 1772f143e0cSDavid Blaikie CurrentFnLexicalScope = &I->second; 1783dfe4788SDavid Blaikie } 179e1649c31SDevang Patel 1802f143e0cSDavid Blaikie return &I->second; 181e1649c31SDevang Patel } 182e1649c31SDevang Patel 183e1649c31SDevang Patel /// getOrCreateInlinedScope - Find or create an inlined lexical scope. 18433af7a8fSDuncan P. N. Exon Smith LexicalScope * 185a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope, 186a9308c49SDuncan P. N. Exon Smith const DILocation *InlinedAt) { 187a5ba9914SAmjad Aboud assert(Scope && "Invalid Scope encoding!"); 188a5ba9914SAmjad Aboud Scope = Scope->getNonLexicalBlockFileScope(); 189a9308c49SDuncan P. N. Exon Smith std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt); 1909b8c8cdaSDavid Blaikie auto I = InlinedLexicalScopeMap.find(P); 1919b8c8cdaSDavid Blaikie if (I != InlinedLexicalScopeMap.end()) 1922f143e0cSDavid Blaikie return &I->second; 193e1649c31SDevang Patel 1949b8c8cdaSDavid Blaikie LexicalScope *Parent; 195a9308c49SDuncan P. N. Exon Smith if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 19633af7a8fSDuncan P. N. Exon Smith Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt); 1979b8c8cdaSDavid Blaikie else 19833af7a8fSDuncan P. N. Exon Smith Parent = getOrCreateLexicalScope(InlinedAt); 1999b8c8cdaSDavid Blaikie 20014303d18SEric Christopher I = InlinedLexicalScopeMap 20114303d18SEric Christopher .emplace(std::piecewise_construct, std::forward_as_tuple(P), 20214303d18SEric Christopher std::forward_as_tuple(Parent, Scope, InlinedAt, false)) 203f17583eeSAaron Ballman .first; 2042f143e0cSDavid Blaikie return &I->second; 205e1649c31SDevang Patel } 206e1649c31SDevang Patel 207e1649c31SDevang Patel /// getOrCreateAbstractScope - Find or create an abstract lexical scope. 20833af7a8fSDuncan P. N. Exon Smith LexicalScope * 209a9308c49SDuncan P. N. Exon Smith LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) { 21033af7a8fSDuncan P. N. Exon Smith assert(Scope && "Invalid Scope encoding!"); 211a5ba9914SAmjad Aboud Scope = Scope->getNonLexicalBlockFileScope(); 212ea862267SDavid Blaikie auto I = AbstractScopeMap.find(Scope); 2132f143e0cSDavid Blaikie if (I != AbstractScopeMap.end()) 2142f143e0cSDavid Blaikie return &I->second; 215e1649c31SDevang Patel 216a9308c49SDuncan P. N. Exon Smith // FIXME: Should the following isa be DILexicalBlock? 217c0196b1bSCraig Topper LexicalScope *Parent = nullptr; 218a9308c49SDuncan P. N. Exon Smith if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 21933af7a8fSDuncan P. N. Exon Smith Parent = getOrCreateAbstractScope(Block->getScope()); 22033af7a8fSDuncan P. N. Exon Smith 2212f143e0cSDavid Blaikie I = AbstractScopeMap.emplace(std::piecewise_construct, 222ea862267SDavid Blaikie std::forward_as_tuple(Scope), 223ea862267SDavid Blaikie std::forward_as_tuple(Parent, Scope, 2242f143e0cSDavid Blaikie nullptr, true)).first; 225a9308c49SDuncan P. N. Exon Smith if (isa<DISubprogram>(Scope)) 2262f143e0cSDavid Blaikie AbstractScopesList.push_back(&I->second); 2272f143e0cSDavid Blaikie return &I->second; 228e1649c31SDevang Patel } 229e1649c31SDevang Patel 230e1649c31SDevang Patel /// constructScopeNest 231e1649c31SDevang Patel void LexicalScopes::constructScopeNest(LexicalScope *Scope) { 232e1649c31SDevang Patel assert(Scope && "Unable to calculate scope dominance graph!"); 233e1649c31SDevang Patel SmallVector<LexicalScope *, 4> WorkStack; 234e1649c31SDevang Patel WorkStack.push_back(Scope); 235e1649c31SDevang Patel unsigned Counter = 0; 236e1649c31SDevang Patel while (!WorkStack.empty()) { 237e1649c31SDevang Patel LexicalScope *WS = WorkStack.back(); 23880170e54SCraig Topper const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); 239e1649c31SDevang Patel bool visitedChildren = false; 24016b2ace0SAdrian Prantl for (auto &ChildScope : Children) 241e1649c31SDevang Patel if (!ChildScope->getDFSOut()) { 242e1649c31SDevang Patel WorkStack.push_back(ChildScope); 243e1649c31SDevang Patel visitedChildren = true; 244e1649c31SDevang Patel ChildScope->setDFSIn(++Counter); 245e1649c31SDevang Patel break; 246e1649c31SDevang Patel } 247e1649c31SDevang Patel if (!visitedChildren) { 248e1649c31SDevang Patel WorkStack.pop_back(); 249e1649c31SDevang Patel WS->setDFSOut(++Counter); 250e1649c31SDevang Patel } 251e1649c31SDevang Patel } 252e1649c31SDevang Patel } 253e1649c31SDevang Patel 254784077ebSDevang Patel /// assignInstructionRanges - Find ranges of instructions covered by each 255784077ebSDevang Patel /// lexical scope. 2566211e4b9SEric Christopher void LexicalScopes::assignInstructionRanges( 2576211e4b9SEric Christopher SmallVectorImpl<InsnRange> &MIRanges, 2586211e4b9SEric Christopher DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { 259c0196b1bSCraig Topper LexicalScope *PrevLexicalScope = nullptr; 26016b2ace0SAdrian Prantl for (const auto &R : MIRanges) { 261e1649c31SDevang Patel LexicalScope *S = MI2ScopeMap.lookup(R.first); 262e1649c31SDevang Patel assert(S && "Lost LexicalScope for a machine instruction!"); 263e1649c31SDevang Patel if (PrevLexicalScope && !PrevLexicalScope->dominates(S)) 264e1649c31SDevang Patel PrevLexicalScope->closeInsnRange(S); 265e1649c31SDevang Patel S->openInsnRange(R.first); 266e1649c31SDevang Patel S->extendInsnRange(R.second); 267e1649c31SDevang Patel PrevLexicalScope = S; 268e1649c31SDevang Patel } 269e1649c31SDevang Patel 270e1649c31SDevang Patel if (PrevLexicalScope) 271e1649c31SDevang Patel PrevLexicalScope->closeInsnRange(); 272e1649c31SDevang Patel } 273e1649c31SDevang Patel 274e1649c31SDevang Patel /// getMachineBasicBlocks - Populate given set using machine basic blocks which 275e1649c31SDevang Patel /// have machine instructions that belong to lexical scope identified by 276e1649c31SDevang Patel /// DebugLoc. 2776211e4b9SEric Christopher void LexicalScopes::getMachineBasicBlocks( 278a9308c49SDuncan P. N. Exon Smith const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) { 279e1649c31SDevang Patel MBBs.clear(); 280e1649c31SDevang Patel LexicalScope *Scope = getOrCreateLexicalScope(DL); 281e1649c31SDevang Patel if (!Scope) 282e1649c31SDevang Patel return; 283e1649c31SDevang Patel 284db4374a2SDevang Patel if (Scope == CurrentFnLexicalScope) { 28541b977dfSAlexey Samsonov for (const auto &MBB : *MF) 28641b977dfSAlexey Samsonov MBBs.insert(&MBB); 287db4374a2SDevang Patel return; 288db4374a2SDevang Patel } 289db4374a2SDevang Patel 29080170e54SCraig Topper SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges(); 29116b2ace0SAdrian Prantl for (auto &R : InsnRanges) 292e1649c31SDevang Patel MBBs.insert(R.first->getParent()); 293e1649c31SDevang Patel } 294e1649c31SDevang Patel 295e1649c31SDevang Patel /// dominates - Return true if DebugLoc's lexical scope dominates at least one 296e1649c31SDevang Patel /// machine instruction's lexical scope in a given machine basic block. 297a9308c49SDuncan P. N. Exon Smith bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) { 298e1649c31SDevang Patel LexicalScope *Scope = getOrCreateLexicalScope(DL); 299e1649c31SDevang Patel if (!Scope) 300e1649c31SDevang Patel return false; 301db4374a2SDevang Patel 302db4374a2SDevang Patel // Current function scope covers all basic blocks in the function. 303db4374a2SDevang Patel if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF) 304db4374a2SDevang Patel return true; 305db4374a2SDevang Patel 306e1649c31SDevang Patel bool Result = false; 30716b2ace0SAdrian Prantl for (auto &I : *MBB) { 30816b2ace0SAdrian Prantl if (const DILocation *IDL = I.getDebugLoc()) 309e1649c31SDevang Patel if (LexicalScope *IScope = getOrCreateLexicalScope(IDL)) 310e1649c31SDevang Patel if (Scope->dominates(IScope)) 311e1649c31SDevang Patel return true; 312e1649c31SDevang Patel } 313e1649c31SDevang Patel return Result; 314e1649c31SDevang Patel } 315e1649c31SDevang Patel 3168c209aa8SMatthias Braun #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 3178c209aa8SMatthias Braun LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const { 318e1649c31SDevang Patel raw_ostream &err = dbgs(); 319e498b25bSManman Ren err.indent(Indent); 320e1649c31SDevang Patel err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; 321e1649c31SDevang Patel const MDNode *N = Desc; 322e498b25bSManman Ren err.indent(Indent); 323e1649c31SDevang Patel N->dump(); 324e1649c31SDevang Patel if (AbstractScope) 325e498b25bSManman Ren err << std::string(Indent, ' ') << "Abstract Scope\n"; 326e1649c31SDevang Patel 327e1649c31SDevang Patel if (!Children.empty()) 328e498b25bSManman Ren err << std::string(Indent + 2, ' ') << "Children ...\n"; 329e1649c31SDevang Patel for (unsigned i = 0, e = Children.size(); i != e; ++i) 330e1649c31SDevang Patel if (Children[i] != this) 331e498b25bSManman Ren Children[i]->dump(Indent + 2); 332e1649c31SDevang Patel } 3338c209aa8SMatthias Braun #endif 334