@@ -57,8 +57,10 @@ using namespace swift::regionanalysisimpl;
57
57
static bool isIsolationBoundaryCrossingApply (SILInstruction *inst) {
58
58
if (ApplyExpr *apply = inst->getLoc ().getAsASTNode <ApplyExpr>())
59
59
return apply->getIsolationCrossing ().has_value ();
60
- if (auto fas = FullApplySite::isa (inst))
61
- return bool (fas.getIsolationCrossing ());
60
+ if (auto fas = FullApplySite::isa (inst)) {
61
+ if (bool (fas.getIsolationCrossing ()))
62
+ return true ;
63
+ }
62
64
63
65
// We assume that any instruction that does not correspond to an ApplyExpr
64
66
// cannot cross an isolation domain.
@@ -249,8 +251,6 @@ static SILValue getUnderlyingTrackedValue(SILValue value) {
249
251
UseDefChainVisitor visitor;
250
252
SILValue base = visitor.visitAll (value);
251
253
assert (base);
252
- if (isa<GlobalAddrInst>(base))
253
- return value;
254
254
if (base->getType ().isObject ())
255
255
return getUnderlyingObject (base);
256
256
return base;
@@ -400,6 +400,38 @@ static bool isGlobalActorInit(SILFunction *fn) {
400
400
return globalDecl->getGlobalActorAttr () != std::nullopt;
401
401
}
402
402
403
+ // / Returns true if this is a function argument that is able to be transferred
404
+ // / in the body of our function.
405
+ static bool isTransferrableFunctionArgument (SILFunctionArgument *arg) {
406
+ // Indirect out parameters cannot be an input transferring parameter.
407
+ if (arg->getArgumentConvention ().isIndirectOutParameter ())
408
+ return false ;
409
+
410
+ // If we have a function argument that is closure captured by a Sendable
411
+ // closure, allow for the argument to be transferred.
412
+ //
413
+ // DISCUSSION: The reason that we do this is that in the case of us
414
+ // having an actual Sendable closure there are two cases we can see:
415
+ //
416
+ // 1. If we have an actual Sendable closure, the AST will emit an
417
+ // earlier error saying that we are capturing a non-Sendable value in a
418
+ // Sendable closure. So we want to squelch the error that we would emit
419
+ // otherwise. This only occurs when we are not in swift-6 mode since in
420
+ // swift-6 mode we will error on the earlier error... but in the case of
421
+ // us not being in swift 6 mode lets not emit extra errors.
422
+ //
423
+ // 2. If we have an async-let based Sendable closure, we want to allow
424
+ // for the argument to be transferred in the async let's statement and
425
+ // not emit an error.
426
+ if (arg->isClosureCapture () &&
427
+ arg->getFunction ()->getLoweredFunctionType ()->isSendable ())
428
+ return true ;
429
+
430
+ // Otherwise, we only allow for the argument to be transferred if it is
431
+ // explicitly marked as a strong transferring parameter.
432
+ return arg->isTransferring ();
433
+ }
434
+
403
435
// ===----------------------------------------------------------------------===//
404
436
// MARK: Partial Apply Reachability
405
437
// ===----------------------------------------------------------------------===//
@@ -1160,31 +1192,22 @@ class PartitionOpTranslator {
1160
1192
llvm::SmallVector<Element, 8 > nonSendableSeparateIndices;
1161
1193
for (SILArgument *arg : functionArguments) {
1162
1194
if (auto state = tryToTrackValue (arg)) {
1163
- LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID () << " : " );
1195
+ LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID () << " : " << *arg );
1164
1196
1165
- // If we have a function argument that is closure captured by a Sendable
1166
- // closure, allow for the argument to be transferred.
1167
- //
1168
- // DISCUSSION: The reason that we do this is that in the case of us
1169
- // having an actual Sendable closure there are two cases we can see:
1197
+ // If we can transfer our parameter, just add it to
1198
+ // nonSendableSeparateIndices.
1170
1199
//
1171
- // 1. If we have an actual Sendable closure, the AST will emit an
1172
- // earlier error saying that we are capturing a non-Sendable value in a
1173
- // Sendable closure. So we want to squelch the error that we would emit
1174
- // otherwise. This only occurs when we are not in swift-6 mode since in
1175
- // swift-6 mode we will error on the earlier error... but in the case of
1176
- // us not being in swift 6 mode lets not emit extra errors.
1177
- //
1178
- // 2. If we have an async-let based Sendable closure, we want to allow
1179
- // for the value to be transferred and not emit an error.
1180
- if (!cast<SILFunctionArgument>(arg)->isClosureCapture () ||
1181
- !function->getLoweredFunctionType ()->isSendable ()) {
1182
- addNeverTransferredValueID (state->getID ());
1183
- nonSendableJoinedIndices.push_back (state->getID ());
1184
- } else {
1200
+ // NOTE: We do not support today the ability to have multiple parameters
1201
+ // transfer together as part of the same region.
1202
+ if (isTransferrableFunctionArgument (cast<SILFunctionArgument>(arg))) {
1185
1203
nonSendableSeparateIndices.push_back (state->getID ());
1204
+ continue ;
1186
1205
}
1187
- LLVM_DEBUG (llvm::dbgs () << *arg);
1206
+
1207
+ // Otherwise, it is one of our merged parameters. Add it to the never
1208
+ // transfer list and to the region join list.
1209
+ valueMap.addNeverTransferredValueID (state->getID ());
1210
+ nonSendableJoinedIndices.push_back (state->getID ());
1188
1211
}
1189
1212
}
1190
1213
@@ -1464,43 +1487,89 @@ class PartitionOpTranslator {
1464
1487
translateSILMultiAssign (applyResults, pai->getOperandValues (), options);
1465
1488
}
1466
1489
1467
- void translateSILApply (SILInstruction *inst) {
1468
- if (auto *bi = dyn_cast<BuiltinInst>(inst)) {
1469
- if (auto kind = bi->getBuiltinKind ()) {
1470
- if (kind == BuiltinValueKind::StartAsyncLetWithLocalBuffer) {
1471
- return translateAsyncLetStart (bi);
1472
- }
1490
+ void translateSILBuiltin (BuiltinInst *bi) {
1491
+ if (auto kind = bi->getBuiltinKind ()) {
1492
+ if (kind == BuiltinValueKind::StartAsyncLetWithLocalBuffer) {
1493
+ return translateAsyncLetStart (bi);
1473
1494
}
1474
1495
}
1475
1496
1476
- if (auto fas = FullApplySite::isa (inst)) {
1477
- if (auto *f = fas.getCalleeFunction ()) {
1478
- // Check against the actual SILFunction.
1479
- if (f->getName () == " swift_asyncLet_get" ) {
1480
- return translateAsyncLetGet (cast<ApplyInst>(*fas));
1481
- }
1497
+ // If we do not have a special builtin, just do a multi-assign. Builtins do
1498
+ // not cross async boundaries.
1499
+ return translateSILMultiAssign (bi->getResults (), bi->getOperandValues (),
1500
+ {});
1501
+ }
1502
+
1503
+ void translateNonIsolationCrossingSILApply (FullApplySite fas) {
1504
+ SILMultiAssignOptions options;
1505
+ if (fas.hasSelfArgument ()) {
1506
+ if (auto self = fas.getSelfArgument ()) {
1507
+ if (self->getType ().isActor ())
1508
+ options |= SILMultiAssignFlags::PropagatesActorSelf;
1482
1509
}
1483
1510
}
1484
1511
1485
- // If this apply does not cross isolation domains, it has normal
1486
- // non-transferring multi-assignment semantics
1487
- if (!isIsolationBoundaryCrossingApply (inst)) {
1488
- SILMultiAssignOptions options;
1489
- if (auto fas = FullApplySite::isa (inst)) {
1490
- if (fas.hasSelfArgument ()) {
1491
- if (auto self = fas.getSelfArgument ()) {
1492
- if (self->getType ().isActor ())
1493
- options |= SILMultiAssignFlags::PropagatesActorSelf;
1512
+ // For non-self parameters, gather all of the transferring parameters and
1513
+ // gather our non-transferring parameters.
1514
+ SmallVector<SILValue, 8 > nonTransferringParameters;
1515
+ if (fas.getNumArguments ()) {
1516
+ // NOTE: We want to process indirect parameters as if they are
1517
+ // parameters... so we process them in nonTransferringParameters.
1518
+ for (auto &op : fas.getOperandsWithoutSelf ()) {
1519
+ if (!fas.getArgumentConvention (op).isIndirectOutParameter () &&
1520
+ fas.getArgumentParameterInfo (op).hasOption (
1521
+ SILParameterInfo::Transferring)) {
1522
+ if (auto value = tryToTrackValue (op.get ())) {
1523
+ builder.addTransfer (value->getRepresentative ().getValue (), &op);
1494
1524
}
1525
+ } else {
1526
+ nonTransferringParameters.push_back (op.get ());
1495
1527
}
1496
1528
}
1529
+ }
1530
+
1531
+ // If our self parameter was transferring, transfer it. Otherwise, just
1532
+ // stick it in the non seld operand values array and run multiassign on
1533
+ // it.
1534
+ if (fas.hasSelfArgument ()) {
1535
+ auto &selfOperand = fas.getSelfArgumentOperand ();
1536
+ if (fas.getArgumentParameterInfo (selfOperand)
1537
+ .hasOption (SILParameterInfo::Transferring)) {
1538
+ if (auto value = tryToTrackValue (selfOperand.get ())) {
1539
+ builder.addTransfer (value->getRepresentative ().getValue (),
1540
+ &selfOperand);
1541
+ }
1542
+ } else {
1543
+ nonTransferringParameters.push_back (selfOperand.get ());
1544
+ }
1545
+ }
1546
+
1547
+ SmallVector<SILValue, 8 > applyResults;
1548
+ getApplyResults (*fas, applyResults);
1549
+ return translateSILMultiAssign (applyResults, nonTransferringParameters,
1550
+ options);
1551
+ }
1497
1552
1498
- SmallVector<SILValue, 8 > applyResults;
1499
- getApplyResults (inst, applyResults);
1500
- return translateSILMultiAssign (applyResults, inst->getOperandValues (),
1501
- options);
1553
+ void translateSILApply (SILInstruction *inst) {
1554
+ if (auto *bi = dyn_cast<BuiltinInst>(inst)) {
1555
+ return translateSILBuiltin (bi);
1502
1556
}
1503
1557
1558
+ auto fas = FullApplySite::isa (inst);
1559
+ assert (bool (fas) && " Builtins should be handled above" );
1560
+
1561
+ if (auto *f = fas.getCalleeFunction ()) {
1562
+ // Check against the actual SILFunction.
1563
+ if (f->getName () == " swift_asyncLet_get" ) {
1564
+ return translateAsyncLetGet (cast<ApplyInst>(*fas));
1565
+ }
1566
+ }
1567
+
1568
+ // If this apply does not cross isolation domains, it has normal
1569
+ // non-transferring multi-assignment semantics
1570
+ if (!isIsolationBoundaryCrossingApply (inst))
1571
+ return translateNonIsolationCrossingSILApply (fas);
1572
+
1504
1573
if (auto cast = dyn_cast<ApplyInst>(inst))
1505
1574
return translateIsolationCrossingSILApply (cast);
1506
1575
if (auto cast = dyn_cast<BeginApplyInst>(inst))
@@ -1521,7 +1590,7 @@ class PartitionOpTranslator {
1521
1590
" only ApplyExpr's should cross isolation domains" );
1522
1591
1523
1592
// require all operands
1524
- for (auto op : applySite-> getOperandValues ())
1593
+ for (auto op : applySite. getArguments ())
1525
1594
if (auto value = tryToTrackValue (op))
1526
1595
builder.addRequire (value->getRepresentative ().getValue ());
1527
1596
0 commit comments