16122f3e6SDimitry Andric //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===//
26122f3e6SDimitry Andric //
36122f3e6SDimitry Andric // The LLVM Compiler Infrastructure
46122f3e6SDimitry Andric //
56122f3e6SDimitry Andric // This file is distributed under the University of Illinois Open Source
66122f3e6SDimitry Andric // License. See LICENSE.TXT for details.
76122f3e6SDimitry Andric //
86122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
96122f3e6SDimitry Andric //
106122f3e6SDimitry Andric // This file implements LexicalScopes analysis.
116122f3e6SDimitry Andric //
126122f3e6SDimitry Andric // This pass collects lexical scope information and maps machine instructions
136122f3e6SDimitry Andric // to respective lexical scopes.
146122f3e6SDimitry Andric //
156122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
166122f3e6SDimitry Andric
17db17bf38SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h"
187a7e6055SDimitry Andric #include "llvm/ADT/DenseMap.h"
197a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
207a7e6055SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
216122f3e6SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
226122f3e6SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
23*4ba319b5SDimitry Andric #include "llvm/Config/llvm-config.h"
247a7e6055SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
257a7e6055SDimitry Andric #include "llvm/IR/Metadata.h"
267a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
277a7e6055SDimitry Andric #include "llvm/Support/Compiler.h"
286122f3e6SDimitry Andric #include "llvm/Support/Debug.h"
297a7e6055SDimitry Andric #include "llvm/Support/raw_ostream.h"
307a7e6055SDimitry Andric #include <cassert>
317a7e6055SDimitry Andric #include <string>
327a7e6055SDimitry Andric #include <tuple>
337a7e6055SDimitry Andric #include <utility>
347a7e6055SDimitry Andric
356122f3e6SDimitry Andric using namespace llvm;
366122f3e6SDimitry Andric
3791bc56edSDimitry Andric #define DEBUG_TYPE "lexicalscopes"
386122f3e6SDimitry Andric
3991bc56edSDimitry Andric /// reset - Reset the instance so that it's prepared for another function.
reset()4091bc56edSDimitry Andric void LexicalScopes::reset() {
4191bc56edSDimitry Andric MF = nullptr;
4291bc56edSDimitry Andric CurrentFnLexicalScope = nullptr;
4391bc56edSDimitry Andric LexicalScopeMap.clear();
4491bc56edSDimitry Andric AbstractScopeMap.clear();
456122f3e6SDimitry Andric InlinedLexicalScopeMap.clear();
466122f3e6SDimitry Andric AbstractScopesList.clear();
476122f3e6SDimitry Andric }
486122f3e6SDimitry Andric
496122f3e6SDimitry Andric /// initialize - Scan machine function and constuct lexical scope nest.
initialize(const MachineFunction & Fn)506122f3e6SDimitry Andric void LexicalScopes::initialize(const MachineFunction &Fn) {
512cab237bSDimitry Andric reset();
527a7e6055SDimitry Andric // Don't attempt any lexical scope creation for a NoDebug compile unit.
532cab237bSDimitry Andric if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() ==
547a7e6055SDimitry Andric DICompileUnit::NoDebug)
557a7e6055SDimitry Andric return;
566122f3e6SDimitry Andric MF = &Fn;
576122f3e6SDimitry Andric SmallVector<InsnRange, 4> MIRanges;
586122f3e6SDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap;
596122f3e6SDimitry Andric extractLexicalScopes(MIRanges, MI2ScopeMap);
606122f3e6SDimitry Andric if (CurrentFnLexicalScope) {
616122f3e6SDimitry Andric constructScopeNest(CurrentFnLexicalScope);
626122f3e6SDimitry Andric assignInstructionRanges(MIRanges, MI2ScopeMap);
636122f3e6SDimitry Andric }
646122f3e6SDimitry Andric }
656122f3e6SDimitry Andric
666122f3e6SDimitry Andric /// extractLexicalScopes - Extract instruction ranges for each lexical scopes
676122f3e6SDimitry Andric /// for the given machine function.
extractLexicalScopes(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)6891bc56edSDimitry Andric void LexicalScopes::extractLexicalScopes(
6991bc56edSDimitry Andric SmallVectorImpl<InsnRange> &MIRanges,
706122f3e6SDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
716122f3e6SDimitry Andric // Scan each instruction and create scopes. First build working set of scopes.
7291bc56edSDimitry Andric for (const auto &MBB : *MF) {
7391bc56edSDimitry Andric const MachineInstr *RangeBeginMI = nullptr;
7491bc56edSDimitry Andric const MachineInstr *PrevMI = nullptr;
75ff0cc061SDimitry Andric const DILocation *PrevDL = nullptr;
7691bc56edSDimitry Andric for (const auto &MInsn : MBB) {
776122f3e6SDimitry Andric // Check if instruction has valid location information.
78ff0cc061SDimitry Andric const DILocation *MIDL = MInsn.getDebugLoc();
79ff0cc061SDimitry Andric if (!MIDL) {
8091bc56edSDimitry Andric PrevMI = &MInsn;
816122f3e6SDimitry Andric continue;
826122f3e6SDimitry Andric }
836122f3e6SDimitry Andric
846122f3e6SDimitry Andric // If scope has not changed then skip this instruction.
856122f3e6SDimitry Andric if (MIDL == PrevDL) {
8691bc56edSDimitry Andric PrevMI = &MInsn;
876122f3e6SDimitry Andric continue;
886122f3e6SDimitry Andric }
896122f3e6SDimitry Andric
90302affcbSDimitry Andric // Ignore DBG_VALUE and similar instruction that do not contribute to any
91302affcbSDimitry Andric // instruction in the output.
92302affcbSDimitry Andric if (MInsn.isMetaInstruction())
936122f3e6SDimitry Andric continue;
946122f3e6SDimitry Andric
956122f3e6SDimitry Andric if (RangeBeginMI) {
966122f3e6SDimitry Andric // If we have already seen a beginning of an instruction range and
976122f3e6SDimitry Andric // current instruction scope does not match scope of first instruction
986122f3e6SDimitry Andric // in this range then create a new instruction range.
996122f3e6SDimitry Andric InsnRange R(RangeBeginMI, PrevMI);
1006122f3e6SDimitry Andric MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
1016122f3e6SDimitry Andric MIRanges.push_back(R);
1026122f3e6SDimitry Andric }
1036122f3e6SDimitry Andric
1046122f3e6SDimitry Andric // This is a beginning of a new instruction range.
10591bc56edSDimitry Andric RangeBeginMI = &MInsn;
1066122f3e6SDimitry Andric
1076122f3e6SDimitry Andric // Reset previous markers.
10891bc56edSDimitry Andric PrevMI = &MInsn;
1096122f3e6SDimitry Andric PrevDL = MIDL;
1106122f3e6SDimitry Andric }
1116122f3e6SDimitry Andric
1126122f3e6SDimitry Andric // Create last instruction range.
113ff0cc061SDimitry Andric if (RangeBeginMI && PrevMI && PrevDL) {
1146122f3e6SDimitry Andric InsnRange R(RangeBeginMI, PrevMI);
1156122f3e6SDimitry Andric MIRanges.push_back(R);
1166122f3e6SDimitry Andric MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL);
1176122f3e6SDimitry Andric }
1186122f3e6SDimitry Andric }
1196122f3e6SDimitry Andric }
1206122f3e6SDimitry Andric
1216122f3e6SDimitry Andric /// findLexicalScope - Find lexical scope, either regular or inlined, for the
1226122f3e6SDimitry Andric /// given DebugLoc. Return NULL if not found.
findLexicalScope(const DILocation * DL)123ff0cc061SDimitry Andric LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
124ff0cc061SDimitry Andric DILocalScope *Scope = DL->getScope();
12591bc56edSDimitry Andric if (!Scope)
12691bc56edSDimitry Andric return nullptr;
1276122f3e6SDimitry Andric
1286122f3e6SDimitry Andric // The scope that we were created with could have an extra file - which
1296122f3e6SDimitry Andric // isn't what we care about in this case.
1303ca95b02SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope();
1316122f3e6SDimitry Andric
132ff0cc061SDimitry Andric if (auto *IA = DL->getInlinedAt()) {
13391bc56edSDimitry Andric auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
13491bc56edSDimitry Andric return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
13591bc56edSDimitry Andric }
13691bc56edSDimitry Andric return findLexicalScope(Scope);
1376122f3e6SDimitry Andric }
1386122f3e6SDimitry Andric
1396122f3e6SDimitry Andric /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
1406122f3e6SDimitry Andric /// not available then create new lexical scope.
getOrCreateLexicalScope(const DILocalScope * Scope,const DILocation * IA)141ff0cc061SDimitry Andric LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope,
142ff0cc061SDimitry Andric const DILocation *IA) {
143ff0cc061SDimitry Andric if (IA) {
1447a7e6055SDimitry Andric // Skip scopes inlined from a NoDebug compile unit.
1457a7e6055SDimitry Andric if (Scope->getSubprogram()->getUnit()->getEmissionKind() ==
1467a7e6055SDimitry Andric DICompileUnit::NoDebug)
1477a7e6055SDimitry Andric return getOrCreateLexicalScope(IA);
1486122f3e6SDimitry Andric // Create an abstract scope for inlined function.
1496122f3e6SDimitry Andric getOrCreateAbstractScope(Scope);
1506122f3e6SDimitry Andric // Create an inlined scope for inlined function.
151ff0cc061SDimitry Andric return getOrCreateInlinedScope(Scope, IA);
1526122f3e6SDimitry Andric }
1536122f3e6SDimitry Andric
1546122f3e6SDimitry Andric return getOrCreateRegularScope(Scope);
1556122f3e6SDimitry Andric }
1566122f3e6SDimitry Andric
1576122f3e6SDimitry Andric /// getOrCreateRegularScope - Find or create a regular lexical scope.
158ff0cc061SDimitry Andric LexicalScope *
getOrCreateRegularScope(const DILocalScope * Scope)159ff0cc061SDimitry Andric LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
1603ca95b02SDimitry Andric assert(Scope && "Invalid Scope encoding!");
1613ca95b02SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope();
1626122f3e6SDimitry Andric
16391bc56edSDimitry Andric auto I = LexicalScopeMap.find(Scope);
16491bc56edSDimitry Andric if (I != LexicalScopeMap.end())
16591bc56edSDimitry Andric return &I->second;
1666122f3e6SDimitry Andric
167ff0cc061SDimitry Andric // FIXME: Should the following dyn_cast be DILexicalBlock?
16891bc56edSDimitry Andric LexicalScope *Parent = nullptr;
169ff0cc061SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
170ff0cc061SDimitry Andric Parent = getOrCreateLexicalScope(Block->getScope());
171ff0cc061SDimitry Andric I = LexicalScopeMap.emplace(std::piecewise_construct,
172ff0cc061SDimitry Andric std::forward_as_tuple(Scope),
173ff0cc061SDimitry Andric std::forward_as_tuple(Parent, Scope, nullptr,
174ff0cc061SDimitry Andric false)).first;
1756122f3e6SDimitry Andric
17639d628a0SDimitry Andric if (!Parent) {
1772cab237bSDimitry Andric assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
17839d628a0SDimitry Andric assert(!CurrentFnLexicalScope);
17991bc56edSDimitry Andric CurrentFnLexicalScope = &I->second;
18039d628a0SDimitry Andric }
18191bc56edSDimitry Andric
18291bc56edSDimitry Andric return &I->second;
1836122f3e6SDimitry Andric }
1846122f3e6SDimitry Andric
1856122f3e6SDimitry Andric /// getOrCreateInlinedScope - Find or create an inlined lexical scope.
186ff0cc061SDimitry Andric LexicalScope *
getOrCreateInlinedScope(const DILocalScope * Scope,const DILocation * InlinedAt)187ff0cc061SDimitry Andric LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
188ff0cc061SDimitry Andric const DILocation *InlinedAt) {
1893ca95b02SDimitry Andric assert(Scope && "Invalid Scope encoding!");
1903ca95b02SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope();
191ff0cc061SDimitry Andric std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
19291bc56edSDimitry Andric auto I = InlinedLexicalScopeMap.find(P);
19391bc56edSDimitry Andric if (I != InlinedLexicalScopeMap.end())
19491bc56edSDimitry Andric return &I->second;
1956122f3e6SDimitry Andric
19691bc56edSDimitry Andric LexicalScope *Parent;
197ff0cc061SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
198ff0cc061SDimitry Andric Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt);
19991bc56edSDimitry Andric else
200ff0cc061SDimitry Andric Parent = getOrCreateLexicalScope(InlinedAt);
20191bc56edSDimitry Andric
2027a7e6055SDimitry Andric I = InlinedLexicalScopeMap
2037a7e6055SDimitry Andric .emplace(std::piecewise_construct, std::forward_as_tuple(P),
2047a7e6055SDimitry Andric std::forward_as_tuple(Parent, Scope, InlinedAt, false))
205ff0cc061SDimitry Andric .first;
20691bc56edSDimitry Andric return &I->second;
2076122f3e6SDimitry Andric }
2086122f3e6SDimitry Andric
2096122f3e6SDimitry Andric /// getOrCreateAbstractScope - Find or create an abstract lexical scope.
210ff0cc061SDimitry Andric LexicalScope *
getOrCreateAbstractScope(const DILocalScope * Scope)211ff0cc061SDimitry Andric LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
212ff0cc061SDimitry Andric assert(Scope && "Invalid Scope encoding!");
2133ca95b02SDimitry Andric Scope = Scope->getNonLexicalBlockFileScope();
21491bc56edSDimitry Andric auto I = AbstractScopeMap.find(Scope);
21591bc56edSDimitry Andric if (I != AbstractScopeMap.end())
21691bc56edSDimitry Andric return &I->second;
2176122f3e6SDimitry Andric
218ff0cc061SDimitry Andric // FIXME: Should the following isa be DILexicalBlock?
21991bc56edSDimitry Andric LexicalScope *Parent = nullptr;
220ff0cc061SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
221ff0cc061SDimitry Andric Parent = getOrCreateAbstractScope(Block->getScope());
222ff0cc061SDimitry Andric
22391bc56edSDimitry Andric I = AbstractScopeMap.emplace(std::piecewise_construct,
22491bc56edSDimitry Andric std::forward_as_tuple(Scope),
22591bc56edSDimitry Andric std::forward_as_tuple(Parent, Scope,
22691bc56edSDimitry Andric nullptr, true)).first;
227ff0cc061SDimitry Andric if (isa<DISubprogram>(Scope))
22891bc56edSDimitry Andric AbstractScopesList.push_back(&I->second);
22991bc56edSDimitry Andric return &I->second;
2306122f3e6SDimitry Andric }
2316122f3e6SDimitry Andric
2326122f3e6SDimitry Andric /// constructScopeNest
constructScopeNest(LexicalScope * Scope)2336122f3e6SDimitry Andric void LexicalScopes::constructScopeNest(LexicalScope *Scope) {
2346122f3e6SDimitry Andric assert(Scope && "Unable to calculate scope dominance graph!");
2356122f3e6SDimitry Andric SmallVector<LexicalScope *, 4> WorkStack;
2366122f3e6SDimitry Andric WorkStack.push_back(Scope);
2376122f3e6SDimitry Andric unsigned Counter = 0;
2386122f3e6SDimitry Andric while (!WorkStack.empty()) {
2396122f3e6SDimitry Andric LexicalScope *WS = WorkStack.back();
240f785676fSDimitry Andric const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
2416122f3e6SDimitry Andric bool visitedChildren = false;
242d88c1a5aSDimitry Andric for (auto &ChildScope : Children)
2436122f3e6SDimitry Andric if (!ChildScope->getDFSOut()) {
2446122f3e6SDimitry Andric WorkStack.push_back(ChildScope);
2456122f3e6SDimitry Andric visitedChildren = true;
2466122f3e6SDimitry Andric ChildScope->setDFSIn(++Counter);
2476122f3e6SDimitry Andric break;
2486122f3e6SDimitry Andric }
2496122f3e6SDimitry Andric if (!visitedChildren) {
2506122f3e6SDimitry Andric WorkStack.pop_back();
2516122f3e6SDimitry Andric WS->setDFSOut(++Counter);
2526122f3e6SDimitry Andric }
2536122f3e6SDimitry Andric }
2546122f3e6SDimitry Andric }
2556122f3e6SDimitry Andric
2566122f3e6SDimitry Andric /// assignInstructionRanges - Find ranges of instructions covered by each
2576122f3e6SDimitry Andric /// lexical scope.
assignInstructionRanges(SmallVectorImpl<InsnRange> & MIRanges,DenseMap<const MachineInstr *,LexicalScope * > & MI2ScopeMap)25891bc56edSDimitry Andric void LexicalScopes::assignInstructionRanges(
25991bc56edSDimitry Andric SmallVectorImpl<InsnRange> &MIRanges,
26091bc56edSDimitry Andric DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) {
26191bc56edSDimitry Andric LexicalScope *PrevLexicalScope = nullptr;
262d88c1a5aSDimitry Andric for (const auto &R : MIRanges) {
2636122f3e6SDimitry Andric LexicalScope *S = MI2ScopeMap.lookup(R.first);
2646122f3e6SDimitry Andric assert(S && "Lost LexicalScope for a machine instruction!");
2656122f3e6SDimitry Andric if (PrevLexicalScope && !PrevLexicalScope->dominates(S))
2666122f3e6SDimitry Andric PrevLexicalScope->closeInsnRange(S);
2676122f3e6SDimitry Andric S->openInsnRange(R.first);
2686122f3e6SDimitry Andric S->extendInsnRange(R.second);
2696122f3e6SDimitry Andric PrevLexicalScope = S;
2706122f3e6SDimitry Andric }
2716122f3e6SDimitry Andric
2726122f3e6SDimitry Andric if (PrevLexicalScope)
2736122f3e6SDimitry Andric PrevLexicalScope->closeInsnRange();
2746122f3e6SDimitry Andric }
2756122f3e6SDimitry Andric
2766122f3e6SDimitry Andric /// getMachineBasicBlocks - Populate given set using machine basic blocks which
2776122f3e6SDimitry Andric /// have machine instructions that belong to lexical scope identified by
2786122f3e6SDimitry Andric /// DebugLoc.
getMachineBasicBlocks(const DILocation * DL,SmallPtrSetImpl<const MachineBasicBlock * > & MBBs)27991bc56edSDimitry Andric void LexicalScopes::getMachineBasicBlocks(
280ff0cc061SDimitry Andric const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) {
2812cab237bSDimitry Andric assert(MF && "Method called on a uninitialized LexicalScopes object!");
2826122f3e6SDimitry Andric MBBs.clear();
2832cab237bSDimitry Andric
2846122f3e6SDimitry Andric LexicalScope *Scope = getOrCreateLexicalScope(DL);
2856122f3e6SDimitry Andric if (!Scope)
2866122f3e6SDimitry Andric return;
2876122f3e6SDimitry Andric
2886122f3e6SDimitry Andric if (Scope == CurrentFnLexicalScope) {
28991bc56edSDimitry Andric for (const auto &MBB : *MF)
29091bc56edSDimitry Andric MBBs.insert(&MBB);
2916122f3e6SDimitry Andric return;
2926122f3e6SDimitry Andric }
2936122f3e6SDimitry Andric
294f785676fSDimitry Andric SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges();
295d88c1a5aSDimitry Andric for (auto &R : InsnRanges)
2966122f3e6SDimitry Andric MBBs.insert(R.first->getParent());
2976122f3e6SDimitry Andric }
2986122f3e6SDimitry Andric
2996122f3e6SDimitry Andric /// dominates - Return true if DebugLoc's lexical scope dominates at least one
3006122f3e6SDimitry Andric /// machine instruction's lexical scope in a given machine basic block.
dominates(const DILocation * DL,MachineBasicBlock * MBB)301ff0cc061SDimitry Andric bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) {
3022cab237bSDimitry Andric assert(MF && "Unexpected uninitialized LexicalScopes object!");
3036122f3e6SDimitry Andric LexicalScope *Scope = getOrCreateLexicalScope(DL);
3046122f3e6SDimitry Andric if (!Scope)
3056122f3e6SDimitry Andric return false;
3066122f3e6SDimitry Andric
3076122f3e6SDimitry Andric // Current function scope covers all basic blocks in the function.
3086122f3e6SDimitry Andric if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF)
3096122f3e6SDimitry Andric return true;
3106122f3e6SDimitry Andric
3116122f3e6SDimitry Andric bool Result = false;
312d88c1a5aSDimitry Andric for (auto &I : *MBB) {
313d88c1a5aSDimitry Andric if (const DILocation *IDL = I.getDebugLoc())
3146122f3e6SDimitry Andric if (LexicalScope *IScope = getOrCreateLexicalScope(IDL))
3156122f3e6SDimitry Andric if (Scope->dominates(IScope))
3166122f3e6SDimitry Andric return true;
3176122f3e6SDimitry Andric }
3186122f3e6SDimitry Andric return Result;
3196122f3e6SDimitry Andric }
3206122f3e6SDimitry Andric
3217a7e6055SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump(unsigned Indent) const3227a7e6055SDimitry Andric LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const {
3236122f3e6SDimitry Andric raw_ostream &err = dbgs();
324139f7f9bSDimitry Andric err.indent(Indent);
3256122f3e6SDimitry Andric err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
3266122f3e6SDimitry Andric const MDNode *N = Desc;
327139f7f9bSDimitry Andric err.indent(Indent);
3286122f3e6SDimitry Andric N->dump();
3296122f3e6SDimitry Andric if (AbstractScope)
330139f7f9bSDimitry Andric err << std::string(Indent, ' ') << "Abstract Scope\n";
3316122f3e6SDimitry Andric
3326122f3e6SDimitry Andric if (!Children.empty())
333139f7f9bSDimitry Andric err << std::string(Indent + 2, ' ') << "Children ...\n";
3346122f3e6SDimitry Andric for (unsigned i = 0, e = Children.size(); i != e; ++i)
3356122f3e6SDimitry Andric if (Children[i] != this)
336139f7f9bSDimitry Andric Children[i]->dump(Indent + 2);
3376122f3e6SDimitry Andric }
3387a7e6055SDimitry Andric #endif
339