@@ -658,15 +658,18 @@ struct DiagnosticEvaluator final
658658 RegionAnalysisFunctionInfo *info;
659659 SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
660660 &transferOpToRequireInstMultiMap;
661+ SmallVectorImpl<Operand *> &transferredNonTransferrable;
661662
662663 DiagnosticEvaluator (Partition &workingPartition,
663664 RegionAnalysisFunctionInfo *info,
664665 SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
665- &transferOpToRequireInstMultiMap)
666+ &transferOpToRequireInstMultiMap,
667+ SmallVectorImpl<Operand *> &transferredNonTransferrable)
666668 : PartitionOpEvaluatorBaseImpl(workingPartition,
667669 info->getOperandSetFactory ()),
668670 info(info),
669- transferOpToRequireInstMultiMap(transferOpToRequireInstMultiMap) {}
671+ transferOpToRequireInstMultiMap(transferOpToRequireInstMultiMap),
672+ transferredNonTransferrable(transferredNonTransferrable) {}
670673
671674 void handleFailure (const PartitionOp &partitionOp,
672675 TrackableValueID transferredVal,
@@ -710,7 +713,8 @@ struct DiagnosticEvaluator final
710713 << " ID: %%" << transferredVal << " \n "
711714 << " Rep: "
712715 << *info->getValueMap ().getRepresentative (transferredVal));
713- diagnose (partitionOp, diag::regionbasedisolation_selforargtransferred);
716+ auto *self = const_cast <DiagnosticEvaluator *>(this );
717+ self->transferredNonTransferrable .push_back (partitionOp.getSourceOp ());
714718 }
715719
716720 bool isActorDerived (Element element) const {
@@ -727,17 +731,30 @@ struct DiagnosticEvaluator final
727731
728732} // namespace
729733
730- // / Once we have reached a fixpoint, this routine runs over all blocks again
731- // / reporting any failures by applying our ops to the converged dataflow
732- // / state.
733- static void emitDiagnostics (RegionAnalysisFunctionInfo *regionInfo) {
734- auto *function = regionInfo->getFunction ();
735- LLVM_DEBUG (llvm::dbgs () << " Emitting diagnostics for function "
736- << function->getName () << " \n " );
734+ namespace {
737735
736+ class TransferNonSendableImpl {
737+ RegionAnalysisFunctionInfo *regionInfo;
738738 SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
739739 transferOpToRequireInstMultiMap;
740+ SmallVector<Operand *, 8 > transferredNonTransferrable;
741+
742+ public:
743+ TransferNonSendableImpl (RegionAnalysisFunctionInfo *regionInfo)
744+ : regionInfo(regionInfo) {}
745+
746+ void run ();
747+
748+ private:
749+ void runDiagnosticEvaluator ();
750+
751+ void emitUseAfterTransferDiagnostics ();
752+ void emitTransferredNonTransferrableDiagnostics ();
753+ };
754+
755+ } // namespace
740756
757+ void TransferNonSendableImpl::runDiagnosticEvaluator () {
741758 // Then for each block...
742759 LLVM_DEBUG (llvm::dbgs () << " Walking blocks for diagnostics.\n " );
743760 for (auto [block, blockState] : regionInfo->getRange ()) {
@@ -749,7 +766,8 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
749766 // has callbacks that emit diagnsotics...
750767 Partition workingPartition = blockState.getEntryPartition ();
751768 DiagnosticEvaluator eval (workingPartition, regionInfo,
752- transferOpToRequireInstMultiMap);
769+ transferOpToRequireInstMultiMap,
770+ transferredNonTransferrable);
753771
754772 // And then evaluate all of our partition ops on the entry partition.
755773 for (auto &partitionOp : blockState.getPartitionOps ()) {
@@ -762,7 +780,10 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
762780
763781 // Now that we have found all of our transferInsts/Requires emit errors.
764782 transferOpToRequireInstMultiMap.setFrozen ();
783+ }
765784
785+ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics () {
786+ auto *function = regionInfo->getFunction ();
766787 BasicBlockData<BlockLivenessInfo> blockLivenessInfo (function);
767788 // We use a generation counter so we can lazily reset blockLivenessInfo
768789 // since we cannot clear it without iterating over it.
@@ -872,6 +893,25 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
872893 }
873894}
874895
896+ void TransferNonSendableImpl::emitTransferredNonTransferrableDiagnostics () {
897+ for (auto *op : transferredNonTransferrable) {
898+ diagnose (op->getUser (), diag::regionbasedisolation_selforargtransferred);
899+ }
900+ }
901+
902+ // / Once we have reached a fixpoint, this routine runs over all blocks again
903+ // / reporting any failures by applying our ops to the converged dataflow
904+ // / state.
905+ void TransferNonSendableImpl::run () {
906+ auto *function = regionInfo->getFunction ();
907+ LLVM_DEBUG (llvm::dbgs () << " Emitting diagnostics for function "
908+ << function->getName () << " \n " );
909+
910+ runDiagnosticEvaluator ();
911+ emitTransferredNonTransferrableDiagnostics ();
912+ emitUseAfterTransferDiagnostics ();
913+ }
914+
875915// ===----------------------------------------------------------------------===//
876916// MARK: Top Level Entrypoint
877917// ===----------------------------------------------------------------------===//
@@ -893,7 +933,8 @@ class TransferNonSendable : public SILFunctionTransform {
893933 LLVM_DEBUG (llvm::dbgs ()
894934 << " ===> PROCESSING: " << function->getName () << ' \n ' );
895935
896- emitDiagnostics (functionInfo);
936+ TransferNonSendableImpl impl (functionInfo);
937+ impl.run ();
897938 }
898939};
899940
0 commit comments