@@ -658,15 +658,18 @@ struct DiagnosticEvaluator final
658
658
RegionAnalysisFunctionInfo *info;
659
659
SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
660
660
&transferOpToRequireInstMultiMap;
661
+ SmallVectorImpl<Operand *> &transferredNonTransferrable;
661
662
662
663
DiagnosticEvaluator (Partition &workingPartition,
663
664
RegionAnalysisFunctionInfo *info,
664
665
SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
665
- &transferOpToRequireInstMultiMap)
666
+ &transferOpToRequireInstMultiMap,
667
+ SmallVectorImpl<Operand *> &transferredNonTransferrable)
666
668
: PartitionOpEvaluatorBaseImpl(workingPartition,
667
669
info->getOperandSetFactory ()),
668
670
info(info),
669
- transferOpToRequireInstMultiMap(transferOpToRequireInstMultiMap) {}
671
+ transferOpToRequireInstMultiMap(transferOpToRequireInstMultiMap),
672
+ transferredNonTransferrable(transferredNonTransferrable) {}
670
673
671
674
void handleFailure (const PartitionOp &partitionOp,
672
675
TrackableValueID transferredVal,
@@ -710,7 +713,8 @@ struct DiagnosticEvaluator final
710
713
<< " ID: %%" << transferredVal << " \n "
711
714
<< " Rep: "
712
715
<< *info->getValueMap ().getRepresentative (transferredVal));
713
- diagnose (partitionOp, diag::regionbasedisolation_selforargtransferred);
716
+ auto *self = const_cast <DiagnosticEvaluator *>(this );
717
+ self->transferredNonTransferrable .push_back (partitionOp.getSourceOp ());
714
718
}
715
719
716
720
bool isActorDerived (Element element) const {
@@ -727,17 +731,30 @@ struct DiagnosticEvaluator final
727
731
728
732
} // namespace
729
733
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 {
737
735
736
+ class TransferNonSendableImpl {
737
+ RegionAnalysisFunctionInfo *regionInfo;
738
738
SmallFrozenMultiMap<Operand *, SILInstruction *, 8 >
739
739
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
740
756
757
+ void TransferNonSendableImpl::runDiagnosticEvaluator () {
741
758
// Then for each block...
742
759
LLVM_DEBUG (llvm::dbgs () << " Walking blocks for diagnostics.\n " );
743
760
for (auto [block, blockState] : regionInfo->getRange ()) {
@@ -749,7 +766,8 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
749
766
// has callbacks that emit diagnsotics...
750
767
Partition workingPartition = blockState.getEntryPartition ();
751
768
DiagnosticEvaluator eval (workingPartition, regionInfo,
752
- transferOpToRequireInstMultiMap);
769
+ transferOpToRequireInstMultiMap,
770
+ transferredNonTransferrable);
753
771
754
772
// And then evaluate all of our partition ops on the entry partition.
755
773
for (auto &partitionOp : blockState.getPartitionOps ()) {
@@ -762,7 +780,10 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
762
780
763
781
// Now that we have found all of our transferInsts/Requires emit errors.
764
782
transferOpToRequireInstMultiMap.setFrozen ();
783
+ }
765
784
785
+ void TransferNonSendableImpl::emitUseAfterTransferDiagnostics () {
786
+ auto *function = regionInfo->getFunction ();
766
787
BasicBlockData<BlockLivenessInfo> blockLivenessInfo (function);
767
788
// We use a generation counter so we can lazily reset blockLivenessInfo
768
789
// since we cannot clear it without iterating over it.
@@ -872,6 +893,25 @@ static void emitDiagnostics(RegionAnalysisFunctionInfo *regionInfo) {
872
893
}
873
894
}
874
895
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
+
875
915
// ===----------------------------------------------------------------------===//
876
916
// MARK: Top Level Entrypoint
877
917
// ===----------------------------------------------------------------------===//
@@ -893,7 +933,8 @@ class TransferNonSendable : public SILFunctionTransform {
893
933
LLVM_DEBUG (llvm::dbgs ()
894
934
<< " ===> PROCESSING: " << function->getName () << ' \n ' );
895
935
896
- emitDiagnostics (functionInfo);
936
+ TransferNonSendableImpl impl (functionInfo);
937
+ impl.run ();
897
938
}
898
939
};
899
940
0 commit comments