@@ -57,8 +57,10 @@ using namespace swift::regionanalysisimpl;
5757static bool isIsolationBoundaryCrossingApply (SILInstruction *inst) {
5858 if (ApplyExpr *apply = inst->getLoc ().getAsASTNode <ApplyExpr>())
5959 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+ }
6264
6365 // We assume that any instruction that does not correspond to an ApplyExpr
6466 // cannot cross an isolation domain.
@@ -249,8 +251,6 @@ static SILValue getUnderlyingTrackedValue(SILValue value) {
249251 UseDefChainVisitor visitor;
250252 SILValue base = visitor.visitAll (value);
251253 assert (base);
252- if (isa<GlobalAddrInst>(base))
253- return value;
254254 if (base->getType ().isObject ())
255255 return getUnderlyingObject (base);
256256 return base;
@@ -400,6 +400,38 @@ static bool isGlobalActorInit(SILFunction *fn) {
400400 return globalDecl->getGlobalActorAttr () != std::nullopt ;
401401}
402402
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+
403435// ===----------------------------------------------------------------------===//
404436// MARK: Partial Apply Reachability
405437// ===----------------------------------------------------------------------===//
@@ -1160,31 +1192,22 @@ class PartitionOpTranslator {
11601192 llvm::SmallVector<Element, 8 > nonSendableSeparateIndices;
11611193 for (SILArgument *arg : functionArguments) {
11621194 if (auto state = tryToTrackValue (arg)) {
1163- LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID () << " : " );
1195+ LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID () << " : " << *arg );
11641196
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.
11701199 //
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))) {
11851203 nonSendableSeparateIndices.push_back (state->getID ());
1204+ continue ;
11861205 }
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 ());
11881211 }
11891212 }
11901213
@@ -1464,43 +1487,89 @@ class PartitionOpTranslator {
14641487 translateSILMultiAssign (applyResults, pai->getOperandValues (), options);
14651488 }
14661489
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);
14731494 }
14741495 }
14751496
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;
14821509 }
14831510 }
14841511
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);
14941524 }
1525+ } else {
1526+ nonTransferringParameters.push_back (op.get ());
14951527 }
14961528 }
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+ }
14971552
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);
15021556 }
15031557
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+
15041573 if (auto cast = dyn_cast<ApplyInst>(inst))
15051574 return translateIsolationCrossingSILApply (cast);
15061575 if (auto cast = dyn_cast<BeginApplyInst>(inst))
@@ -1521,7 +1590,7 @@ class PartitionOpTranslator {
15211590 " only ApplyExpr's should cross isolation domains" );
15221591
15231592 // require all operands
1524- for (auto op : applySite-> getOperandValues ())
1593+ for (auto op : applySite. getArguments ())
15251594 if (auto value = tryToTrackValue (op))
15261595 builder.addRequire (value->getRepresentative ().getValue ());
15271596
0 commit comments