|
13 | 13 | #include "llvm/IR/DebugInfoMetadata.h"
|
14 | 14 | #include "LLVMContextImpl.h"
|
15 | 15 | #include "MetadataImpl.h"
|
16 |
| -#include "llvm/ADT/SmallPtrSet.h" |
| 16 | +#include "llvm/ADT/SetVector.h" |
17 | 17 | #include "llvm/ADT/StringSwitch.h"
|
18 | 18 | #include "llvm/BinaryFormat/Dwarf.h"
|
19 | 19 | #include "llvm/IR/DebugProgramInstruction.h"
|
@@ -125,6 +125,98 @@ DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {
|
125 | 125 | return Merged;
|
126 | 126 | }
|
127 | 127 |
|
| 128 | +static DILexicalBlockBase *cloneAndReplaceParentScope(DILexicalBlockBase *LBB, |
| 129 | + DIScope *NewParent) { |
| 130 | + TempMDNode ClonedScope = LBB->clone(); |
| 131 | + cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent); |
| 132 | + return cast<DILexicalBlockBase>( |
| 133 | + MDNode::replaceWithUniqued(std::move(ClonedScope))); |
| 134 | +} |
| 135 | + |
| 136 | +using LineColumn = std::pair<unsigned /* Line */, unsigned /* Column */>; |
| 137 | + |
| 138 | +/// Returns the location of DILocalScope, if present, or a default value. |
| 139 | +static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) { |
| 140 | + assert(isa<DILocalScope>(S) && "Expected DILocalScope."); |
| 141 | + |
| 142 | + if (isa<DILexicalBlockFile>(S)) |
| 143 | + return Default; |
| 144 | + if (auto *LB = dyn_cast<DILexicalBlock>(S)) |
| 145 | + return {LB->getLine(), LB->getColumn()}; |
| 146 | + if (auto *SP = dyn_cast<DISubprogram>(S)) |
| 147 | + return {SP->getLine(), 0u}; |
| 148 | + |
| 149 | + llvm_unreachable("Unhandled type of DILocalScope."); |
| 150 | +} |
| 151 | + |
| 152 | +// Returns the nearest matching scope inside a subprogram. |
| 153 | +template <typename MatcherT> |
| 154 | +static std::pair<DIScope *, LineColumn> |
| 155 | +getNearestMatchingScope(const DILocation *L1, const DILocation *L2) { |
| 156 | + MatcherT Matcher; |
| 157 | + |
| 158 | + DIScope *S1 = L1->getScope(); |
| 159 | + DIScope *S2 = L2->getScope(); |
| 160 | + |
| 161 | + LineColumn Loc1(L1->getLine(), L1->getColumn()); |
| 162 | + for (; S1; S1 = S1->getScope()) { |
| 163 | + Loc1 = getLocalScopeLocationOr(S1, Loc1); |
| 164 | + Matcher.insert(S1, Loc1); |
| 165 | + if (isa<DISubprogram>(S1)) |
| 166 | + break; |
| 167 | + } |
| 168 | + |
| 169 | + LineColumn Loc2(L2->getLine(), L2->getColumn()); |
| 170 | + for (; S2; S2 = S2->getScope()) { |
| 171 | + Loc2 = getLocalScopeLocationOr(S2, Loc2); |
| 172 | + |
| 173 | + if (DIScope *S = Matcher.match(S2, Loc2)) |
| 174 | + return std::make_pair(S, Loc2); |
| 175 | + |
| 176 | + if (isa<DISubprogram>(S2)) |
| 177 | + break; |
| 178 | + } |
| 179 | + return std::make_pair(nullptr, LineColumn(L2->getLine(), L2->getColumn())); |
| 180 | +} |
| 181 | + |
| 182 | +// Matches equal scopes. |
| 183 | +struct EqualScopesMatcher { |
| 184 | + SmallPtrSet<DIScope *, 8> Scopes; |
| 185 | + |
| 186 | + void insert(DIScope *S, LineColumn Loc) { Scopes.insert(S); } |
| 187 | + |
| 188 | + DIScope *match(DIScope *S, LineColumn Loc) { |
| 189 | + return Scopes.contains(S) ? S : nullptr; |
| 190 | + } |
| 191 | +}; |
| 192 | + |
| 193 | +// Matches scopes with the same location. |
| 194 | +struct ScopeLocationsMatcher { |
| 195 | + SmallMapVector<std::pair<DIFile *, LineColumn>, SmallSetVector<DIScope *, 8>, |
| 196 | + 8> |
| 197 | + Scopes; |
| 198 | + |
| 199 | + void insert(DIScope *S, LineColumn Loc) { |
| 200 | + Scopes[{S->getFile(), Loc}].insert(S); |
| 201 | + } |
| 202 | + |
| 203 | + DIScope *match(DIScope *S, LineColumn Loc) { |
| 204 | + auto ScopesAtLoc = Scopes.find({S->getFile(), Loc}); |
| 205 | + // No scope found with the given location. |
| 206 | + if (ScopesAtLoc == Scopes.end()) |
| 207 | + return nullptr; |
| 208 | + |
| 209 | + // Prefer S over other scopes with the same location. |
| 210 | + if (ScopesAtLoc->second.contains(S)) |
| 211 | + return S; |
| 212 | + |
| 213 | + if (!ScopesAtLoc->second.empty()) |
| 214 | + return *ScopesAtLoc->second.begin(); |
| 215 | + |
| 216 | + llvm_unreachable("Scopes must not have empty entries."); |
| 217 | + } |
| 218 | +}; |
| 219 | + |
128 | 220 | DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
|
129 | 221 | if (!LocA || !LocB)
|
130 | 222 | return nullptr;
|
@@ -208,28 +300,31 @@ DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
|
208 | 300 | if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())
|
209 | 301 | return nullptr;
|
210 | 302 |
|
211 |
| - // Return the nearest common scope inside a subprogram. |
212 |
| - auto GetNearestCommonScope = [](DIScope *S1, DIScope *S2) -> DIScope * { |
213 |
| - SmallPtrSet<DIScope *, 8> Scopes; |
214 |
| - for (; S1; S1 = S1->getScope()) { |
215 |
| - Scopes.insert(S1); |
216 |
| - if (isa<DISubprogram>(S1)) |
217 |
| - break; |
218 |
| - } |
219 |
| - |
220 |
| - for (; S2; S2 = S2->getScope()) { |
221 |
| - if (Scopes.count(S2)) |
222 |
| - return S2; |
223 |
| - if (isa<DISubprogram>(S2)) |
224 |
| - break; |
225 |
| - } |
226 |
| - |
227 |
| - return nullptr; |
228 |
| - }; |
229 |
| - |
230 |
| - auto Scope = GetNearestCommonScope(L1->getScope(), L2->getScope()); |
| 303 | + // Find nearest common scope inside subprogram. |
| 304 | + DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first; |
231 | 305 | assert(Scope && "No common scope in the same subprogram?");
|
232 | 306 |
|
| 307 | + // Try using the nearest scope with common location if files are different. |
| 308 | + if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) { |
| 309 | + auto [CommonLocScope, CommonLoc] = |
| 310 | + getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2); |
| 311 | + |
| 312 | + // If CommonLocScope is a DILexicalBlockBase, clone it and locate |
| 313 | + // a new scope inside the nearest common scope to preserve |
| 314 | + // lexical blocks structure. |
| 315 | + if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope); |
| 316 | + LBB && LBB != Scope) |
| 317 | + CommonLocScope = cloneAndReplaceParentScope(LBB, Scope); |
| 318 | + |
| 319 | + Scope = CommonLocScope; |
| 320 | + |
| 321 | + // If files are still different, assume that L1 and L2 were "included" |
| 322 | + // from CommonLoc. Use it as merged location. |
| 323 | + if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) |
| 324 | + return DILocation::get(C, CommonLoc.first, CommonLoc.second, |
| 325 | + CommonLocScope, InlinedAt); |
| 326 | + } |
| 327 | + |
233 | 328 | bool SameLine = L1->getLine() == L2->getLine();
|
234 | 329 | bool SameCol = L1->getColumn() == L2->getColumn();
|
235 | 330 | unsigned Line = SameLine ? L1->getLine() : 0;
|
@@ -1187,10 +1282,8 @@ DILocalScope *DILocalScope::cloneScopeForSubprogram(
|
1187 | 1282 | // cached result).
|
1188 | 1283 | DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
|
1189 | 1284 | for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
|
1190 |
| - TempMDNode ClonedScope = ScopeToUpdate->clone(); |
1191 |
| - cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope); |
1192 |
| - UpdatedScope = |
1193 |
| - cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope))); |
| 1285 | + UpdatedScope = cloneAndReplaceParentScope( |
| 1286 | + cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope); |
1194 | 1287 | Cache[ScopeToUpdate] = UpdatedScope;
|
1195 | 1288 | }
|
1196 | 1289 |
|
|
0 commit comments