@@ -641,6 +641,213 @@ class SendNonSendableImpl {
641
641
642
642
} // namespace
643
643
644
+ // ===----------------------------------------------------------------------===//
645
+ // MARK: Diagnostic Evaluator
646
+ // ===----------------------------------------------------------------------===//
647
+
648
+ namespace {
649
+
650
+ struct DiagnosticEvaluator final
651
+ : PartitionOpEvaluatorBaseImpl<DiagnosticEvaluator> {
652
+ RegionAnalysisFunctionInfo *info;
653
+ SmallFrozenMultiMap<Operand *, RequireInst, 8 >
654
+ &sendingOpToRequireInstMultiMap;
655
+
656
+ // / An error that we know how to emit verbatim without needing to preprocess.
657
+ // /
658
+ // / A contrasting case here is the use after send error where we need to pair
659
+ // / sending operands to require insts.
660
+ SmallVectorImpl<PartitionOpError> &foundVerbatimErrors;
661
+
662
+ DiagnosticEvaluator (Partition &workingPartition,
663
+ RegionAnalysisFunctionInfo *info,
664
+ SmallFrozenMultiMap<Operand *, RequireInst, 8 >
665
+ &sendingOpToRequireInstMultiMap,
666
+ SmallVectorImpl<PartitionOpError> &foundVerbatimErrors,
667
+ SendingOperandToStateMap &operandToStateMap)
668
+ : PartitionOpEvaluatorBaseImpl(
669
+ workingPartition, info->getOperandSetFactory (), operandToStateMap),
670
+ info(info),
671
+ sendingOpToRequireInstMultiMap(sendingOpToRequireInstMultiMap),
672
+ foundVerbatimErrors(foundVerbatimErrors) {}
673
+
674
+ void handleLocalUseAfterSend (LocalUseAfterSendError error) const {
675
+ const auto &partitionOp = *error.op ;
676
+ REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
677
+
678
+ // Ignore this if we are erroring on a mutable base of a Sendable value and
679
+ // if when we sent the value's region was not closure captured.
680
+ if (error.op ->getOptions ().containsOnly (
681
+ PartitionOp::Flag::RequireOfMutableBaseOfSendableValue) &&
682
+ !operandToStateMap.get (error.sendingOp ).isClosureCaptured )
683
+ return ;
684
+
685
+ sendingOpToRequireInstMultiMap.insert (
686
+ error.sendingOp , RequireInst::forUseAfterSend (partitionOp.getSourceInst ()));
687
+ }
688
+
689
+ void handleInOutSendingNotInitializedAtExitError (
690
+ InOutSendingNotInitializedAtExitError error) const {
691
+ const PartitionOp &partitionOp = *error.op ;
692
+ Operand *sendingOp = error.sendingOp ;
693
+
694
+ REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
695
+
696
+ sendingOpToRequireInstMultiMap.insert (
697
+ sendingOp, RequireInst::forInOutReinitializationNeeded (
698
+ partitionOp.getSourceInst ()));
699
+ }
700
+
701
+ void handleUnknownCodePattern (UnknownCodePatternError error) const {
702
+ const PartitionOp &op = *error.op ;
703
+
704
+ if (shouldAbortOnUnknownPatternMatchError ()) {
705
+ llvm::report_fatal_error (
706
+ " RegionIsolation: Aborting on unknown pattern match error" );
707
+ }
708
+
709
+ diagnoseError (op.getSourceInst (),
710
+ diag::regionbasedisolation_unknown_pattern);
711
+ }
712
+
713
+ void handleError (PartitionOpError error) {
714
+ switch (error.getKind ()) {
715
+ case PartitionOpError::LocalUseAfterSend: {
716
+ return handleLocalUseAfterSend (error.getLocalUseAfterSendError ());
717
+ }
718
+ case PartitionOpError::InOutSendingNotDisconnectedAtExit:
719
+ case PartitionOpError::InOutSendingReturned:
720
+ case PartitionOpError::SentNeverSendable:
721
+ case PartitionOpError::AssignNeverSendableIntoSendingResult:
722
+ case PartitionOpError::NonSendableIsolationCrossingResult:
723
+ // We are going to process these later... but dump so we can see that we
724
+ // handled an error here. The rest of the explicit handlers will dump as
725
+ // appropriate if they want to emit an error here (some will squelch the
726
+ // error).
727
+ REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
728
+ foundVerbatimErrors.emplace_back (error);
729
+ return ;
730
+ case PartitionOpError::InOutSendingNotInitializedAtExit: {
731
+ return handleInOutSendingNotInitializedAtExitError (
732
+ error.getInOutSendingNotInitializedAtExitError ());
733
+ }
734
+ case PartitionOpError::UnknownCodePattern: {
735
+ return handleUnknownCodePattern (error.getUnknownCodePatternError ());
736
+ }
737
+ }
738
+ llvm_unreachable (" Covered switch isn't covered?!" );
739
+ }
740
+
741
+ bool isActorDerived (Element element) const {
742
+ return info->getValueMap ().getIsolationRegion (element).isActorIsolated ();
743
+ }
744
+
745
+ // / If \p element's representative is an indirect out parameter, return
746
+ // / that parameter.
747
+ SILValue getIndirectOutParameter (Element element) const {
748
+ auto rep = info->getValueMap ().getRepresentativeValue (element);
749
+ if (!rep)
750
+ return {};
751
+ if (auto value = dyn_cast_or_null<SILFunctionArgument>(rep.maybeGetValue ());
752
+ value && value->getArgumentConvention ().isIndirectOutParameter ())
753
+ return value;
754
+ return {};
755
+ }
756
+
757
+ SILValue getInOutSendingParameter (Element elt) const {
758
+ auto rep = info->getValueMap ().getRepresentativeValue (elt);
759
+ if (!rep)
760
+ return {};
761
+ if (auto value = dyn_cast_or_null<SILFunctionArgument>(rep.maybeGetValue ());
762
+ value && value->getArgumentConvention ().isInoutConvention () &&
763
+ value->isSending ())
764
+ return value;
765
+ return {};
766
+ }
767
+
768
+ bool isTaskIsolatedDerived (Element element) const {
769
+ return info->getValueMap ().getIsolationRegion (element).isTaskIsolated ();
770
+ }
771
+
772
+ SILIsolationInfo::Kind hasSpecialDerivation (Element element) const {
773
+ return info->getValueMap ().getIsolationRegion (element).getKind ();
774
+ }
775
+
776
+ SILIsolationInfo getIsolationRegionInfo (Element element) const {
777
+ return info->getValueMap ().getIsolationRegion (element);
778
+ }
779
+
780
+ // / Only return an element if we are already tracking value and it is
781
+ // / non-Sendable.
782
+ // /
783
+ // / TODO: Can we return only
784
+ std::optional<Element> getElement (SILValue value) const {
785
+ auto trackableValue = info->getValueMap ().getTrackableValue (value);
786
+ if (trackableValue.value .isSendable ())
787
+ return {};
788
+ return trackableValue.value .getID ();
789
+ }
790
+
791
+ SILValue getRepresentative (SILValue value) const {
792
+ return info->getValueMap ()
793
+ .getTrackableValue (value)
794
+ .value .getRepresentative ()
795
+ .maybeGetValue ();
796
+ }
797
+
798
+ RepresentativeValue getRepresentativeValue (Element element) const {
799
+ return info->getValueMap ().getRepresentativeValue (element);
800
+ }
801
+
802
+ bool isClosureCaptured (Element element, Operand *op) const {
803
+ auto value = info->getValueMap ().maybeGetRepresentative (element);
804
+ if (!value)
805
+ return false ;
806
+ return info->isClosureCaptured (value, op);
807
+ }
808
+ };
809
+
810
+ } // namespace
811
+
812
+ void SendNonSendableImpl::runDiagnosticEvaluator () {
813
+ // Then for each block...
814
+ REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Walking blocks for diagnostics.\n " );
815
+ for (auto [block, blockState] : info->getRange ()) {
816
+ REGIONBASEDISOLATION_LOG (llvm::dbgs ()
817
+ << " |--> Block bb" << block.getDebugID () << " \n " );
818
+
819
+ if (!blockState.getLiveness ()) {
820
+ REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Dead block... skipping!\n " );
821
+ continue ;
822
+ }
823
+
824
+ REGIONBASEDISOLATION_LOG (
825
+ llvm::dbgs () << " Entry Partition: " ;
826
+ blockState.getEntryPartition ().print (llvm::dbgs ()));
827
+
828
+ // Grab its entry partition and setup an evaluator for the partition that
829
+ // has callbacks that emit diagnsotics...
830
+ Partition workingPartition = blockState.getEntryPartition ();
831
+ DiagnosticEvaluator eval (
832
+ workingPartition, info, sendingOpToRequireInstMultiMap,
833
+ foundVerbatimErrors, info->getSendingOperandToStateMap ());
834
+
835
+ // And then evaluate all of our partition ops on the entry partition.
836
+ for (auto &partitionOp : blockState.getPartitionOps ()) {
837
+ eval.apply (partitionOp);
838
+ }
839
+
840
+ REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Exit Partition: " ;
841
+ workingPartition.print (llvm::dbgs ()));
842
+ }
843
+
844
+ REGIONBASEDISOLATION_LOG (llvm::dbgs ()
845
+ << " Finished walking blocks for diagnostics.\n " );
846
+
847
+ // Now that we have found all of our sendingInsts/Requires emit errors.
848
+ sendingOpToRequireInstMultiMap.setFrozen ();
849
+ }
850
+
644
851
// ===----------------------------------------------------------------------===//
645
852
// MARK: UseAfterSend Diagnostic Inference
646
853
// ===----------------------------------------------------------------------===//
@@ -2643,182 +2850,6 @@ void NonSendableIsolationCrossingResultDiagnosticEmitter::emit() {
2643
2850
}
2644
2851
}
2645
2852
2646
- // ===----------------------------------------------------------------------===//
2647
- // MARK: Diagnostic Evaluator
2648
- // ===----------------------------------------------------------------------===//
2649
-
2650
- namespace {
2651
-
2652
- struct DiagnosticEvaluator final
2653
- : PartitionOpEvaluatorBaseImpl<DiagnosticEvaluator> {
2654
- RegionAnalysisFunctionInfo *info;
2655
- SmallFrozenMultiMap<Operand *, RequireInst, 8 >
2656
- &sendingOpToRequireInstMultiMap;
2657
-
2658
- // / An error that we know how to emit verbatim without needing to preprocess.
2659
- // /
2660
- // / A contrasting case here is the use after send error where we need to pair
2661
- // / sending operands to require insts.
2662
- SmallVectorImpl<PartitionOpError> &foundVerbatimErrors;
2663
-
2664
- DiagnosticEvaluator (Partition &workingPartition,
2665
- RegionAnalysisFunctionInfo *info,
2666
- SmallFrozenMultiMap<Operand *, RequireInst, 8 >
2667
- &sendingOpToRequireInstMultiMap,
2668
- SmallVectorImpl<PartitionOpError> &foundVerbatimErrors,
2669
- SendingOperandToStateMap &operandToStateMap)
2670
- : PartitionOpEvaluatorBaseImpl(
2671
- workingPartition, info->getOperandSetFactory (), operandToStateMap),
2672
- info(info),
2673
- sendingOpToRequireInstMultiMap(sendingOpToRequireInstMultiMap),
2674
- foundVerbatimErrors(foundVerbatimErrors) {}
2675
-
2676
- void handleLocalUseAfterSend (LocalUseAfterSendError error) const {
2677
- const auto &partitionOp = *error.op ;
2678
- REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
2679
-
2680
- // Ignore this if we are erroring on a mutable base of a Sendable value and
2681
- // if when we sent the value's region was not closure captured.
2682
- if (error.op ->getOptions ().containsOnly (
2683
- PartitionOp::Flag::RequireOfMutableBaseOfSendableValue) &&
2684
- !operandToStateMap.get (error.sendingOp ).isClosureCaptured )
2685
- return ;
2686
-
2687
- sendingOpToRequireInstMultiMap.insert (
2688
- error.sendingOp , RequireInst::forUseAfterSend (partitionOp.getSourceInst ()));
2689
- }
2690
-
2691
- void handleInOutSendingNotInitializedAtExitError (
2692
- InOutSendingNotInitializedAtExitError error) const {
2693
- const PartitionOp &partitionOp = *error.op ;
2694
- Operand *sendingOp = error.sendingOp ;
2695
-
2696
- REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
2697
-
2698
- sendingOpToRequireInstMultiMap.insert (
2699
- sendingOp, RequireInst::forInOutReinitializationNeeded (
2700
- partitionOp.getSourceInst ()));
2701
- }
2702
-
2703
- void handleUnknownCodePattern (UnknownCodePatternError error) const {
2704
- const PartitionOp &op = *error.op ;
2705
-
2706
- if (shouldAbortOnUnknownPatternMatchError ()) {
2707
- llvm::report_fatal_error (
2708
- " RegionIsolation: Aborting on unknown pattern match error" );
2709
- }
2710
-
2711
- diagnoseError (op.getSourceInst (),
2712
- diag::regionbasedisolation_unknown_pattern);
2713
- }
2714
-
2715
- void handleError (PartitionOpError error) {
2716
- switch (error.getKind ()) {
2717
- case PartitionOpError::LocalUseAfterSend: {
2718
- return handleLocalUseAfterSend (error.getLocalUseAfterSendError ());
2719
- }
2720
- case PartitionOpError::InOutSendingNotDisconnectedAtExit:
2721
- case PartitionOpError::SentNeverSendable:
2722
- case PartitionOpError::AssignNeverSendableIntoSendingResult:
2723
- case PartitionOpError::NonSendableIsolationCrossingResult:
2724
- // We are going to process these later... but dump so we can see that we
2725
- // handled an error here. The rest of the explicit handlers will dump as
2726
- // appropriate if they want to emit an error here (some will squelch the
2727
- // error).
2728
- REGIONBASEDISOLATION_LOG (error.print (llvm::dbgs (), info->getValueMap ()));
2729
- foundVerbatimErrors.emplace_back (error);
2730
- return ;
2731
- case PartitionOpError::InOutSendingNotInitializedAtExit: {
2732
- return handleInOutSendingNotInitializedAtExitError (
2733
- error.getInOutSendingNotInitializedAtExitError ());
2734
- }
2735
- case PartitionOpError::UnknownCodePattern: {
2736
- return handleUnknownCodePattern (error.getUnknownCodePatternError ());
2737
- }
2738
- }
2739
- llvm_unreachable (" Covered switch isn't covered?!" );
2740
- }
2741
-
2742
- bool isActorDerived (Element element) const {
2743
- return info->getValueMap ().getIsolationRegion (element).isActorIsolated ();
2744
- }
2745
-
2746
- bool isTaskIsolatedDerived (Element element) const {
2747
- return info->getValueMap ().getIsolationRegion (element).isTaskIsolated ();
2748
- }
2749
-
2750
- SILIsolationInfo::Kind hasSpecialDerivation (Element element) const {
2751
- return info->getValueMap ().getIsolationRegion (element).getKind ();
2752
- }
2753
-
2754
- SILIsolationInfo getIsolationRegionInfo (Element element) const {
2755
- return info->getValueMap ().getIsolationRegion (element);
2756
- }
2757
-
2758
- std::optional<Element> getElement (SILValue value) const {
2759
- return info->getValueMap ().getTrackableValue (value).value .getID ();
2760
- }
2761
-
2762
- SILValue getRepresentative (SILValue value) const {
2763
- return info->getValueMap ()
2764
- .getTrackableValue (value)
2765
- .value .getRepresentative ()
2766
- .maybeGetValue ();
2767
- }
2768
-
2769
- RepresentativeValue getRepresentativeValue (Element element) const {
2770
- return info->getValueMap ().getRepresentativeValue (element);
2771
- }
2772
-
2773
- bool isClosureCaptured (Element element, Operand *op) const {
2774
- auto value = info->getValueMap ().maybeGetRepresentative (element);
2775
- if (!value)
2776
- return false ;
2777
- return info->isClosureCaptured (value, op);
2778
- }
2779
- };
2780
-
2781
- } // namespace
2782
-
2783
- void SendNonSendableImpl::runDiagnosticEvaluator () {
2784
- // Then for each block...
2785
- REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Walking blocks for diagnostics.\n " );
2786
- for (auto [block, blockState] : info->getRange ()) {
2787
- REGIONBASEDISOLATION_LOG (llvm::dbgs ()
2788
- << " |--> Block bb" << block.getDebugID () << " \n " );
2789
-
2790
- if (!blockState.getLiveness ()) {
2791
- REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Dead block... skipping!\n " );
2792
- continue ;
2793
- }
2794
-
2795
- REGIONBASEDISOLATION_LOG (
2796
- llvm::dbgs () << " Entry Partition: " ;
2797
- blockState.getEntryPartition ().print (llvm::dbgs ()));
2798
-
2799
- // Grab its entry partition and setup an evaluator for the partition that
2800
- // has callbacks that emit diagnsotics...
2801
- Partition workingPartition = blockState.getEntryPartition ();
2802
- DiagnosticEvaluator eval (
2803
- workingPartition, info, sendingOpToRequireInstMultiMap,
2804
- foundVerbatimErrors, info->getSendingOperandToStateMap ());
2805
-
2806
- // And then evaluate all of our partition ops on the entry partition.
2807
- for (auto &partitionOp : blockState.getPartitionOps ()) {
2808
- eval.apply (partitionOp);
2809
- }
2810
-
2811
- REGIONBASEDISOLATION_LOG (llvm::dbgs () << " Exit Partition: " ;
2812
- workingPartition.print (llvm::dbgs ()));
2813
- }
2814
-
2815
- REGIONBASEDISOLATION_LOG (llvm::dbgs ()
2816
- << " Finished walking blocks for diagnostics.\n " );
2817
-
2818
- // Now that we have found all of our sendingInsts/Requires emit errors.
2819
- sendingOpToRequireInstMultiMap.setFrozen ();
2820
- }
2821
-
2822
2853
// ===----------------------------------------------------------------------===//
2823
2854
// MARK: Top Level Entrypoint
2824
2855
// ===----------------------------------------------------------------------===//
0 commit comments