@@ -47,6 +47,12 @@ using namespace swift::PartitionPrimitives;
4747using namespace swift ::PatternMatch;
4848using namespace swift ::regionanalysisimpl;
4949
50+ static llvm::cl::opt<bool > AbortOnUnknownPatternMatchError (
51+ " sil-region-isolation-assert-on-unknown-pattern" ,
52+ llvm::cl::desc (" Abort if SIL region isolation detects an unknown pattern. "
53+ " Intended only to be used when debugging the compiler!" ),
54+ llvm::cl::init(false ), llvm::cl::Hidden);
55+
5056// ===----------------------------------------------------------------------===//
5157// MARK: Utilities
5258// ===----------------------------------------------------------------------===//
@@ -1191,6 +1197,10 @@ struct PartitionOpBuilder {
11911197 }
11921198
11931199 void addUnknownPatternError (SILValue value) {
1200+ if (AbortOnUnknownPatternMatchError) {
1201+ llvm::report_fatal_error (
1202+ " RegionIsolation: Aborting on unknown pattern match error" );
1203+ }
11941204 currentInstPartitionOps.emplace_back (
11951205 PartitionOp::UnknownPatternError (lookupValueID (value), currentInst));
11961206 }
@@ -1510,12 +1520,12 @@ class PartitionOpTranslator {
15101520 std::optional<std::pair<TrackableValue, bool >>
15111521 initializeTrackedValue (SILValue value, SILIsolationInfo info) const {
15121522 auto trackedValuePair = valueMap.initializeTrackableValue (value, info);
1513- if (trackedValuePair. first . isNonSendable ()) {
1514- assert (trackedValuePair. second );
1515- return trackedValuePair;
1516- }
1517- assert (trackedValuePair. second );
1518- return {} ;
1523+
1524+ // If we have a Sendable value return none.
1525+ if (! trackedValuePair. first . isNonSendable ())
1526+ return {};
1527+
1528+ return trackedValuePair ;
15191529 }
15201530
15211531 TrackableValue
@@ -1564,27 +1574,52 @@ class PartitionOpTranslator {
15641574 // / Require all non-sendable sources, merge their regions, and assign the
15651575 // / resulting region to all non-sendable targets, or assign non-sendable
15661576 // / targets to a fresh region if there are no non-sendable sources.
1577+ // /
1578+ // / \arg isolationInfo An isolation info that can be specified as the true
1579+ // / base isolation of results. Otherwise, results are assumed to have a
1580+ // / element isolation of disconnected. NOTE: The results will still be in the
1581+ // / region of the non-Sendable arguments so at the region level they will have
1582+ // / the same value.
15671583 template <typename TargetRange, typename SourceRange>
1568- void translateSILMultiAssign (const TargetRange &resultValues,
1569- const SourceRange &sourceValues,
1570- SILIsolationInfo isolationInfo = {}) {
1584+ void
1585+ translateSILMultiAssign (const TargetRange &resultValues,
1586+ const SourceRange &sourceValues,
1587+ SILIsolationInfo resultIsolationInfoOverride = {}) {
15711588 SmallVector<SILValue, 8 > assignOperands;
15721589 SmallVector<SILValue, 8 > assignResults;
15731590
1591+ std::optional<SILDynamicMergedIsolationInfo> mergedInfo;
1592+ if (resultIsolationInfoOverride) {
1593+ mergedInfo = resultIsolationInfoOverride;
1594+ } else {
1595+ mergedInfo = SILIsolationInfo::getDisconnected (false );
1596+ }
1597+
15741598 for (SILValue src : sourceValues) {
15751599 if (auto value = tryToTrackValue (src)) {
15761600 assignOperands.push_back (value->getRepresentative ().getValue ());
1601+ mergedInfo = mergedInfo->merge (value->getIsolationRegionInfo ());
1602+
1603+ // If we fail to merge, then we have an incompatibility in between some
1604+ // of our arguments (consider isolated to different actors) or with the
1605+ // isolationInfo we specified. Emit an unknown patten error.
1606+ if (!mergedInfo) {
1607+ builder.addUnknownPatternError (src);
1608+ continue ;
1609+ }
15771610 }
15781611 }
15791612
15801613 for (SILValue result : resultValues) {
1581- if (isolationInfo) {
1614+ // If we had isolation info explicitly passed in... use our
1615+ // mergedInfo. Otherwise, we want to infer.
1616+ if (resultIsolationInfoOverride) {
15821617 // We only get back result if it is non-Sendable.
15831618 if (auto nonSendableValue =
1584- initializeTrackedValue (result, isolationInfo)) {
1619+ initializeTrackedValue (result, resultIsolationInfoOverride)) {
1620+ // If we did not insert, emit an unknown patten error.
15851621 if (!nonSendableValue->second ) {
15861622 builder.addUnknownPatternError (result);
1587- continue ;
15881623 }
15891624 assignResults.push_back (
15901625 nonSendableValue->first .getRepresentative ().getValue ());
@@ -1611,8 +1646,13 @@ class PartitionOpTranslator {
16111646 // non-Sendable operands and we are supposed to mark value as actor
16121647 // derived, introduce a fake element so we just propagate the actor
16131648 // region.
1614- if (assignOperands.size () && isolationInfo) {
1615- builder.addActorIntroducingInst (assignOperands.back (), isolationInfo);
1649+ //
1650+ // NOTE: Here we check if we have mergedInfo rather than isolationInfo
1651+ // since we want to do this regardless of whether or not we passed in a
1652+ // specific isolation info unlike earlier when processing actual results.
1653+ if (assignOperands.size () && resultIsolationInfoOverride) {
1654+ builder.addActorIntroducingInst (assignOperands.back (),
1655+ resultIsolationInfoOverride);
16161656 }
16171657
16181658 return ;
@@ -1818,8 +1858,7 @@ class PartitionOpTranslator {
18181858
18191859 // If we do not have a special builtin, just do a multi-assign. Builtins do
18201860 // not cross async boundaries.
1821- return translateSILMultiAssign (bi->getResults (), bi->getOperandValues (),
1822- {});
1861+ return translateSILMultiAssign (bi->getResults (), bi->getOperandValues ());
18231862 }
18241863
18251864 void translateNonIsolationCrossingSILApply (FullApplySite fas) {
@@ -1864,11 +1903,16 @@ class PartitionOpTranslator {
18641903 }
18651904 }
18661905
1867- // Add our callee to non-transferring parameters. This ensures that if it is
1868- // actor isolated, that propagates into our results. This is especially
1869- // important since our callee could be dynamically isolated and we cannot
1870- // know that until we perform dataflow.
1871- nonTransferringParameters.push_back (fas.getCallee ());
1906+ // Require our callee operand if it is non-Sendable.
1907+ //
1908+ // DISCUSSION: Even though we do not include our callee operand in the same
1909+ // region as our operands/results, we still need to require that it is live
1910+ // at the point of application. Otherwise, we will not emit errors if the
1911+ // closure before this function application is already in the same region as
1912+ // a transferred value. In such a case, the function application must error.
1913+ if (auto value = tryToTrackValue (fas.getCallee ())) {
1914+ builder.addRequire (value->getRepresentative ().getValue ());
1915+ }
18721916
18731917 SmallVector<SILValue, 8 > applyResults;
18741918 getApplyResults (*fas, applyResults);
@@ -2769,18 +2813,14 @@ PartitionOpTranslator::visitAllocStackInst(AllocStackInst *asi) {
27692813
27702814 // Ok at this point we know that our value is a non-Sendable temporary.
27712815 auto isolationInfo = SILIsolationInfo::get (asi);
2772- if (!bool (isolationInfo)) {
2773- return TranslationSemantics::AssignFresh;
2774- }
2775-
2776- if (isolationInfo.isDisconnected ()) {
2816+ if (!bool (isolationInfo) || isolationInfo.isDisconnected ()) {
27772817 return TranslationSemantics::AssignFresh;
27782818 }
27792819
27802820 // Ok, we can handle this and have a valid isolation. Initialize the value.
27812821 auto v = initializeTrackedValue (asi, isolationInfo);
2782- if (!v)
2783- return TranslationSemantics::AssignFresh ;
2822+ assert (v && " Only return none if we have a sendable value, but we checked "
2823+ " that earlier! " ) ;
27842824
27852825 // If we already had a value for this alloc_stack (which we shouldn't
27862826 // ever)... emit an unknown pattern error.
@@ -2789,7 +2829,9 @@ PartitionOpTranslator::visitAllocStackInst(AllocStackInst *asi) {
27892829 return TranslationSemantics::Special;
27902830 }
27912831
2792- translateSILAssignFresh (v->first .getRepresentative ().getValue ());
2832+ // NOTE: To prevent an additional reinitialization by the canned AssignFresh
2833+ // code, we do our own assign fresh and return special.
2834+ builder.addAssignFresh (v->first .getRepresentative ().getValue ());
27932835 return TranslationSemantics::Special;
27942836}
27952837
0 commit comments