@@ -1362,7 +1362,12 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &SGF,
1362
1362
}
1363
1363
1364
1364
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);
1366
1371
continue ;
1367
1372
}
1368
1373
@@ -1597,7 +1602,8 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1597
1602
// Bridge the arguments.
1598
1603
Optional<ForeignErrorConvention> foreignError;
1599
1604
Optional<ForeignAsyncConvention> foreignAsync;
1600
- SILValue foreignErrorSlot, foreignAsyncSlot;
1605
+ SILValue foreignErrorSlot;
1606
+ SILValue foreignAsyncSlot;
1601
1607
CanType nativeFormalResultType, bridgedFormalResultType;
1602
1608
auto objcFnTy = emitObjCThunkArguments (*this , loc, thunk, args,
1603
1609
foreignErrorSlot, foreignAsyncSlot,
@@ -1634,16 +1640,63 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1634
1640
1635
1641
SILValue result;
1636
1642
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
+
1637
1687
// Helper function to pass a native async function's result as arguments to
1638
1688
// the ObjC completion handler block.
1639
1689
auto passResultToCompletionHandler = [&](SILValue result) -> SILValue {
1640
1690
Scope completionArgScope (*this , loc);
1641
1691
1642
1692
SmallVector<SILValue, 2 > completionHandlerArgs;
1643
- auto completionTy = foreignAsyncSlot->getType ().castTo <SILFunctionType>();
1644
1693
1645
1694
auto asyncResult = emitManagedRValueWithCleanup (result);
1646
1695
1696
+ SILValue completionBlock;
1697
+ SILBasicBlock *doneBB;
1698
+ consumeAndUnwrapCompletionBlock (completionBlock, doneBB);
1699
+
1647
1700
auto pushArg = [&](ManagedValue arg,
1648
1701
CanType nativeFormalTy,
1649
1702
SILParameterInfo param) {
@@ -1654,7 +1707,9 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1654
1707
SILType::getPrimitiveObjectType (bridgedTy));
1655
1708
completionHandlerArgs.push_back (bridgedArg.borrow (*this , loc).getValue ());
1656
1709
};
1657
-
1710
+
1711
+ Scope completionArgDestructureScope (*this , loc);
1712
+
1658
1713
auto errorParamIndex = foreignAsync->completionHandlerErrorParamIndex ();
1659
1714
auto pushErrorPlaceholder = [&]{
1660
1715
auto errorArgTy = completionTy->getParameters ()[*errorParamIndex]
@@ -1696,7 +1751,13 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1696
1751
}
1697
1752
}
1698
1753
// 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
+ }
1700
1761
1701
1762
// The immediate function result is an empty tuple.
1702
1763
return SILUndef::get (SGM.Types .getEmptyTupleType (), F);
@@ -1763,6 +1824,7 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1763
1824
// Emit the error destination.
1764
1825
{
1765
1826
B.emitBlock (errorBB);
1827
+
1766
1828
SILValue nativeError = errorBB->createPhiArgument (
1767
1829
substConv.getSILErrorType (getTypeExpansionContext ()),
1768
1830
OwnershipKind::Owned);
@@ -1772,15 +1834,23 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1772
1834
// completion handler, with dummy values for the other argument(s).
1773
1835
Scope completionArgScope (*this , loc);
1774
1836
1837
+ auto nativeErrorMV = emitManagedRValueWithCleanup (nativeError);
1838
+
1839
+ SILValue completionBlock;
1840
+ SILBasicBlock *doneBB;
1841
+ consumeAndUnwrapCompletionBlock (completionBlock, doneBB);
1842
+
1843
+ Scope completionErrorScope (*this , loc);
1844
+
1775
1845
SmallVector<SILValue, 2 > completionHandlerArgs;
1776
- auto completionTy = foreignAsyncSlot ->getType ().castTo <SILFunctionType>();
1846
+ auto completionTy = completionBlock ->getType ().castTo <SILFunctionType>();
1777
1847
auto errorParamIndex = *foreignAsync->completionHandlerErrorParamIndex ();
1778
1848
auto completionErrorTy = completionTy->getParameters ()[errorParamIndex]
1779
1849
.getInterfaceType ();
1780
1850
auto bridgedError = emitNativeToBridgedError (loc,
1781
- emitManagedRValueWithCleanup (nativeError) ,
1782
- nativeError->getType ().getASTType (),
1783
- completionErrorTy);
1851
+ nativeErrorMV ,
1852
+ nativeError->getType ().getASTType (),
1853
+ completionErrorTy);
1784
1854
1785
1855
// Fill in placeholder arguments, and put the bridged error in its
1786
1856
// rightful place.
@@ -1805,10 +1875,17 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
1805
1875
completionHandlerArgs.push_back (none);
1806
1876
}
1807
1877
}
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 ();
1811
1882
1883
+ if (doneBB) {
1884
+ B.createBranch (loc, doneBB);
1885
+ B.emitBlock (doneBB);
1886
+ }
1887
+ completionArgScope.pop ();
1888
+
1812
1889
B.createBranch (loc, contBB);
1813
1890
} else {
1814
1891
// In this branch, the eventual return value is mostly invented.
0 commit comments