@@ -641,6 +641,213 @@ class SendNonSendableImpl {
641641
642642} // namespace
643643
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+
644851// ===----------------------------------------------------------------------===//
645852// MARK: UseAfterSend Diagnostic Inference
646853// ===----------------------------------------------------------------------===//
@@ -2643,182 +2850,6 @@ void NonSendableIsolationCrossingResultDiagnosticEmitter::emit() {
26432850 }
26442851}
26452852
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-
28222853// ===----------------------------------------------------------------------===//
28232854// MARK: Top Level Entrypoint
28242855// ===----------------------------------------------------------------------===//
0 commit comments