@@ -738,6 +738,75 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
738
738
// A foreign async function shouldn't have any indirect results.
739
739
}
740
740
741
+ std::tuple</* blockStorage=*/ SILValue, /* blockStorageType=*/ CanType,
742
+ /* continuationType=*/ CanType>
743
+ emitBlockStorage (SILGenFunction &SGF, SILLocation loc, bool throws) {
744
+ auto &ctx = SGF.getASTContext ();
745
+
746
+ // Wrap the Builtin.RawUnsafeContinuation in an
747
+ // UnsafeContinuation<T, E>.
748
+ auto *unsafeContinuationDecl = ctx.getUnsafeContinuationDecl ();
749
+ auto errorTy = throws ? ctx.getErrorExistentialType () : ctx.getNeverType ();
750
+ auto continuationTy =
751
+ BoundGenericType::get (unsafeContinuationDecl, /* parent=*/ Type (),
752
+ {calleeTypeInfo.substResultType , errorTy})
753
+ ->getCanonicalType ();
754
+
755
+ auto wrappedContinuation = SGF.B .createStruct (
756
+ loc, SILType::getPrimitiveObjectType (continuationTy), {continuation});
757
+
758
+ const bool checkedBridging = ctx.LangOpts .UseCheckedAsyncObjCBridging ;
759
+
760
+ // If checked bridging is enabled, wrap that continuation again in a
761
+ // CheckedContinuation<T, E>
762
+ if (checkedBridging) {
763
+ auto *checkedContinuationDecl = ctx.getCheckedContinuationDecl ();
764
+ continuationTy =
765
+ BoundGenericType::get (checkedContinuationDecl, /* parent=*/ Type (),
766
+ {calleeTypeInfo.substResultType , errorTy})
767
+ ->getCanonicalType ();
768
+ }
769
+
770
+ auto blockStorageTy = SILBlockStorageType::get (
771
+ checkedBridging ? ctx.TheAnyType : continuationTy);
772
+ auto blockStorage = SGF.emitTemporaryAllocation (
773
+ loc, SILType::getPrimitiveAddressType (blockStorageTy));
774
+
775
+ auto continuationAddr = SGF.B .createProjectBlockStorage (loc, blockStorage);
776
+
777
+ // Stash continuation in a buffer for a block object.
778
+
779
+ if (checkedBridging) {
780
+ auto createIntrinsic =
781
+ throws ? SGF.SGM .getCreateCheckedThrowingContinuation ()
782
+ : SGF.SGM .getCreateCheckedContinuation ();
783
+
784
+ // In this case block storage captures `Any` which would be initialized
785
+ // with an checked continuation.
786
+ auto underlyingContinuationAddr =
787
+ SGF.B .createInitExistentialAddr (loc, continuationAddr, continuationTy,
788
+ SGF.getLoweredType (continuationTy),
789
+ /* conformances=*/ {});
790
+
791
+ auto subs = SubstitutionMap::get (createIntrinsic->getGenericSignature (),
792
+ {calleeTypeInfo.substResultType },
793
+ ArrayRef<ProtocolConformanceRef>{});
794
+
795
+ InitializationPtr underlyingInit (
796
+ new KnownAddressInitialization (underlyingContinuationAddr));
797
+ auto continuationMV =
798
+ ManagedValue::forRValueWithoutOwnership (wrappedContinuation);
799
+ SGF.emitApplyOfLibraryIntrinsic (loc, createIntrinsic, subs,
800
+ {continuationMV}, SGFContext ())
801
+ .forwardInto (SGF, loc, underlyingInit.get ());
802
+ } else {
803
+ SGF.B .createStore (loc, wrappedContinuation, continuationAddr,
804
+ StoreOwnershipQualifier::Trivial);
805
+ }
806
+
807
+ return std::make_tuple (blockStorage, blockStorageTy, continuationTy);
808
+ }
809
+
741
810
ManagedValue
742
811
emitForeignAsyncCompletionHandler (SILGenFunction &SGF,
743
812
AbstractionPattern origFormalType,
@@ -751,28 +820,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
751
820
continuation = SGF.B .createGetAsyncContinuationAddr (loc, resumeBuf,
752
821
calleeTypeInfo.substResultType , throws);
753
822
754
- // Wrap the Builtin.RawUnsafeContinuation in an
755
- // UnsafeContinuation<T, E>.
756
- auto continuationDecl = SGF.getASTContext ().getUnsafeContinuationDecl ();
757
-
758
- auto errorTy = throws
759
- ? SGF.getASTContext ().getErrorExistentialType ()
760
- : SGF.getASTContext ().getNeverType ();
761
- auto continuationTy = BoundGenericType::get (continuationDecl, Type (),
762
- { calleeTypeInfo.substResultType , errorTy })
763
- ->getCanonicalType ();
764
- auto wrappedContinuation =
765
- SGF.B .createStruct (loc,
766
- SILType::getPrimitiveObjectType (continuationTy),
767
- {continuation});
768
-
769
- // Stash it in a buffer for a block object.
770
- auto blockStorageTy = SILBlockStorageType::get (continuationTy);
771
- auto blockStorage = SGF.emitTemporaryAllocation (
772
- loc, SILType::getPrimitiveAddressType (blockStorageTy));
773
- auto continuationAddr = SGF.B .createProjectBlockStorage (loc, blockStorage);
774
- SGF.B .createStore (loc, wrappedContinuation, continuationAddr,
775
- StoreOwnershipQualifier::Trivial);
823
+ SILValue blockStorage;
824
+ CanType blockStorageTy;
825
+ CanType continuationTy;
826
+ std::tie (blockStorage, blockStorageTy, continuationTy) =
827
+ emitBlockStorage (SGF, loc, throws);
776
828
777
829
// Get the block invocation function for the given completion block type.
778
830
auto completionHandlerIndex = calleeTypeInfo.foreign .async
@@ -797,6 +849,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
797
849
cast<SILFunctionType>(
798
850
impFnTy->mapTypeOutOfContext ()->getReducedType (sig)),
799
851
blockStorageTy->mapTypeOutOfContext ()->getReducedType (sig),
852
+ continuationTy->mapTypeOutOfContext ()->getReducedType (sig),
800
853
origFormalType, sig, calleeTypeInfo);
801
854
auto impRef = SGF.B .createFunctionRef (loc, impl);
802
855
0 commit comments