@@ -118,6 +118,14 @@ DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {
118
118
return Merged;
119
119
}
120
120
121
+ static DILexicalBlockBase *cloneAndReplaceParentScope (DILexicalBlockBase *LBB,
122
+ DIScope *NewParent) {
123
+ TempMDNode ClonedScope = LBB->clone ();
124
+ cast<DILexicalBlockBase>(*ClonedScope).replaceScope (NewParent);
125
+ return cast<DILexicalBlockBase>(
126
+ MDNode::replaceWithUniqued (std::move (ClonedScope)));
127
+ }
128
+
121
129
using LineColumn = std::pair<unsigned /* Line */ , unsigned /* Column */ >;
122
130
123
131
// / Returns the location of DILocalScope, if present, or a default value.
@@ -134,6 +142,82 @@ static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) {
134
142
llvm_unreachable (" Unhandled type of DILocalScope." );
135
143
}
136
144
145
+ // Returns the nearest matching scope inside a subprogram.
146
+ template <typename MatcherT>
147
+ static std::pair<DIScope *, LineColumn>
148
+ getNearestMatchingScope (const DILocation *L1, const DILocation *L2) {
149
+ MatcherT Matcher;
150
+
151
+ DIScope *S1 = L1->getScope ();
152
+ DIScope *S2 = L2->getScope ();
153
+
154
+ // When matching DILexicalBlockFile's, ignore column numbers, so that
155
+ // DILocation's having different columns within the same
156
+ // DILexicalBlockFile will match.
157
+ auto GetLocForBlockFile = [](LineColumn L) {
158
+ L.second = 0 ;
159
+ return L;
160
+ };
161
+
162
+ LineColumn Loc1 (L1->getLine (), L1->getColumn ());
163
+ for (; S1; S1 = S1->getScope ()) {
164
+ Loc1 = getLocalScopeLocationOr (S1, GetLocForBlockFile (Loc1));
165
+ Matcher.insert (S1, Loc1);
166
+ if (isa<DISubprogram>(S1))
167
+ break ;
168
+ }
169
+
170
+ LineColumn Loc2 (L2->getLine (), L2->getColumn ());
171
+ for (; S2; S2 = S2->getScope ()) {
172
+ Loc2 = getLocalScopeLocationOr (S2, GetLocForBlockFile (Loc2));
173
+
174
+ if (DIScope *S = Matcher.match (S2, Loc2))
175
+ return std::make_pair (S, Loc2);
176
+
177
+ if (isa<DISubprogram>(S2))
178
+ break ;
179
+ }
180
+ return std::make_pair (nullptr , LineColumn (L2->getLine (), L2->getColumn ()));
181
+ }
182
+
183
+ // Matches equal scopes.
184
+ struct EqualScopesMatcher {
185
+ SmallPtrSet<DIScope *, 8 > Scopes;
186
+
187
+ void insert (DIScope *S, LineColumn Loc) { Scopes.insert (S); }
188
+
189
+ DIScope *match (DIScope *S, LineColumn Loc) {
190
+ return Scopes.contains (S) ? S : nullptr ;
191
+ }
192
+ };
193
+
194
+ // Matches scopes with the same location.
195
+ struct ScopeLocationsMatcher {
196
+ SmallMapVector<std::pair<DIFile *, LineColumn>, SmallSetVector<DIScope *, 8 >,
197
+ 8 >
198
+ Scopes;
199
+
200
+ void insert (DIScope *S, LineColumn Loc) {
201
+ Scopes[{S->getFile (), Loc}].insert (S);
202
+ }
203
+
204
+ DIScope *match (DIScope *S, LineColumn Loc) {
205
+ auto ScopesAtLoc = Scopes.find ({S->getFile (), Loc});
206
+ // No scope found with the given location.
207
+ if (ScopesAtLoc == Scopes.end ())
208
+ return nullptr ;
209
+
210
+ // Prefer S over other scopes with the same location.
211
+ if (ScopesAtLoc->second .contains (S))
212
+ return S;
213
+
214
+ if (!ScopesAtLoc->second .empty ())
215
+ return *ScopesAtLoc->second .begin ();
216
+
217
+ llvm_unreachable (" Scopes must not have empty entries." );
218
+ }
219
+ };
220
+
137
221
DILocation *DILocation::getMergedLocation (DILocation *LocA, DILocation *LocB) {
138
222
if (!LocA || !LocB)
139
223
return nullptr ;
@@ -203,66 +287,29 @@ DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
203
287
if (L1->getScope ()->getSubprogram () != L2->getScope ()->getSubprogram ())
204
288
return nullptr ;
205
289
206
- // Return the nearest common scope inside a subprogram.
207
- auto GetNearestCommonScope =
208
- [](const DILocation *L1,
209
- const DILocation *L2) -> std::pair<DIScope *, LineColumn> {
210
- DIScope *S1 = L1->getScope ();
211
- DIScope *S2 = L2->getScope ();
212
-
213
- SmallMapVector<std::pair<DIFile *, LineColumn>,
214
- SmallSetVector<DIScope *, 8 >, 8 >
215
- Scopes;
216
-
217
- // When matching DILexicalBlockFile's, ignore column numbers, so that
218
- // DILocation's having different columns within the same
219
- // DILexicalBlockFile will match.
220
- auto getLocForBlockFile = [](LineColumn L) {
221
- L.second = 0 ;
222
- return L;
223
- };
224
-
225
- LineColumn Loc1 (L1->getLine (), L1->getColumn ());
226
- for (; S1; S1 = S1->getScope ()) {
227
- Loc1 = getLocalScopeLocationOr (S1, getLocForBlockFile (Loc1));
228
- Scopes[{S1->getFile (), Loc1}].insert (S1);
229
-
230
- if (isa<DISubprogram>(S1))
231
- break ;
232
- }
233
-
234
- LineColumn Loc2 (L2->getLine (), L2->getColumn ());
235
- for (; S2; S2 = S2->getScope ()) {
236
- Loc2 = getLocalScopeLocationOr (S2, getLocForBlockFile (Loc2));
237
-
238
- auto ScopesAtLoc = Scopes.find ({S2->getFile (), Loc2});
239
- // No scope found with the same file, line and column as S2.
240
- if (ScopesAtLoc == Scopes.end ())
241
- continue ;
242
-
243
- // Return S2 if it is L1's parent.
244
- if (ScopesAtLoc->second .contains (S2))
245
- return std::make_pair (S2, Loc2);
246
-
247
- // Return any L1's parent with the same file, line and column as S2.
248
- if (!ScopesAtLoc->second .empty ())
249
- return std::make_pair (*ScopesAtLoc->second .begin (), Loc2);
250
-
251
- if (isa<DISubprogram>(S2))
252
- break ;
253
- }
254
-
255
- return std::make_pair (nullptr ,
256
- LineColumn (L2->getLine (), L2->getColumn ()));
257
- };
258
-
259
- auto [Scope, ScopeLoc] = GetNearestCommonScope (L1, L2);
290
+ // Find nearest common scope inside subprogram.
291
+ DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first ;
260
292
assert (Scope && " No common scope in the same subprogram?" );
261
293
262
- // Use inclusion location if files are different.
294
+ // Try using the nearest scope with common location if files are different.
263
295
if (Scope->getFile () != L1->getFile () || L1->getFile () != L2->getFile ()) {
264
- return DILocation::get (C, ScopeLoc.first , ScopeLoc.second , Scope,
265
- InlinedAt);
296
+ auto [CommonLocScope, CommonLoc] =
297
+ getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);
298
+
299
+ // If CommonLocScope is a DILexicalBlockBase, clone it and locate
300
+ // a new scope inside the nearest common scope to preserve
301
+ // lexical blocks structure.
302
+ if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
303
+ LBB && LBB != Scope)
304
+ CommonLocScope = cloneAndReplaceParentScope (LBB, Scope);
305
+
306
+ Scope = CommonLocScope;
307
+
308
+ // If files are still different, assume that L1 and L2 were "included"
309
+ // from CommonLoc. Use it as merged location.
310
+ if (Scope->getFile () != L1->getFile () || L1->getFile () != L2->getFile ())
311
+ return DILocation::get (C, CommonLoc.first , CommonLoc.second ,
312
+ CommonLocScope, InlinedAt);
266
313
}
267
314
268
315
bool SameLine = L1->getLine () == L2->getLine ();
@@ -1179,10 +1226,8 @@ DILocalScope *DILocalScope::cloneScopeForSubprogram(
1179
1226
// cached result).
1180
1227
DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
1181
1228
for (DIScope *ScopeToUpdate : reverse (ScopeChain)) {
1182
- TempMDNode ClonedScope = ScopeToUpdate->clone ();
1183
- cast<DILexicalBlockBase>(*ClonedScope).replaceScope (UpdatedScope);
1184
- UpdatedScope =
1185
- cast<DIScope>(MDNode::replaceWithUniqued (std::move (ClonedScope)));
1229
+ UpdatedScope = cloneAndReplaceParentScope (
1230
+ cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
1186
1231
Cache[ScopeToUpdate] = UpdatedScope;
1187
1232
}
1188
1233
0 commit comments