@@ -217,6 +217,87 @@ static bool hasNonInlinedDebugScope(SILInstruction *i) {
217
217
return false ;
218
218
}
219
219
220
+ namespace {
221
+
222
+ // / A helper struct that attempts to infer the decl associated with a value from
223
+ // / one of its uses. It does this by searching the def-use graph locally for
224
+ // / debug_value and debug_value_addr instructions.
225
+ struct ValueUseToDeclInferrer {
226
+ using Argument = ValueToDeclInferrer::Argument;
227
+ using ArgumentKeyKind = ValueToDeclInferrer::ArgumentKeyKind;
228
+
229
+ SmallPtrSet<swift::SILInstruction *, 8 > visitedDebugValueInsts;
230
+ ValueToDeclInferrer &object;
231
+ ArgumentKeyKind keyKind;
232
+ SmallVectorImpl<Argument> &resultingInferredDecls;
233
+
234
+ bool findDecls (Operand *use, SILValue value);
235
+ };
236
+
237
+ } // anonymous namespace
238
+
239
+ bool ValueUseToDeclInferrer::findDecls (Operand *use, SILValue value) {
240
+ // Skip type dependent operands.
241
+ if (use->isTypeDependent ())
242
+ return false ;
243
+
244
+ // Then see if we have a debug_value that is associated with a non-inlined
245
+ // debug scope. Such an instruction is an instruction that is from the
246
+ // current function.
247
+ auto *dvi = dyn_cast<DebugValueInst>(use->getUser ());
248
+ if (!dvi)
249
+ return false ;
250
+
251
+ if (!hasNonInlinedDebugScope (dvi))
252
+ return false ;
253
+
254
+ // See if we have already inferred this debug_value as a potential source
255
+ // for this instruction. In such a case, just return.
256
+ if (!visitedDebugValueInsts.insert (dvi).second )
257
+ return false ;
258
+
259
+ if (auto *decl = dvi->getDecl ()) {
260
+ std::string msg;
261
+ {
262
+ llvm::raw_string_ostream stream (msg);
263
+ // If we are not a top level use, we must be a rc-identical transitive
264
+ // use. In such a case, we just print out the rc identical value
265
+ // without a projection path. This is because we now have a better
266
+ // name and the name is rc-identical to whatever was at the end of the
267
+ // projection path but is not at the end of that projection path.
268
+ object.printNote (stream, decl,
269
+ use->get () == value /* print projection path*/ );
270
+ }
271
+ resultingInferredDecls.emplace_back (
272
+ OptRemark::ArgumentKey{keyKind, " InferredValue" }, std::move (msg), decl);
273
+ return true ;
274
+ }
275
+
276
+ // If we did not have a decl, see if we were asked for testing
277
+ // purposes to use SILDebugInfo to create a placeholder inferred
278
+ // value.
279
+ if (!DecllessDebugValueUseSILDebugInfo)
280
+ return false ;
281
+
282
+ auto varInfo = dvi->getVarInfo ();
283
+ if (!varInfo)
284
+ return false ;
285
+
286
+ auto name = varInfo->Name ;
287
+ if (name.empty ())
288
+ return false ;
289
+
290
+ std::string msg;
291
+ {
292
+ llvm::raw_string_ostream stream (msg);
293
+ object.printNote (stream, name,
294
+ use->get () == value /* print projection path*/ );
295
+ }
296
+ resultingInferredDecls.push_back (
297
+ Argument ({keyKind, " InferredValue" }, std::move (msg), dvi->getLoc ()));
298
+ return true ;
299
+ }
300
+
220
301
bool ValueToDeclInferrer::infer (
221
302
ArgumentKeyKind keyKind, SILValue value,
222
303
SmallVectorImpl<Argument> &resultingInferredDecls,
@@ -225,7 +306,8 @@ bool ValueToDeclInferrer::infer(
225
306
SWIFT_DEFER {
226
307
accessPath.clear ();
227
308
};
228
- SmallPtrSet<SILInstruction *, 8 > visitedDebugValueInsts;
309
+ ValueUseToDeclInferrer valueUseInferrer{
310
+ {}, *this , keyKind, resultingInferredDecls};
229
311
bool foundSingleRefElementAddr = false ;
230
312
231
313
// This is a linear IR traversal using a 'falling while loop'. That means
@@ -308,66 +390,7 @@ bool ValueToDeclInferrer::infer(
308
390
// instance, if we FSOed.
309
391
bool foundDeclFromUse = false ;
310
392
rcfi.visitRCUses (value, [&](Operand *use) {
311
- // Skip type dependent uses.
312
- if (use->isTypeDependent ())
313
- return ;
314
-
315
- // Then see if we have a debug_value that is associated with a non-inlined
316
- // debug scope. Such an instruction is an instruction that is from the
317
- // current function.
318
- auto *dvi = dyn_cast<DebugValueInst>(use->getUser ());
319
- if (!dvi)
320
- return ;
321
-
322
- if (!hasNonInlinedDebugScope (dvi))
323
- return ;
324
-
325
- // See if we have already inferred this debug_value as a potential source
326
- // for this instruction. In such a case, just return.
327
- if (!visitedDebugValueInsts.insert (dvi).second )
328
- return ;
329
-
330
- if (auto *decl = dvi->getDecl ()) {
331
- std::string msg;
332
- {
333
- llvm::raw_string_ostream stream (msg);
334
- // If we are not a top level use, we must be a rc-identical transitive
335
- // use. In such a case, we just print out the rc identical value
336
- // without a projection path. This is because we now have a better
337
- // name and the name is rc-identical to whatever was at the end of the
338
- // projection path but is not at the end of that projection path.
339
- printNote (stream, decl,
340
- use->get () == value /* print projection path*/ );
341
- }
342
- resultingInferredDecls.emplace_back (
343
- OptRemark::ArgumentKey{keyKind, " InferredValue" }, std::move (msg),
344
- decl);
345
- foundDeclFromUse = true ;
346
- return ;
347
- }
348
-
349
- // If we did not have a decl, see if we were asked for testing
350
- // purposes to use SILDebugInfo to create a placeholder inferred
351
- // value.
352
- if (!DecllessDebugValueUseSILDebugInfo)
353
- return ;
354
-
355
- auto varInfo = dvi->getVarInfo ();
356
- if (!varInfo)
357
- return ;
358
-
359
- auto name = varInfo->Name ;
360
- if (name.empty ())
361
- return ;
362
-
363
- std::string msg;
364
- {
365
- llvm::raw_string_ostream stream (msg);
366
- printNote (stream, name, use->get () == value /* print projection path*/ );
367
- }
368
- resultingInferredDecls.push_back (
369
- Argument ({keyKind, " InferredValue" }, std::move (msg), dvi->getLoc ()));
370
- foundDeclFromUse = true ;
393
+ foundDeclFromUse |= valueUseInferrer.findDecls (use, value);
371
394
});
372
395
373
396
// At this point, we could not infer any argument. See if we can look up the
0 commit comments