10b57cec5SDimitry Andric //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements LexicalScopes analysis. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // This pass collects lexical scope information and maps machine instructions 120b57cec5SDimitry Andric // to respective lexical scopes. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h" 170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 220b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 230b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 248bcb0991SDimitry Andric #include "llvm/IR/Function.h" 250b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 260b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 270b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 280b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include <cassert> 310b57cec5SDimitry Andric #include <string> 320b57cec5SDimitry Andric #include <tuple> 330b57cec5SDimitry Andric #include <utility> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #define DEBUG_TYPE "lexicalscopes" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// reset - Reset the instance so that it's prepared for another function. 400b57cec5SDimitry Andric void LexicalScopes::reset() { 410b57cec5SDimitry Andric MF = nullptr; 420b57cec5SDimitry Andric CurrentFnLexicalScope = nullptr; 430b57cec5SDimitry Andric LexicalScopeMap.clear(); 440b57cec5SDimitry Andric AbstractScopeMap.clear(); 450b57cec5SDimitry Andric InlinedLexicalScopeMap.clear(); 460b57cec5SDimitry Andric AbstractScopesList.clear(); 475ffd83dbSDimitry Andric DominatedBlocks.clear(); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric /// initialize - Scan machine function and constuct lexical scope nest. 510b57cec5SDimitry Andric void LexicalScopes::initialize(const MachineFunction &Fn) { 520b57cec5SDimitry Andric reset(); 530b57cec5SDimitry Andric // Don't attempt any lexical scope creation for a NoDebug compile unit. 540b57cec5SDimitry Andric if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() == 550b57cec5SDimitry Andric DICompileUnit::NoDebug) 560b57cec5SDimitry Andric return; 570b57cec5SDimitry Andric MF = &Fn; 580b57cec5SDimitry Andric SmallVector<InsnRange, 4> MIRanges; 590b57cec5SDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap; 600b57cec5SDimitry Andric extractLexicalScopes(MIRanges, MI2ScopeMap); 610b57cec5SDimitry Andric if (CurrentFnLexicalScope) { 620b57cec5SDimitry Andric constructScopeNest(CurrentFnLexicalScope); 630b57cec5SDimitry Andric assignInstructionRanges(MIRanges, MI2ScopeMap); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// extractLexicalScopes - Extract instruction ranges for each lexical scopes 680b57cec5SDimitry Andric /// for the given machine function. 690b57cec5SDimitry Andric void LexicalScopes::extractLexicalScopes( 700b57cec5SDimitry Andric SmallVectorImpl<InsnRange> &MIRanges, 710b57cec5SDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { 720b57cec5SDimitry Andric // Scan each instruction and create scopes. First build working set of scopes. 730b57cec5SDimitry Andric for (const auto &MBB : *MF) { 740b57cec5SDimitry Andric const MachineInstr *RangeBeginMI = nullptr; 750b57cec5SDimitry Andric const MachineInstr *PrevMI = nullptr; 760b57cec5SDimitry Andric const DILocation *PrevDL = nullptr; 770b57cec5SDimitry Andric for (const auto &MInsn : MBB) { 78fe6060f1SDimitry Andric // Ignore DBG_VALUE and similar instruction that do not contribute to any 79fe6060f1SDimitry Andric // instruction in the output. 80fe6060f1SDimitry Andric if (MInsn.isMetaInstruction()) 81fe6060f1SDimitry Andric continue; 82fe6060f1SDimitry Andric 830b57cec5SDimitry Andric // Check if instruction has valid location information. 840b57cec5SDimitry Andric const DILocation *MIDL = MInsn.getDebugLoc(); 850b57cec5SDimitry Andric if (!MIDL) { 860b57cec5SDimitry Andric PrevMI = &MInsn; 870b57cec5SDimitry Andric continue; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // If scope has not changed then skip this instruction. 910b57cec5SDimitry Andric if (MIDL == PrevDL) { 920b57cec5SDimitry Andric PrevMI = &MInsn; 930b57cec5SDimitry Andric continue; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric if (RangeBeginMI) { 970b57cec5SDimitry Andric // If we have already seen a beginning of an instruction range and 980b57cec5SDimitry Andric // current instruction scope does not match scope of first instruction 990b57cec5SDimitry Andric // in this range then create a new instruction range. 1000b57cec5SDimitry Andric InsnRange R(RangeBeginMI, PrevMI); 1010b57cec5SDimitry Andric MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); 1020b57cec5SDimitry Andric MIRanges.push_back(R); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // This is a beginning of a new instruction range. 1060b57cec5SDimitry Andric RangeBeginMI = &MInsn; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Reset previous markers. 1090b57cec5SDimitry Andric PrevMI = &MInsn; 1100b57cec5SDimitry Andric PrevDL = MIDL; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // Create last instruction range. 1140b57cec5SDimitry Andric if (RangeBeginMI && PrevMI && PrevDL) { 1150b57cec5SDimitry Andric InsnRange R(RangeBeginMI, PrevMI); 1160b57cec5SDimitry Andric MIRanges.push_back(R); 1170b57cec5SDimitry Andric MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// findLexicalScope - Find lexical scope, either regular or inlined, for the 1230b57cec5SDimitry Andric /// given DebugLoc. Return NULL if not found. 1240b57cec5SDimitry Andric LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) { 1250b57cec5SDimitry Andric DILocalScope *Scope = DL->getScope(); 1260b57cec5SDimitry Andric if (!Scope) 1270b57cec5SDimitry Andric return nullptr; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // The scope that we were created with could have an extra file - which 1300b57cec5SDimitry Andric // isn't what we care about in this case. 1310b57cec5SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric if (auto *IA = DL->getInlinedAt()) { 1340b57cec5SDimitry Andric auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA)); 1350b57cec5SDimitry Andric return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric return findLexicalScope(Scope); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If 1410b57cec5SDimitry Andric /// not available then create new lexical scope. 1420b57cec5SDimitry Andric LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope, 1430b57cec5SDimitry Andric const DILocation *IA) { 1440b57cec5SDimitry Andric if (IA) { 1450b57cec5SDimitry Andric // Skip scopes inlined from a NoDebug compile unit. 1460b57cec5SDimitry Andric if (Scope->getSubprogram()->getUnit()->getEmissionKind() == 1470b57cec5SDimitry Andric DICompileUnit::NoDebug) 1480b57cec5SDimitry Andric return getOrCreateLexicalScope(IA); 1490b57cec5SDimitry Andric // Create an abstract scope for inlined function. 1500b57cec5SDimitry Andric getOrCreateAbstractScope(Scope); 1510b57cec5SDimitry Andric // Create an inlined scope for inlined function. 1520b57cec5SDimitry Andric return getOrCreateInlinedScope(Scope, IA); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric return getOrCreateRegularScope(Scope); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// getOrCreateRegularScope - Find or create a regular lexical scope. 1590b57cec5SDimitry Andric LexicalScope * 1600b57cec5SDimitry Andric LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) { 1610b57cec5SDimitry Andric assert(Scope && "Invalid Scope encoding!"); 1620b57cec5SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope(); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric auto I = LexicalScopeMap.find(Scope); 1650b57cec5SDimitry Andric if (I != LexicalScopeMap.end()) 1660b57cec5SDimitry Andric return &I->second; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric // FIXME: Should the following dyn_cast be DILexicalBlock? 1690b57cec5SDimitry Andric LexicalScope *Parent = nullptr; 1700b57cec5SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 1710b57cec5SDimitry Andric Parent = getOrCreateLexicalScope(Block->getScope()); 1720b57cec5SDimitry Andric I = LexicalScopeMap.emplace(std::piecewise_construct, 1730b57cec5SDimitry Andric std::forward_as_tuple(Scope), 1740b57cec5SDimitry Andric std::forward_as_tuple(Parent, Scope, nullptr, 1750b57cec5SDimitry Andric false)).first; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (!Parent) { 1780b57cec5SDimitry Andric assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction())); 1790b57cec5SDimitry Andric assert(!CurrentFnLexicalScope); 1800b57cec5SDimitry Andric CurrentFnLexicalScope = &I->second; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric return &I->second; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric /// getOrCreateInlinedScope - Find or create an inlined lexical scope. 1870b57cec5SDimitry Andric LexicalScope * 1880b57cec5SDimitry Andric LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope, 1890b57cec5SDimitry Andric const DILocation *InlinedAt) { 1900b57cec5SDimitry Andric assert(Scope && "Invalid Scope encoding!"); 1910b57cec5SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope(); 1920b57cec5SDimitry Andric std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt); 1930b57cec5SDimitry Andric auto I = InlinedLexicalScopeMap.find(P); 1940b57cec5SDimitry Andric if (I != InlinedLexicalScopeMap.end()) 1950b57cec5SDimitry Andric return &I->second; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric LexicalScope *Parent; 1980b57cec5SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 1990b57cec5SDimitry Andric Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt); 2000b57cec5SDimitry Andric else 2010b57cec5SDimitry Andric Parent = getOrCreateLexicalScope(InlinedAt); 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric I = InlinedLexicalScopeMap 2040b57cec5SDimitry Andric .emplace(std::piecewise_construct, std::forward_as_tuple(P), 2050b57cec5SDimitry Andric std::forward_as_tuple(Parent, Scope, InlinedAt, false)) 2060b57cec5SDimitry Andric .first; 2070b57cec5SDimitry Andric return &I->second; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric /// getOrCreateAbstractScope - Find or create an abstract lexical scope. 2110b57cec5SDimitry Andric LexicalScope * 2120b57cec5SDimitry Andric LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) { 2130b57cec5SDimitry Andric assert(Scope && "Invalid Scope encoding!"); 2140b57cec5SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope(); 2150b57cec5SDimitry Andric auto I = AbstractScopeMap.find(Scope); 2160b57cec5SDimitry Andric if (I != AbstractScopeMap.end()) 2170b57cec5SDimitry Andric return &I->second; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric // FIXME: Should the following isa be DILexicalBlock? 2200b57cec5SDimitry Andric LexicalScope *Parent = nullptr; 2210b57cec5SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) 2220b57cec5SDimitry Andric Parent = getOrCreateAbstractScope(Block->getScope()); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric I = AbstractScopeMap.emplace(std::piecewise_construct, 2250b57cec5SDimitry Andric std::forward_as_tuple(Scope), 2260b57cec5SDimitry Andric std::forward_as_tuple(Parent, Scope, 2270b57cec5SDimitry Andric nullptr, true)).first; 2280b57cec5SDimitry Andric if (isa<DISubprogram>(Scope)) 2290b57cec5SDimitry Andric AbstractScopesList.push_back(&I->second); 2300b57cec5SDimitry Andric return &I->second; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2335ffd83dbSDimitry Andric /// constructScopeNest - Traverse the Scope tree depth-first, storing 2345ffd83dbSDimitry Andric /// traversal state in WorkStack and recording the depth-first 2355ffd83dbSDimitry Andric /// numbering (setDFSIn, setDFSOut) for edge classification. 2360b57cec5SDimitry Andric void LexicalScopes::constructScopeNest(LexicalScope *Scope) { 2370b57cec5SDimitry Andric assert(Scope && "Unable to calculate scope dominance graph!"); 2385ffd83dbSDimitry Andric SmallVector<std::pair<LexicalScope *, size_t>, 4> WorkStack; 2395ffd83dbSDimitry Andric WorkStack.push_back(std::make_pair(Scope, 0)); 2400b57cec5SDimitry Andric unsigned Counter = 0; 2410b57cec5SDimitry Andric while (!WorkStack.empty()) { 2425ffd83dbSDimitry Andric auto &ScopePosition = WorkStack.back(); 2435ffd83dbSDimitry Andric LexicalScope *WS = ScopePosition.first; 2445ffd83dbSDimitry Andric size_t ChildNum = ScopePosition.second++; 2450b57cec5SDimitry Andric const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); 2465ffd83dbSDimitry Andric if (ChildNum < Children.size()) { 2475ffd83dbSDimitry Andric auto &ChildScope = Children[ChildNum]; 2485ffd83dbSDimitry Andric WorkStack.push_back(std::make_pair(ChildScope, 0)); 2490b57cec5SDimitry Andric ChildScope->setDFSIn(++Counter); 2505ffd83dbSDimitry Andric } else { 2510b57cec5SDimitry Andric WorkStack.pop_back(); 2520b57cec5SDimitry Andric WS->setDFSOut(++Counter); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// assignInstructionRanges - Find ranges of instructions covered by each 2580b57cec5SDimitry Andric /// lexical scope. 2590b57cec5SDimitry Andric void LexicalScopes::assignInstructionRanges( 2600b57cec5SDimitry Andric SmallVectorImpl<InsnRange> &MIRanges, 2610b57cec5SDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { 2620b57cec5SDimitry Andric LexicalScope *PrevLexicalScope = nullptr; 2630b57cec5SDimitry Andric for (const auto &R : MIRanges) { 2640b57cec5SDimitry Andric LexicalScope *S = MI2ScopeMap.lookup(R.first); 2650b57cec5SDimitry Andric assert(S && "Lost LexicalScope for a machine instruction!"); 2660b57cec5SDimitry Andric if (PrevLexicalScope && !PrevLexicalScope->dominates(S)) 2670b57cec5SDimitry Andric PrevLexicalScope->closeInsnRange(S); 2680b57cec5SDimitry Andric S->openInsnRange(R.first); 2690b57cec5SDimitry Andric S->extendInsnRange(R.second); 2700b57cec5SDimitry Andric PrevLexicalScope = S; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric if (PrevLexicalScope) 2740b57cec5SDimitry Andric PrevLexicalScope->closeInsnRange(); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric /// getMachineBasicBlocks - Populate given set using machine basic blocks which 2780b57cec5SDimitry Andric /// have machine instructions that belong to lexical scope identified by 2790b57cec5SDimitry Andric /// DebugLoc. 2800b57cec5SDimitry Andric void LexicalScopes::getMachineBasicBlocks( 2810b57cec5SDimitry Andric const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) { 2820b57cec5SDimitry Andric assert(MF && "Method called on a uninitialized LexicalScopes object!"); 2830b57cec5SDimitry Andric MBBs.clear(); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric LexicalScope *Scope = getOrCreateLexicalScope(DL); 2860b57cec5SDimitry Andric if (!Scope) 2870b57cec5SDimitry Andric return; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric if (Scope == CurrentFnLexicalScope) { 2900b57cec5SDimitry Andric for (const auto &MBB : *MF) 2910b57cec5SDimitry Andric MBBs.insert(&MBB); 2920b57cec5SDimitry Andric return; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2955ffd83dbSDimitry Andric // The scope ranges can cover multiple basic blocks in each span. Iterate over 2965ffd83dbSDimitry Andric // all blocks (in the order they are in the function) until we reach the one 2975ffd83dbSDimitry Andric // containing the end of the span. 2980b57cec5SDimitry Andric SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges(); 2990b57cec5SDimitry Andric for (auto &R : InsnRanges) 3005ffd83dbSDimitry Andric for (auto CurMBBIt = R.first->getParent()->getIterator(), 3015ffd83dbSDimitry Andric EndBBIt = std::next(R.second->getParent()->getIterator()); 3025ffd83dbSDimitry Andric CurMBBIt != EndBBIt; CurMBBIt++) 3035ffd83dbSDimitry Andric MBBs.insert(&*CurMBBIt); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) { 3070b57cec5SDimitry Andric assert(MF && "Unexpected uninitialized LexicalScopes object!"); 3080b57cec5SDimitry Andric LexicalScope *Scope = getOrCreateLexicalScope(DL); 3090b57cec5SDimitry Andric if (!Scope) 3100b57cec5SDimitry Andric return false; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // Current function scope covers all basic blocks in the function. 3130b57cec5SDimitry Andric if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF) 3140b57cec5SDimitry Andric return true; 3150b57cec5SDimitry Andric 3165ffd83dbSDimitry Andric // Fetch all the blocks in DLs scope. Because the range / block list also 3175ffd83dbSDimitry Andric // contain any subscopes, any instruction that DL dominates can be found in 3185ffd83dbSDimitry Andric // the block set. 3195ffd83dbSDimitry Andric // 3205ffd83dbSDimitry Andric // Cache the set of fetched blocks to avoid repeatedly recomputing the set in 3215ffd83dbSDimitry Andric // the LiveDebugValues pass. 3225ffd83dbSDimitry Andric std::unique_ptr<BlockSetT> &Set = DominatedBlocks[DL]; 3235ffd83dbSDimitry Andric if (!Set) { 3245ffd83dbSDimitry Andric Set = std::make_unique<BlockSetT>(); 3255ffd83dbSDimitry Andric getMachineBasicBlocks(DL, *Set); 3260b57cec5SDimitry Andric } 327e8d8bef9SDimitry Andric return Set->contains(MBB); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 3310b57cec5SDimitry Andric LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const { 3320b57cec5SDimitry Andric raw_ostream &err = dbgs(); 3330b57cec5SDimitry Andric err.indent(Indent); 3340b57cec5SDimitry Andric err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; 3350b57cec5SDimitry Andric const MDNode *N = Desc; 3360b57cec5SDimitry Andric err.indent(Indent); 3370b57cec5SDimitry Andric N->dump(); 3380b57cec5SDimitry Andric if (AbstractScope) 3390b57cec5SDimitry Andric err << std::string(Indent, ' ') << "Abstract Scope\n"; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric if (!Children.empty()) 3420b57cec5SDimitry Andric err << std::string(Indent + 2, ' ') << "Children ...\n"; 343*0fca6ea1SDimitry Andric for (const LexicalScope *Child : Children) 344*0fca6ea1SDimitry Andric if (Child != this) 345*0fca6ea1SDimitry Andric Child->dump(Indent + 2); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric #endif 348