@@ -1362,7 +1362,12 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &SGF,
13621362 }
13631363
13641364 if (foreignAsync && i == foreignAsync->completionHandlerParamIndex ()) {
1365- foreignAsyncSlot = arg;
1365+ // Copy the block.
1366+ foreignAsyncSlot = SGF.B .createCopyBlock (loc, arg);
1367+ // If the argument is consumed, we're still responsible for releasing the
1368+ // original.
1369+ if (inputs[i].isConsumed ())
1370+ SGF.emitManagedRValueWithCleanup (arg);
13661371 continue ;
13671372 }
13681373
@@ -1597,7 +1602,8 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
15971602 // Bridge the arguments.
15981603 Optional<ForeignErrorConvention> foreignError;
15991604 Optional<ForeignAsyncConvention> foreignAsync;
1600- SILValue foreignErrorSlot, foreignAsyncSlot;
1605+ SILValue foreignErrorSlot;
1606+ SILValue foreignAsyncSlot;
16011607 CanType nativeFormalResultType, bridgedFormalResultType;
16021608 auto objcFnTy = emitObjCThunkArguments (*this , loc, thunk, args,
16031609 foreignErrorSlot, foreignAsyncSlot,
@@ -1634,16 +1640,63 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
16341640
16351641 SILValue result;
16361642
1643+ CanSILFunctionType completionTy;
1644+ bool completionIsOptional = false ;
1645+ if (foreignAsyncSlot) {
1646+ completionTy = foreignAsyncSlot->getType ().getAs <SILFunctionType>();
1647+ if (!completionTy) {
1648+ completionTy = foreignAsyncSlot->getType ().getOptionalObjectType ()
1649+ .castTo <SILFunctionType>();
1650+ completionIsOptional = true ;
1651+ }
1652+ }
1653+
1654+ // Helper function to take ownership of the completion handler from the
1655+ // foreign async slot, and unwrap it if it's in an optional.
1656+ auto consumeAndUnwrapCompletionBlock = [&](SILValue &completionBlock,
1657+ SILBasicBlock *&doneBBOrNull) {
1658+ auto completionBlockMV = emitManagedRValueWithCleanup (foreignAsyncSlot);
1659+
1660+ // If the completion handler argument is nullable, and the caller gave us
1661+ // no completion handler, discard the result.
1662+ completionBlock = completionBlockMV.borrow (*this , loc).getValue ();
1663+ doneBBOrNull = nullptr ;
1664+ if (completionIsOptional) {
1665+ doneBBOrNull = createBasicBlock ();
1666+ auto hasCompletionBB = createBasicBlock ();
1667+ auto noCompletionBB = createBasicBlock ();
1668+
1669+ std::pair<EnumElementDecl *, SILBasicBlock *> dests[] = {
1670+ {getASTContext ().getOptionalSomeDecl (), hasCompletionBB},
1671+ {getASTContext ().getOptionalNoneDecl (), noCompletionBB},
1672+ };
1673+
1674+ B.createSwitchEnum (loc, completionBlock, nullptr , dests);
1675+
1676+ B.emitBlock (noCompletionBB);
1677+ B.createBranch (loc, doneBBOrNull);
1678+
1679+ B.emitBlock (hasCompletionBB);
1680+ completionBlock = hasCompletionBB->createPhiArgument (
1681+ SILType::getPrimitiveObjectType (completionTy),
1682+ OwnershipKind::Guaranteed);
1683+
1684+ }
1685+ };
1686+
16371687 // Helper function to pass a native async function's result as arguments to
16381688 // the ObjC completion handler block.
16391689 auto passResultToCompletionHandler = [&](SILValue result) -> SILValue {
16401690 Scope completionArgScope (*this , loc);
16411691
16421692 SmallVector<SILValue, 2 > completionHandlerArgs;
1643- auto completionTy = foreignAsyncSlot->getType ().castTo <SILFunctionType>();
16441693
16451694 auto asyncResult = emitManagedRValueWithCleanup (result);
16461695
1696+ SILValue completionBlock;
1697+ SILBasicBlock *doneBB;
1698+ consumeAndUnwrapCompletionBlock (completionBlock, doneBB);
1699+
16471700 auto pushArg = [&](ManagedValue arg,
16481701 CanType nativeFormalTy,
16491702 SILParameterInfo param) {
@@ -1654,7 +1707,9 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
16541707 SILType::getPrimitiveObjectType (bridgedTy));
16551708 completionHandlerArgs.push_back (bridgedArg.borrow (*this , loc).getValue ());
16561709 };
1657-
1710+
1711+ Scope completionArgDestructureScope (*this , loc);
1712+
16581713 auto errorParamIndex = foreignAsync->completionHandlerErrorParamIndex ();
16591714 auto pushErrorPlaceholder = [&]{
16601715 auto errorArgTy = completionTy->getParameters ()[*errorParamIndex]
@@ -1696,7 +1751,13 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
16961751 }
16971752 }
16981753 // Pass the bridged results on to the completion handler.
1699- B.createApply (loc, foreignAsyncSlot, {}, completionHandlerArgs);
1754+ B.createApply (loc, completionBlock, {}, completionHandlerArgs);
1755+ completionArgDestructureScope.pop ();
1756+
1757+ if (doneBB) {
1758+ B.createBranch (loc, doneBB);
1759+ B.emitBlock (doneBB);
1760+ }
17001761
17011762 // The immediate function result is an empty tuple.
17021763 return SILUndef::get (SGM.Types .getEmptyTupleType (), F);
@@ -1763,6 +1824,7 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
17631824 // Emit the error destination.
17641825 {
17651826 B.emitBlock (errorBB);
1827+
17661828 SILValue nativeError = errorBB->createPhiArgument (
17671829 substConv.getSILErrorType (getTypeExpansionContext ()),
17681830 OwnershipKind::Owned);
@@ -1772,15 +1834,23 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
17721834 // completion handler, with dummy values for the other argument(s).
17731835 Scope completionArgScope (*this , loc);
17741836
1837+ auto nativeErrorMV = emitManagedRValueWithCleanup (nativeError);
1838+
1839+ SILValue completionBlock;
1840+ SILBasicBlock *doneBB;
1841+ consumeAndUnwrapCompletionBlock (completionBlock, doneBB);
1842+
1843+ Scope completionErrorScope (*this , loc);
1844+
17751845 SmallVector<SILValue, 2 > completionHandlerArgs;
1776- auto completionTy = foreignAsyncSlot ->getType ().castTo <SILFunctionType>();
1846+ auto completionTy = completionBlock ->getType ().castTo <SILFunctionType>();
17771847 auto errorParamIndex = *foreignAsync->completionHandlerErrorParamIndex ();
17781848 auto completionErrorTy = completionTy->getParameters ()[errorParamIndex]
17791849 .getInterfaceType ();
17801850 auto bridgedError = emitNativeToBridgedError (loc,
1781- emitManagedRValueWithCleanup (nativeError) ,
1782- nativeError->getType ().getASTType (),
1783- completionErrorTy);
1851+ nativeErrorMV ,
1852+ nativeError->getType ().getASTType (),
1853+ completionErrorTy);
17841854
17851855 // Fill in placeholder arguments, and put the bridged error in its
17861856 // rightful place.
@@ -1805,10 +1875,17 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
18051875 completionHandlerArgs.push_back (none);
18061876 }
18071877 }
1808- // Pass the bridged results on to the completion handler.
1809- B.createApply (loc, foreignAsyncSlot, {}, completionHandlerArgs);
1810- completionArgScope.pop ();
1878+ // Pass the bridged error on to the completion handler.
1879+ B.createApply (loc, completionBlock, {}, completionHandlerArgs);
1880+
1881+ completionErrorScope.pop ();
18111882
1883+ if (doneBB) {
1884+ B.createBranch (loc, doneBB);
1885+ B.emitBlock (doneBB);
1886+ }
1887+ completionArgScope.pop ();
1888+
18121889 B.createBranch (loc, contBB);
18131890 } else {
18141891 // In this branch, the eventual return value is mostly invented.
0 commit comments