@@ -63,20 +63,30 @@ static llvm::cl::opt<bool> DecllessDebugValueUseSILDebugInfo(
6363namespace {
6464
6565struct ValueToDeclInferrer {
66+
67+ enum class NotePrefix {
68+ of,
69+ fromLocation,
70+ toLocation,
71+ inMemoryLocationOf
72+ };
73+
6674 using Argument = OptRemark::Argument;
6775 using ArgumentKeyKind = OptRemark::ArgumentKeyKind;
6876
6977 SmallVector<std::pair<SILType, Projection>, 32 > accessPath;
7078 SmallVector<Operand *, 32 > rcIdenticalSecondaryUseSearch;
7179 RCIdentityFunctionInfo &rcfi;
80+ NotePrefix currentNotePrefix = NotePrefix::of;
7281
7382 ValueToDeclInferrer (RCIdentityFunctionInfo &rcfi) : rcfi(rcfi) {}
7483
7584 // / Given a value, attempt to infer a conservative list of decls that the
7685 // / passed in value could be referring to. This is done just using heuristics
7786 bool infer (ArgumentKeyKind keyKind, SILValue value,
7887 SmallVectorImpl<Argument> &resultingInferredDecls,
79- bool allowSingleRefEltAddrPeek = false );
88+ bool allowSingleRefEltAddrPeek = false ,
89+ NotePrefix notePrefix = NotePrefix::of);
8090
8191 // / Print out a note to \p stream that beings at decl and then if
8292 // / useProjectionPath is set to true iterates the accessPath we computed for
@@ -196,7 +206,20 @@ void ValueToDeclInferrer::printAccessPath(llvm::raw_string_ostream &stream) {
196206void ValueToDeclInferrer::printNote (llvm::raw_string_ostream &stream,
197207 StringRef name,
198208 bool shouldPrintAccessPath) {
199- stream << " of '" << name;
209+ switch (currentNotePrefix) {
210+ case NotePrefix::of:
211+ stream << " of '" << name;
212+ break ;
213+ case NotePrefix::fromLocation:
214+ stream << " from location '" << name;
215+ break ;
216+ case NotePrefix::toLocation:
217+ stream << " to location '" << name;
218+ break ;
219+ case NotePrefix::inMemoryLocationOf:
220+ stream << " in memory location of '" << name;
221+ break ;
222+ }
200223 if (shouldPrintAccessPath)
201224 printAccessPath (stream);
202225 stream << " '" ;
@@ -314,7 +337,11 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
314337bool ValueToDeclInferrer::infer (
315338 ArgumentKeyKind keyKind, SILValue value,
316339 SmallVectorImpl<Argument> &resultingInferredDecls,
317- bool allowSingleRefEltAddrPeek) {
340+ bool allowSingleRefEltAddrPeek,
341+ NotePrefix notePrefix) {
342+
343+ currentNotePrefix = notePrefix;
344+
318345 // Clear the stored access path at end of scope.
319346 SWIFT_DEFER { accessPath.clear (); };
320347 ValueUseToDeclInferrer valueUseInferrer{
@@ -533,10 +560,72 @@ struct AssemblyVisionRemarkGeneratorInstructionVisitor
533560 void visitCheckedCastAddrBranchInst (CheckedCastAddrBranchInst *ccabi);
534561 void visitUnconditionalCheckedCastAddrInst (
535562 UnconditionalCheckedCastAddrInst *uccai);
563+ void visitCopyAddrInst (CopyAddrInst *copy);
564+ void visitDestroyAddrInst (DestroyAddrInst *destroy);
536565};
537566
538567} // anonymous namespace
539568
569+ void AssemblyVisionRemarkGeneratorInstructionVisitor::
570+ visitCopyAddrInst (CopyAddrInst *copy) {
571+ ORE.emit ([&]() {
572+ using namespace OptRemark ;
573+ SmallVector<Argument, 8 > inferredArgs;
574+ bool foundArgs = valueToDeclInferrer.infer (
575+ ArgumentKeyKind::Note, copy->getSrc (), inferredArgs,
576+ true /* allow single ref elt peek*/ ,
577+ ValueToDeclInferrer::NotePrefix::fromLocation);
578+ (void )foundArgs;
579+
580+ // Use the actual source loc of the
581+ auto remark = RemarkMissed (" memory" , *copy)
582+ << " Memory copy of value with type '"
583+ << NV (" ValueType" , copy->getSrc ()->getType ()) << " '" ;
584+ if (foundArgs) {
585+ for (auto arg : inferredArgs) {
586+ remark << arg;
587+ }
588+ }
589+ inferredArgs.clear ();
590+ foundArgs = valueToDeclInferrer.infer (
591+ ArgumentKeyKind::Note, copy->getDest (), inferredArgs,
592+ true /* allow single ref elt peek*/ ,
593+ ValueToDeclInferrer::NotePrefix::toLocation);
594+ if (foundArgs) {
595+ for (auto arg : inferredArgs) {
596+ remark << arg;
597+ }
598+ }
599+
600+ return remark;
601+ });
602+ }
603+
604+ void AssemblyVisionRemarkGeneratorInstructionVisitor::
605+ visitDestroyAddrInst (DestroyAddrInst *destroy) {
606+ ORE.emit ([&]() {
607+ using namespace OptRemark ;
608+ SmallVector<Argument, 8 > inferredArgs;
609+ bool foundArgs = valueToDeclInferrer.infer (
610+ ArgumentKeyKind::Note, destroy->getOperand (), inferredArgs,
611+ true /* allow single ref elt peek*/ ,
612+ ValueToDeclInferrer::NotePrefix::inMemoryLocationOf);
613+ (void )foundArgs;
614+
615+ // Use the actual source loc of the
616+ auto remark = RemarkMissed (" memory" , *destroy)
617+ << " Memory destroy of value with type '"
618+ << NV (" ValueType" , destroy->getOperand ()->getType ()) << " '" ;
619+ if (foundArgs) {
620+ for (auto arg : inferredArgs) {
621+ remark << arg;
622+ }
623+ }
624+
625+ return remark;
626+ });
627+ }
628+
540629void AssemblyVisionRemarkGeneratorInstructionVisitor::
541630 visitUnconditionalCheckedCastAddrInst (
542631 UnconditionalCheckedCastAddrInst *uccai) {
0 commit comments