@@ -125,6 +125,14 @@ 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
+
128
136
using LineColumn = std::pair<unsigned /* Line */ , unsigned /* Column */ >;
129
137
130
138
// / Returns the location of DILocalScope, if present, or a default value.
@@ -141,6 +149,82 @@ static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) {
141
149
llvm_unreachable (" Unhandled type of DILocalScope." );
142
150
}
143
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
+ // When matching DILexicalBlockFile's, ignore column numbers, so that
162
+ // DILocation's having different columns within the same
163
+ // DILexicalBlockFile will match.
164
+ auto GetLocForBlockFile = [](LineColumn L) {
165
+ L.second = 0 ;
166
+ return L;
167
+ };
168
+
169
+ LineColumn Loc1 (L1->getLine (), L1->getColumn ());
170
+ for (; S1; S1 = S1->getScope ()) {
171
+ Loc1 = getLocalScopeLocationOr (S1, GetLocForBlockFile (Loc1));
172
+ Matcher.insert (S1, Loc1);
173
+ if (isa<DISubprogram>(S1))
174
+ break ;
175
+ }
176
+
177
+ LineColumn Loc2 (L2->getLine (), L2->getColumn ());
178
+ for (; S2; S2 = S2->getScope ()) {
179
+ Loc2 = getLocalScopeLocationOr (S2, GetLocForBlockFile (Loc2));
180
+
181
+ if (DIScope *S = Matcher.match (S2, Loc2))
182
+ return std::make_pair (S, Loc2);
183
+
184
+ if (isa<DISubprogram>(S2))
185
+ break ;
186
+ }
187
+ return std::make_pair (nullptr , LineColumn (L2->getLine (), L2->getColumn ()));
188
+ }
189
+
190
+ // Matches equal scopes.
191
+ struct EqualScopesMatcher {
192
+ SmallPtrSet<DIScope *, 8 > Scopes;
193
+
194
+ void insert (DIScope *S, LineColumn Loc) { Scopes.insert (S); }
195
+
196
+ DIScope *match (DIScope *S, LineColumn Loc) {
197
+ return Scopes.contains (S) ? S : nullptr ;
198
+ }
199
+ };
200
+
201
+ // Matches scopes with the same location.
202
+ struct ScopeLocationsMatcher {
203
+ SmallMapVector<std::pair<DIFile *, LineColumn>, SmallSetVector<DIScope *, 8 >,
204
+ 8 >
205
+ Scopes;
206
+
207
+ void insert (DIScope *S, LineColumn Loc) {
208
+ Scopes[{S->getFile (), Loc}].insert (S);
209
+ }
210
+
211
+ DIScope *match (DIScope *S, LineColumn Loc) {
212
+ auto ScopesAtLoc = Scopes.find ({S->getFile (), Loc});
213
+ // No scope found with the given location.
214
+ if (ScopesAtLoc == Scopes.end ())
215
+ return nullptr ;
216
+
217
+ // Prefer S over other scopes with the same location.
218
+ if (ScopesAtLoc->second .contains (S))
219
+ return S;
220
+
221
+ if (!ScopesAtLoc->second .empty ())
222
+ return *ScopesAtLoc->second .begin ();
223
+
224
+ llvm_unreachable (" Scopes must not have empty entries." );
225
+ }
226
+ };
227
+
144
228
DILocation *DILocation::getMergedLocation (DILocation *LocA, DILocation *LocB) {
145
229
if (!LocA || !LocB)
146
230
return nullptr ;
@@ -224,66 +308,29 @@ DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
224
308
if (L1->getScope ()->getSubprogram () != L2->getScope ()->getSubprogram ())
225
309
return nullptr ;
226
310
227
- // Return the nearest common scope inside a subprogram.
228
- auto GetNearestCommonScope =
229
- [](const DILocation *L1,
230
- const DILocation *L2) -> std::pair<DIScope *, LineColumn> {
231
- DIScope *S1 = L1->getScope ();
232
- DIScope *S2 = L2->getScope ();
233
-
234
- SmallMapVector<std::pair<DIFile *, LineColumn>,
235
- SmallSetVector<DIScope *, 8 >, 8 >
236
- Scopes;
237
-
238
- // When matching DILexicalBlockFile's, ignore column numbers, so that
239
- // DILocation's having different columns within the same
240
- // DILexicalBlockFile will match.
241
- auto getLocForBlockFile = [](LineColumn L) {
242
- L.second = 0 ;
243
- return L;
244
- };
245
-
246
- LineColumn Loc1 (L1->getLine (), L1->getColumn ());
247
- for (; S1; S1 = S1->getScope ()) {
248
- Loc1 = getLocalScopeLocationOr (S1, getLocForBlockFile (Loc1));
249
- Scopes[{S1->getFile (), Loc1}].insert (S1);
250
-
251
- if (isa<DISubprogram>(S1))
252
- break ;
253
- }
254
-
255
- LineColumn Loc2 (L2->getLine (), L2->getColumn ());
256
- for (; S2; S2 = S2->getScope ()) {
257
- Loc2 = getLocalScopeLocationOr (S2, getLocForBlockFile (Loc2));
258
-
259
- auto ScopesAtLoc = Scopes.find ({S2->getFile (), Loc2});
260
- // No scope found with the same file, line and column as S2.
261
- if (ScopesAtLoc == Scopes.end ())
262
- continue ;
263
-
264
- // Return S2 if it is L1's parent.
265
- if (ScopesAtLoc->second .contains (S2))
266
- return std::make_pair (S2, Loc2);
267
-
268
- // Return any L1's parent with the same file, line and column as S2.
269
- if (!ScopesAtLoc->second .empty ())
270
- return std::make_pair (*ScopesAtLoc->second .begin (), Loc2);
271
-
272
- if (isa<DISubprogram>(S2))
273
- break ;
274
- }
275
-
276
- return std::make_pair (nullptr ,
277
- LineColumn (L2->getLine (), L2->getColumn ()));
278
- };
279
-
280
- auto [Scope, ScopeLoc] = GetNearestCommonScope (L1, L2);
311
+ // Find nearest common scope inside subprogram.
312
+ DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first ;
281
313
assert (Scope && " No common scope in the same subprogram?" );
282
314
283
- // Use inclusion location if files are different.
315
+ // Try using the nearest scope with common location if files are different.
284
316
if (Scope->getFile () != L1->getFile () || L1->getFile () != L2->getFile ()) {
285
- return DILocation::get (C, ScopeLoc.first , ScopeLoc.second , Scope,
286
- InlinedAt);
317
+ auto [CommonLocScope, CommonLoc] =
318
+ getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);
319
+
320
+ // If CommonLocScope is a DILexicalBlockBase, clone it and locate
321
+ // a new scope inside the nearest common scope to preserve
322
+ // lexical blocks structure.
323
+ if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
324
+ LBB && LBB != Scope)
325
+ CommonLocScope = cloneAndReplaceParentScope (LBB, Scope);
326
+
327
+ Scope = CommonLocScope;
328
+
329
+ // If files are still different, assume that L1 and L2 were "included"
330
+ // from CommonLoc. Use it as merged location.
331
+ if (Scope->getFile () != L1->getFile () || L1->getFile () != L2->getFile ())
332
+ return DILocation::get (C, CommonLoc.first , CommonLoc.second ,
333
+ CommonLocScope, InlinedAt);
287
334
}
288
335
289
336
bool SameLine = L1->getLine () == L2->getLine ();
@@ -1243,10 +1290,8 @@ DILocalScope *DILocalScope::cloneScopeForSubprogram(
1243
1290
// cached result).
1244
1291
DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
1245
1292
for (DIScope *ScopeToUpdate : reverse (ScopeChain)) {
1246
- TempMDNode ClonedScope = ScopeToUpdate->clone ();
1247
- cast<DILexicalBlockBase>(*ClonedScope).replaceScope (UpdatedScope);
1248
- UpdatedScope =
1249
- cast<DIScope>(MDNode::replaceWithUniqued (std::move (ClonedScope)));
1293
+ UpdatedScope = cloneAndReplaceParentScope (
1294
+ cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
1250
1295
Cache[ScopeToUpdate] = UpdatedScope;
1251
1296
}
1252
1297
0 commit comments