Skip to content

Commit 9f8b989

Browse files
committed
[rbi] Hoist diagnostic evaluator earlier in the file to make review easier.
I am going to use this in the next commit. So it makes sense to hoist it as a separate commit to make it easy to just look through the diff.
1 parent 31f344d commit 9f8b989

File tree

1 file changed

+207
-176
lines changed

1 file changed

+207
-176
lines changed

lib/SILOptimizer/Mandatory/SendNonSendable.cpp

Lines changed: 207 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)