@@ -47,6 +47,12 @@ using namespace swift::PartitionPrimitives;
47
47
using namespace swift ::PatternMatch;
48
48
using namespace swift ::regionanalysisimpl;
49
49
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
+
50
56
// ===----------------------------------------------------------------------===//
51
57
// MARK: Utilities
52
58
// ===----------------------------------------------------------------------===//
@@ -1191,6 +1197,10 @@ struct PartitionOpBuilder {
1191
1197
}
1192
1198
1193
1199
void addUnknownPatternError (SILValue value) {
1200
+ if (AbortOnUnknownPatternMatchError) {
1201
+ llvm::report_fatal_error (
1202
+ " RegionIsolation: Aborting on unknown pattern match error" );
1203
+ }
1194
1204
currentInstPartitionOps.emplace_back (
1195
1205
PartitionOp::UnknownPatternError (lookupValueID (value), currentInst));
1196
1206
}
@@ -1510,12 +1520,12 @@ class PartitionOpTranslator {
1510
1520
std::optional<std::pair<TrackableValue, bool >>
1511
1521
initializeTrackedValue (SILValue value, SILIsolationInfo info) const {
1512
1522
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 ;
1519
1529
}
1520
1530
1521
1531
TrackableValue
@@ -1564,27 +1574,52 @@ class PartitionOpTranslator {
1564
1574
// / Require all non-sendable sources, merge their regions, and assign the
1565
1575
// / resulting region to all non-sendable targets, or assign non-sendable
1566
1576
// / 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.
1567
1583
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 = {}) {
1571
1588
SmallVector<SILValue, 8 > assignOperands;
1572
1589
SmallVector<SILValue, 8 > assignResults;
1573
1590
1591
+ std::optional<SILDynamicMergedIsolationInfo> mergedInfo;
1592
+ if (resultIsolationInfoOverride) {
1593
+ mergedInfo = resultIsolationInfoOverride;
1594
+ } else {
1595
+ mergedInfo = SILIsolationInfo::getDisconnected (false );
1596
+ }
1597
+
1574
1598
for (SILValue src : sourceValues) {
1575
1599
if (auto value = tryToTrackValue (src)) {
1576
1600
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
+ }
1577
1610
}
1578
1611
}
1579
1612
1580
1613
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) {
1582
1617
// We only get back result if it is non-Sendable.
1583
1618
if (auto nonSendableValue =
1584
- initializeTrackedValue (result, isolationInfo)) {
1619
+ initializeTrackedValue (result, resultIsolationInfoOverride)) {
1620
+ // If we did not insert, emit an unknown patten error.
1585
1621
if (!nonSendableValue->second ) {
1586
1622
builder.addUnknownPatternError (result);
1587
- continue ;
1588
1623
}
1589
1624
assignResults.push_back (
1590
1625
nonSendableValue->first .getRepresentative ().getValue ());
@@ -1611,8 +1646,13 @@ class PartitionOpTranslator {
1611
1646
// non-Sendable operands and we are supposed to mark value as actor
1612
1647
// derived, introduce a fake element so we just propagate the actor
1613
1648
// 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);
1616
1656
}
1617
1657
1618
1658
return ;
@@ -1818,8 +1858,7 @@ class PartitionOpTranslator {
1818
1858
1819
1859
// If we do not have a special builtin, just do a multi-assign. Builtins do
1820
1860
// not cross async boundaries.
1821
- return translateSILMultiAssign (bi->getResults (), bi->getOperandValues (),
1822
- {});
1861
+ return translateSILMultiAssign (bi->getResults (), bi->getOperandValues ());
1823
1862
}
1824
1863
1825
1864
void translateNonIsolationCrossingSILApply (FullApplySite fas) {
@@ -1864,11 +1903,16 @@ class PartitionOpTranslator {
1864
1903
}
1865
1904
}
1866
1905
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
+ }
1872
1916
1873
1917
SmallVector<SILValue, 8 > applyResults;
1874
1918
getApplyResults (*fas, applyResults);
@@ -2769,18 +2813,14 @@ PartitionOpTranslator::visitAllocStackInst(AllocStackInst *asi) {
2769
2813
2770
2814
// Ok at this point we know that our value is a non-Sendable temporary.
2771
2815
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 ()) {
2777
2817
return TranslationSemantics::AssignFresh;
2778
2818
}
2779
2819
2780
2820
// Ok, we can handle this and have a valid isolation. Initialize the value.
2781
2821
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! " ) ;
2784
2824
2785
2825
// If we already had a value for this alloc_stack (which we shouldn't
2786
2826
// ever)... emit an unknown pattern error.
@@ -2789,7 +2829,9 @@ PartitionOpTranslator::visitAllocStackInst(AllocStackInst *asi) {
2789
2829
return TranslationSemantics::Special;
2790
2830
}
2791
2831
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 ());
2793
2835
return TranslationSemantics::Special;
2794
2836
}
2795
2837
0 commit comments