Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 1 | //===- LexicalScopes.cpp - Collecting lexical scope info ------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements LexicalScopes analysis. |
| 11 | // |
| 12 | // This pass collects lexical scope information and maps machine instructions |
| 13 | // to respective lexical scopes. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
Chandler Carruth | e3e43d9 | 2017-06-06 11:49:48 +0000 | [diff] [blame] | 17 | #include "llvm/CodeGen/LexicalScopes.h" |
Eugene Zelenko | ad3a540 | 2017-02-17 21:43:25 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/DenseMap.h" |
| 19 | #include "llvm/ADT/SmallVector.h" |
Eugene Zelenko | ad3a540 | 2017-02-17 21:43:25 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/MachineBasicBlock.h" |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 21 | #include "llvm/CodeGen/MachineFunction.h" |
| 22 | #include "llvm/CodeGen/MachineInstr.h" |
Nico Weber | 0f38c60 | 2018-04-30 14:59:11 +0000 | [diff] [blame] | 23 | #include "llvm/Config/llvm-config.h" |
Eugene Zelenko | ad3a540 | 2017-02-17 21:43:25 +0000 | [diff] [blame] | 24 | #include "llvm/IR/DebugInfoMetadata.h" |
| 25 | #include "llvm/IR/Metadata.h" |
| 26 | #include "llvm/Support/Casting.h" |
| 27 | #include "llvm/Support/Compiler.h" |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 28 | #include "llvm/Support/Debug.h" |
Eugene Zelenko | ad3a540 | 2017-02-17 21:43:25 +0000 | [diff] [blame] | 29 | #include "llvm/Support/raw_ostream.h" |
| 30 | #include <cassert> |
| 31 | #include <string> |
| 32 | #include <tuple> |
| 33 | #include <utility> |
| 34 | |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 35 | using namespace llvm; |
| 36 | |
Chandler Carruth | 8677f2f | 2014-04-22 02:02:50 +0000 | [diff] [blame] | 37 | #define DEBUG_TYPE "lexicalscopes" |
| 38 | |
Eric Christopher | b88a94f | 2013-11-20 00:54:28 +0000 | [diff] [blame] | 39 | /// reset - Reset the instance so that it's prepared for another function. |
| 40 | void LexicalScopes::reset() { |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 41 | MF = nullptr; |
| 42 | CurrentFnLexicalScope = nullptr; |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 43 | LexicalScopeMap.clear(); |
| 44 | AbstractScopeMap.clear(); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 45 | InlinedLexicalScopeMap.clear(); |
| 46 | AbstractScopesList.clear(); |
| 47 | } |
| 48 | |
| 49 | /// initialize - Scan machine function and constuct lexical scope nest. |
| 50 | void LexicalScopes::initialize(const MachineFunction &Fn) { |
Wolfgang Pieb | a6df1e5 | 2017-07-19 19:36:40 +0000 | [diff] [blame] | 51 | reset(); |
Teresa Johnson | 0640903 | 2017-02-17 00:21:19 +0000 | [diff] [blame] | 52 | // Don't attempt any lexical scope creation for a NoDebug compile unit. |
Matthias Braun | d318139 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 53 | if (Fn.getFunction().getSubprogram()->getUnit()->getEmissionKind() == |
Teresa Johnson | 0640903 | 2017-02-17 00:21:19 +0000 | [diff] [blame] | 54 | DICompileUnit::NoDebug) |
| 55 | return; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 56 | MF = &Fn; |
| 57 | SmallVector<InsnRange, 4> MIRanges; |
| 58 | DenseMap<const MachineInstr *, LexicalScope *> MI2ScopeMap; |
| 59 | extractLexicalScopes(MIRanges, MI2ScopeMap); |
| 60 | if (CurrentFnLexicalScope) { |
| 61 | constructScopeNest(CurrentFnLexicalScope); |
| 62 | assignInstructionRanges(MIRanges, MI2ScopeMap); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | /// extractLexicalScopes - Extract instruction ranges for each lexical scopes |
| 67 | /// for the given machine function. |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 68 | void LexicalScopes::extractLexicalScopes( |
| 69 | SmallVectorImpl<InsnRange> &MIRanges, |
| 70 | DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 71 | // Scan each instruction and create scopes. First build working set of scopes. |
Alexey Samsonov | 4aef727 | 2014-04-30 18:29:51 +0000 | [diff] [blame] | 72 | for (const auto &MBB : *MF) { |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 73 | const MachineInstr *RangeBeginMI = nullptr; |
| 74 | const MachineInstr *PrevMI = nullptr; |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 75 | const DILocation *PrevDL = nullptr; |
Alexey Samsonov | 8467812 | 2014-04-30 22:17:38 +0000 | [diff] [blame] | 76 | for (const auto &MInsn : MBB) { |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 77 | // Check if instruction has valid location information. |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 78 | const DILocation *MIDL = MInsn.getDebugLoc(); |
Duncan P. N. Exon Smith | 3637bab | 2015-03-30 19:14:47 +0000 | [diff] [blame] | 79 | if (!MIDL) { |
Alexey Samsonov | 8467812 | 2014-04-30 22:17:38 +0000 | [diff] [blame] | 80 | PrevMI = &MInsn; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 81 | continue; |
| 82 | } |
| 83 | |
| 84 | // If scope has not changed then skip this instruction. |
| 85 | if (MIDL == PrevDL) { |
Alexey Samsonov | 8467812 | 2014-04-30 22:17:38 +0000 | [diff] [blame] | 86 | PrevMI = &MInsn; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 87 | continue; |
| 88 | } |
| 89 | |
Adrian Prantl | 14a1dd1 | 2017-05-22 20:47:09 +0000 | [diff] [blame] | 90 | // Ignore DBG_VALUE and similar instruction that do not contribute to any |
| 91 | // instruction in the output. |
| 92 | if (MInsn.isMetaInstruction()) |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 93 | continue; |
| 94 | |
| 95 | if (RangeBeginMI) { |
| 96 | // If we have already seen a beginning of an instruction range and |
| 97 | // current instruction scope does not match scope of first instruction |
| 98 | // in this range then create a new instruction range. |
| 99 | InsnRange R(RangeBeginMI, PrevMI); |
| 100 | MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); |
| 101 | MIRanges.push_back(R); |
| 102 | } |
| 103 | |
| 104 | // This is a beginning of a new instruction range. |
Alexey Samsonov | 8467812 | 2014-04-30 22:17:38 +0000 | [diff] [blame] | 105 | RangeBeginMI = &MInsn; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 106 | |
| 107 | // Reset previous markers. |
Alexey Samsonov | 8467812 | 2014-04-30 22:17:38 +0000 | [diff] [blame] | 108 | PrevMI = &MInsn; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 109 | PrevDL = MIDL; |
| 110 | } |
| 111 | |
| 112 | // Create last instruction range. |
Duncan P. N. Exon Smith | 3637bab | 2015-03-30 19:14:47 +0000 | [diff] [blame] | 113 | if (RangeBeginMI && PrevMI && PrevDL) { |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 114 | InsnRange R(RangeBeginMI, PrevMI); |
| 115 | MIRanges.push_back(R); |
| 116 | MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /// findLexicalScope - Find lexical scope, either regular or inlined, for the |
| 122 | /// given DebugLoc. Return NULL if not found. |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 123 | LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) { |
| 124 | DILocalScope *Scope = DL->getScope(); |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 125 | if (!Scope) |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 126 | return nullptr; |
Eric Christopher | 6618a24 | 2011-10-11 22:59:11 +0000 | [diff] [blame] | 127 | |
| 128 | // The scope that we were created with could have an extra file - which |
| 129 | // isn't what we care about in this case. |
Amjad Aboud | 1268621 | 2016-04-21 16:58:49 +0000 | [diff] [blame] | 130 | Scope = Scope->getNonLexicalBlockFileScope(); |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 131 | |
Duncan P. N. Exon Smith | 35ff67e | 2015-03-30 21:54:46 +0000 | [diff] [blame] | 132 | if (auto *IA = DL->getInlinedAt()) { |
David Blaikie | ee8af3e | 2014-05-14 01:08:28 +0000 | [diff] [blame] | 133 | auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA)); |
| 134 | return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; |
| 135 | } |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 136 | return findLexicalScope(Scope); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If |
| 140 | /// not available then create new lexical scope. |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 141 | LexicalScope *LexicalScopes::getOrCreateLexicalScope(const DILocalScope *Scope, |
| 142 | const DILocation *IA) { |
Duncan P. N. Exon Smith | 497110d | 2015-03-30 23:47:26 +0000 | [diff] [blame] | 143 | if (IA) { |
Teresa Johnson | 0640903 | 2017-02-17 00:21:19 +0000 | [diff] [blame] | 144 | // Skip scopes inlined from a NoDebug compile unit. |
| 145 | if (Scope->getSubprogram()->getUnit()->getEmissionKind() == |
| 146 | DICompileUnit::NoDebug) |
| 147 | return getOrCreateLexicalScope(IA); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 148 | // Create an abstract scope for inlined function. |
| 149 | getOrCreateAbstractScope(Scope); |
| 150 | // Create an inlined scope for inlined function. |
Duncan P. N. Exon Smith | 497110d | 2015-03-30 23:47:26 +0000 | [diff] [blame] | 151 | return getOrCreateInlinedScope(Scope, IA); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 152 | } |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 153 | |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 154 | return getOrCreateRegularScope(Scope); |
| 155 | } |
| 156 | |
| 157 | /// getOrCreateRegularScope - Find or create a regular lexical scope. |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 158 | LexicalScope * |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 159 | LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) { |
Amjad Aboud | 1268621 | 2016-04-21 16:58:49 +0000 | [diff] [blame] | 160 | assert(Scope && "Invalid Scope encoding!"); |
| 161 | Scope = Scope->getNonLexicalBlockFileScope(); |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 162 | |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 163 | auto I = LexicalScopeMap.find(Scope); |
| 164 | if (I != LexicalScopeMap.end()) |
| 165 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 166 | |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 167 | // FIXME: Should the following dyn_cast be DILexicalBlock? |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 168 | LexicalScope *Parent = nullptr; |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 169 | if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) |
Duncan P. N. Exon Smith | 497110d | 2015-03-30 23:47:26 +0000 | [diff] [blame] | 170 | Parent = getOrCreateLexicalScope(Block->getScope()); |
Aaron Ballman | 7fcd745 | 2015-02-16 18:21:19 +0000 | [diff] [blame] | 171 | I = LexicalScopeMap.emplace(std::piecewise_construct, |
| 172 | std::forward_as_tuple(Scope), |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 173 | std::forward_as_tuple(Parent, Scope, nullptr, |
| 174 | false)).first; |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 175 | |
David Blaikie | d661fde | 2014-10-14 18:22:52 +0000 | [diff] [blame] | 176 | if (!Parent) { |
Matthias Braun | d318139 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 177 | assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction())); |
David Blaikie | d661fde | 2014-10-14 18:22:52 +0000 | [diff] [blame] | 178 | assert(!CurrentFnLexicalScope); |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 179 | CurrentFnLexicalScope = &I->second; |
David Blaikie | d661fde | 2014-10-14 18:22:52 +0000 | [diff] [blame] | 180 | } |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 181 | |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 182 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | /// getOrCreateInlinedScope - Find or create an inlined lexical scope. |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 186 | LexicalScope * |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 187 | LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope, |
| 188 | const DILocation *InlinedAt) { |
Amjad Aboud | 1268621 | 2016-04-21 16:58:49 +0000 | [diff] [blame] | 189 | assert(Scope && "Invalid Scope encoding!"); |
| 190 | Scope = Scope->getNonLexicalBlockFileScope(); |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 191 | std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt); |
David Blaikie | ee8af3e | 2014-05-14 01:08:28 +0000 | [diff] [blame] | 192 | auto I = InlinedLexicalScopeMap.find(P); |
| 193 | if (I != InlinedLexicalScopeMap.end()) |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 194 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 195 | |
David Blaikie | ee8af3e | 2014-05-14 01:08:28 +0000 | [diff] [blame] | 196 | LexicalScope *Parent; |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 197 | if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 198 | Parent = getOrCreateInlinedScope(Block->getScope(), InlinedAt); |
David Blaikie | ee8af3e | 2014-05-14 01:08:28 +0000 | [diff] [blame] | 199 | else |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 200 | Parent = getOrCreateLexicalScope(InlinedAt); |
David Blaikie | ee8af3e | 2014-05-14 01:08:28 +0000 | [diff] [blame] | 201 | |
Eric Christopher | 71648d0 | 2017-02-14 19:43:50 +0000 | [diff] [blame] | 202 | I = InlinedLexicalScopeMap |
| 203 | .emplace(std::piecewise_construct, std::forward_as_tuple(P), |
| 204 | std::forward_as_tuple(Parent, Scope, InlinedAt, false)) |
Aaron Ballman | 7fcd745 | 2015-02-16 18:21:19 +0000 | [diff] [blame] | 205 | .first; |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 206 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 207 | } |
| 208 | |
| 209 | /// getOrCreateAbstractScope - Find or create an abstract lexical scope. |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 210 | LexicalScope * |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 211 | LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) { |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 212 | assert(Scope && "Invalid Scope encoding!"); |
Amjad Aboud | 1268621 | 2016-04-21 16:58:49 +0000 | [diff] [blame] | 213 | Scope = Scope->getNonLexicalBlockFileScope(); |
David Blaikie | cec3724 | 2014-05-25 18:11:35 +0000 | [diff] [blame] | 214 | auto I = AbstractScopeMap.find(Scope); |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 215 | if (I != AbstractScopeMap.end()) |
| 216 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 217 | |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 218 | // FIXME: Should the following isa be DILexicalBlock? |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 219 | LexicalScope *Parent = nullptr; |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 220 | if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope)) |
Duncan P. N. Exon Smith | 62e3e38 | 2015-03-30 23:21:21 +0000 | [diff] [blame] | 221 | Parent = getOrCreateAbstractScope(Block->getScope()); |
| 222 | |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 223 | I = AbstractScopeMap.emplace(std::piecewise_construct, |
David Blaikie | cec3724 | 2014-05-25 18:11:35 +0000 | [diff] [blame] | 224 | std::forward_as_tuple(Scope), |
| 225 | std::forward_as_tuple(Parent, Scope, |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 226 | nullptr, true)).first; |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 227 | if (isa<DISubprogram>(Scope)) |
David Blaikie | bccff0f | 2014-05-08 22:24:51 +0000 | [diff] [blame] | 228 | AbstractScopesList.push_back(&I->second); |
| 229 | return &I->second; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | /// constructScopeNest |
| 233 | void LexicalScopes::constructScopeNest(LexicalScope *Scope) { |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 234 | assert(Scope && "Unable to calculate scope dominance graph!"); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 235 | SmallVector<LexicalScope *, 4> WorkStack; |
| 236 | WorkStack.push_back(Scope); |
| 237 | unsigned Counter = 0; |
| 238 | while (!WorkStack.empty()) { |
| 239 | LexicalScope *WS = WorkStack.back(); |
Craig Topper | 9f4c379 | 2013-07-03 04:30:58 +0000 | [diff] [blame] | 240 | const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 241 | bool visitedChildren = false; |
Adrian Prantl | 89584ae | 2016-09-28 17:31:17 +0000 | [diff] [blame] | 242 | for (auto &ChildScope : Children) |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 243 | if (!ChildScope->getDFSOut()) { |
| 244 | WorkStack.push_back(ChildScope); |
| 245 | visitedChildren = true; |
| 246 | ChildScope->setDFSIn(++Counter); |
| 247 | break; |
| 248 | } |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 249 | if (!visitedChildren) { |
| 250 | WorkStack.pop_back(); |
| 251 | WS->setDFSOut(++Counter); |
| 252 | } |
| 253 | } |
| 254 | } |
| 255 | |
Devang Patel | 5bc942c | 2011-08-10 23:58:09 +0000 | [diff] [blame] | 256 | /// assignInstructionRanges - Find ranges of instructions covered by each |
| 257 | /// lexical scope. |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 258 | void LexicalScopes::assignInstructionRanges( |
| 259 | SmallVectorImpl<InsnRange> &MIRanges, |
| 260 | DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { |
Craig Topper | 4ba8443 | 2014-04-14 00:51:57 +0000 | [diff] [blame] | 261 | LexicalScope *PrevLexicalScope = nullptr; |
Adrian Prantl | 89584ae | 2016-09-28 17:31:17 +0000 | [diff] [blame] | 262 | for (const auto &R : MIRanges) { |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 263 | LexicalScope *S = MI2ScopeMap.lookup(R.first); |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 264 | assert(S && "Lost LexicalScope for a machine instruction!"); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 265 | if (PrevLexicalScope && !PrevLexicalScope->dominates(S)) |
| 266 | PrevLexicalScope->closeInsnRange(S); |
| 267 | S->openInsnRange(R.first); |
| 268 | S->extendInsnRange(R.second); |
| 269 | PrevLexicalScope = S; |
| 270 | } |
| 271 | |
| 272 | if (PrevLexicalScope) |
| 273 | PrevLexicalScope->closeInsnRange(); |
| 274 | } |
| 275 | |
| 276 | /// getMachineBasicBlocks - Populate given set using machine basic blocks which |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 277 | /// have machine instructions that belong to lexical scope identified by |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 278 | /// DebugLoc. |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 279 | void LexicalScopes::getMachineBasicBlocks( |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 280 | const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs) { |
Wolfgang Pieb | a6df1e5 | 2017-07-19 19:36:40 +0000 | [diff] [blame] | 281 | assert(MF && "Method called on a uninitialized LexicalScopes object!"); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 282 | MBBs.clear(); |
Wolfgang Pieb | a6df1e5 | 2017-07-19 19:36:40 +0000 | [diff] [blame] | 283 | |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 284 | LexicalScope *Scope = getOrCreateLexicalScope(DL); |
| 285 | if (!Scope) |
| 286 | return; |
Eric Christopher | 73a69d6 | 2013-11-20 00:54:19 +0000 | [diff] [blame] | 287 | |
Devang Patel | 2e85b1b | 2011-08-12 18:01:34 +0000 | [diff] [blame] | 288 | if (Scope == CurrentFnLexicalScope) { |
Alexey Samsonov | 4aef727 | 2014-04-30 18:29:51 +0000 | [diff] [blame] | 289 | for (const auto &MBB : *MF) |
| 290 | MBBs.insert(&MBB); |
Devang Patel | 2e85b1b | 2011-08-12 18:01:34 +0000 | [diff] [blame] | 291 | return; |
| 292 | } |
| 293 | |
Craig Topper | 9f4c379 | 2013-07-03 04:30:58 +0000 | [diff] [blame] | 294 | SmallVectorImpl<InsnRange> &InsnRanges = Scope->getRanges(); |
Adrian Prantl | 89584ae | 2016-09-28 17:31:17 +0000 | [diff] [blame] | 295 | for (auto &R : InsnRanges) |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 296 | MBBs.insert(R.first->getParent()); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | /// dominates - Return true if DebugLoc's lexical scope dominates at least one |
| 300 | /// machine instruction's lexical scope in a given machine basic block. |
Duncan P. N. Exon Smith | e56023a | 2015-04-29 16:38:44 +0000 | [diff] [blame] | 301 | bool LexicalScopes::dominates(const DILocation *DL, MachineBasicBlock *MBB) { |
Wolfgang Pieb | a6df1e5 | 2017-07-19 19:36:40 +0000 | [diff] [blame] | 302 | assert(MF && "Unexpected uninitialized LexicalScopes object!"); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 303 | LexicalScope *Scope = getOrCreateLexicalScope(DL); |
| 304 | if (!Scope) |
| 305 | return false; |
Devang Patel | 2e85b1b | 2011-08-12 18:01:34 +0000 | [diff] [blame] | 306 | |
| 307 | // Current function scope covers all basic blocks in the function. |
| 308 | if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF) |
| 309 | return true; |
| 310 | |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 311 | bool Result = false; |
Adrian Prantl | 89584ae | 2016-09-28 17:31:17 +0000 | [diff] [blame] | 312 | for (auto &I : *MBB) { |
| 313 | if (const DILocation *IDL = I.getDebugLoc()) |
Duncan P. N. Exon Smith | 1aa1d1a | 2015-03-30 23:58:59 +0000 | [diff] [blame] | 314 | if (LexicalScope *IScope = getOrCreateLexicalScope(IDL)) |
| 315 | if (Scope->dominates(IScope)) |
| 316 | return true; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 317 | } |
| 318 | return Result; |
| 319 | } |
| 320 | |
Aaron Ballman | 1d03d38 | 2017-10-15 14:32:27 +0000 | [diff] [blame] | 321 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
Matthias Braun | 88d2075 | 2017-01-28 02:02:38 +0000 | [diff] [blame] | 322 | LLVM_DUMP_METHOD void LexicalScope::dump(unsigned Indent) const { |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 323 | raw_ostream &err = dbgs(); |
Manman Ren | 7650d9b | 2013-02-02 00:02:03 +0000 | [diff] [blame] | 324 | err.indent(Indent); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 325 | err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; |
| 326 | const MDNode *N = Desc; |
Manman Ren | 7650d9b | 2013-02-02 00:02:03 +0000 | [diff] [blame] | 327 | err.indent(Indent); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 328 | N->dump(); |
| 329 | if (AbstractScope) |
Manman Ren | 7650d9b | 2013-02-02 00:02:03 +0000 | [diff] [blame] | 330 | err << std::string(Indent, ' ') << "Abstract Scope\n"; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 331 | |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 332 | if (!Children.empty()) |
Manman Ren | 7650d9b | 2013-02-02 00:02:03 +0000 | [diff] [blame] | 333 | err << std::string(Indent + 2, ' ') << "Children ...\n"; |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 334 | for (unsigned i = 0, e = Children.size(); i != e; ++i) |
| 335 | if (Children[i] != this) |
Manman Ren | 7650d9b | 2013-02-02 00:02:03 +0000 | [diff] [blame] | 336 | Children[i]->dump(Indent + 2); |
Devang Patel | 103b8e6 | 2011-08-10 19:04:06 +0000 | [diff] [blame] | 337 | } |
Matthias Braun | 88d2075 | 2017-01-28 02:02:38 +0000 | [diff] [blame] | 338 | #endif |