@@ -719,7 +719,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
719
719
SILValue resumeBuf;
720
720
SILValue continuation;
721
721
ExecutorBreadcrumb breadcrumb;
722
-
722
+
723
+ SILValue blockStorage;
724
+ CanType blockStorageTy;
725
+ CanType continuationTy;
726
+
723
727
public:
724
728
ForeignAsyncInitializationPlan (SILGenFunction &SGF, SILLocation loc,
725
729
const CalleeTypeInfo &calleeTypeInfo)
@@ -738,6 +742,75 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
738
742
// A foreign async function shouldn't have any indirect results.
739
743
}
740
744
745
+ std::tuple</* blockStorage=*/ SILValue, /* blockStorageType=*/ CanType,
746
+ /* continuationType=*/ CanType>
747
+ emitBlockStorage (SILGenFunction &SGF, SILLocation loc, bool throws) {
748
+ auto &ctx = SGF.getASTContext ();
749
+
750
+ // Wrap the Builtin.RawUnsafeContinuation in an
751
+ // UnsafeContinuation<T, E>.
752
+ auto *unsafeContinuationDecl = ctx.getUnsafeContinuationDecl ();
753
+ auto errorTy = throws ? ctx.getErrorExistentialType () : ctx.getNeverType ();
754
+ auto continuationTy =
755
+ BoundGenericType::get (unsafeContinuationDecl, /* parent=*/ Type (),
756
+ {calleeTypeInfo.substResultType , errorTy})
757
+ ->getCanonicalType ();
758
+
759
+ auto wrappedContinuation = SGF.B .createStruct (
760
+ loc, SILType::getPrimitiveObjectType (continuationTy), {continuation});
761
+
762
+ const bool checkedBridging = ctx.LangOpts .UseCheckedAsyncObjCBridging ;
763
+
764
+ // If checked bridging is enabled, wrap that continuation again in a
765
+ // CheckedContinuation<T, E>
766
+ if (checkedBridging) {
767
+ auto *checkedContinuationDecl = ctx.getCheckedContinuationDecl ();
768
+ continuationTy =
769
+ BoundGenericType::get (checkedContinuationDecl, /* parent=*/ Type (),
770
+ {calleeTypeInfo.substResultType , errorTy})
771
+ ->getCanonicalType ();
772
+ }
773
+
774
+ auto blockStorageTy = SILBlockStorageType::get (
775
+ checkedBridging ? ctx.TheAnyType : continuationTy);
776
+ auto blockStorage = SGF.emitTemporaryAllocation (
777
+ loc, SILType::getPrimitiveAddressType (blockStorageTy));
778
+
779
+ auto continuationAddr = SGF.B .createProjectBlockStorage (loc, blockStorage);
780
+
781
+ // Stash continuation in a buffer for a block object.
782
+
783
+ if (checkedBridging) {
784
+ auto createIntrinsic =
785
+ throws ? SGF.SGM .getCreateCheckedThrowingContinuation ()
786
+ : SGF.SGM .getCreateCheckedContinuation ();
787
+
788
+ // In this case block storage captures `Any` which would be initialized
789
+ // with an checked continuation.
790
+ auto underlyingContinuationAddr =
791
+ SGF.B .createInitExistentialAddr (loc, continuationAddr, continuationTy,
792
+ SGF.getLoweredType (continuationTy),
793
+ /* conformances=*/ {});
794
+
795
+ auto subs = SubstitutionMap::get (createIntrinsic->getGenericSignature (),
796
+ {calleeTypeInfo.substResultType },
797
+ ArrayRef<ProtocolConformanceRef>{});
798
+
799
+ InitializationPtr underlyingInit (
800
+ new KnownAddressInitialization (underlyingContinuationAddr));
801
+ auto continuationMV =
802
+ ManagedValue::forRValueWithoutOwnership (wrappedContinuation);
803
+ SGF.emitApplyOfLibraryIntrinsic (loc, createIntrinsic, subs,
804
+ {continuationMV}, SGFContext ())
805
+ .forwardInto (SGF, loc, underlyingInit.get ());
806
+ } else {
807
+ SGF.B .createStore (loc, wrappedContinuation, continuationAddr,
808
+ StoreOwnershipQualifier::Trivial);
809
+ }
810
+
811
+ return std::make_tuple (blockStorage, blockStorageTy, continuationTy);
812
+ }
813
+
741
814
ManagedValue
742
815
emitForeignAsyncCompletionHandler (SILGenFunction &SGF,
743
816
AbstractionPattern origFormalType,
@@ -751,28 +824,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
751
824
continuation = SGF.B .createGetAsyncContinuationAddr (loc, resumeBuf,
752
825
calleeTypeInfo.substResultType , throws);
753
826
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 = SILType::getPrimitiveAddressType (
771
- SILBlockStorageType::get (continuationTy));
772
- auto blockStorage = SGF.emitTemporaryAllocation (loc, blockStorageTy);
773
- auto continuationAddr = SGF.B .createProjectBlockStorage (loc, blockStorage);
774
- SGF.B .createStore (loc, wrappedContinuation, continuationAddr,
775
- StoreOwnershipQualifier::Trivial);
827
+ std::tie (blockStorage, blockStorageTy, continuationTy) =
828
+ emitBlockStorage (SGF, loc, throws);
776
829
777
830
// Get the block invocation function for the given completion block type.
778
831
auto completionHandlerIndex = calleeTypeInfo.foreign .async
@@ -796,11 +849,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
796
849
SGF.SGM .getOrCreateForeignAsyncCompletionHandlerImplFunction (
797
850
cast<SILFunctionType>(
798
851
impFnTy->mapTypeOutOfContext ()->getReducedType (sig)),
852
+ blockStorageTy->mapTypeOutOfContext ()->getReducedType (sig),
799
853
continuationTy->mapTypeOutOfContext ()->getReducedType (sig),
800
- origFormalType, sig, *calleeTypeInfo.foreign .async ,
801
- calleeTypeInfo.foreign .error );
854
+ origFormalType, sig, calleeTypeInfo);
802
855
auto impRef = SGF.B .createFunctionRef (loc, impl);
803
-
856
+
804
857
// Initialize the block object for the completion handler.
805
858
SILValue block = SGF.B .createInitBlockStorageHeader (loc, blockStorage,
806
859
impRef, SILType::getPrimitiveObjectType (impFnTy),
@@ -829,7 +882,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
829
882
SILValue bridgedForeignError) override {
830
883
// There should be no direct results from the call.
831
884
assert (directResults.empty ());
832
-
885
+ auto &ctx = SGF.getASTContext ();
886
+
833
887
// Await the continuation we handed off to the completion handler.
834
888
SILBasicBlock *resumeBlock = SGF.createBasicBlock ();
835
889
SILBasicBlock *errorBlock = nullptr ;
@@ -854,54 +908,74 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
854
908
// (1) fulfill the unsafe continuation with the foreign error
855
909
// (2) branch to the await block
856
910
{
857
- // First, fulfill the unsafe continuation with the foreign error.
911
+ // First, fulfill the continuation with the foreign error.
858
912
// Currently, that block's code looks something like
859
913
// %foreignError = ... : $*Optional<NSError>
860
914
// %converter = function_ref _convertNSErrorToError(_:)
861
915
// %error = apply %converter(%foreignError)
862
916
// [... insert here ...]
863
917
// destroy_value %error
864
918
// destroy_value %foreignError
865
- // Insert code to fulfill it after the native %error is defined. That
866
- // code should structure the RawUnsafeContinuation (continuation) into
867
- // an appropriately typed UnsafeContinuation and then pass that together
868
- // with (a copy of) the error to
869
- // _resumeUnsafeThrowingContinuationWithError.
919
+ // Insert code to fulfill it after the native %error is defined. That
920
+ // code should load UnsafeContinuation (or CheckedContinuation
921
+ // depending on mode) and then pass that together with (a copy of) the
922
+ // error to _resume{Unsafe, Checked}ThrowingContinuationWithError.
870
923
// [foreign_error_block_with_foreign_async_convention]
871
924
SGF.B .setInsertionPoint (
872
925
++bridgedForeignError->getDefiningInstruction ()->getIterator ());
873
926
874
- auto continuationDecl = SGF. getASTContext (). getUnsafeContinuationDecl () ;
927
+ bool checkedBridging = ctx. LangOpts . UseCheckedAsyncObjCBridging ;
875
928
876
- auto errorTy = SGF.getASTContext ().getErrorExistentialType ();
877
- auto continuationBGT =
878
- BoundGenericType::get (continuationDecl, Type (),
879
- {calleeTypeInfo.substResultType , errorTy});
880
929
auto env = SGF.F .getGenericEnvironment ();
881
930
auto sig = env ? env->getGenericSignature ().getCanonicalSignature ()
882
931
: CanGenericSignature ();
883
- auto mappedContinuationTy =
884
- continuationBGT->mapTypeOutOfContext ()->getReducedType (sig);
932
+
933
+ // Load unsafe or checked continuation from the block storage
934
+ // and call _resume{Unsafe, Checked}ThrowingContinuationWithError.
935
+
936
+ SILValue continuationAddr =
937
+ SGF.B .createProjectBlockStorage (loc, blockStorage);
938
+
939
+ ManagedValue continuation;
940
+ if (checkedBridging) {
941
+ FormalEvaluationScope scope (SGF);
942
+
943
+ auto underlyingValueTy =
944
+ OpenedArchetypeType::get (ctx.TheAnyType , sig);
945
+
946
+ auto underlyingValueAddr = SGF.emitOpenExistential (
947
+ loc, ManagedValue::forTrivialAddressRValue (continuationAddr),
948
+ SGF.getLoweredType (underlyingValueTy), AccessKind::Read);
949
+
950
+ continuation = SGF.B .createUncheckedAddrCast (
951
+ loc, underlyingValueAddr,
952
+ SILType::getPrimitiveAddressType (continuationTy));
953
+ } else {
954
+ auto continuationVal = SGF.B .createLoad (
955
+ loc, continuationAddr, LoadOwnershipQualifier::Trivial);
956
+ continuation =
957
+ ManagedValue::forObjectRValueWithoutOwnership (continuationVal);
958
+ }
959
+
960
+ auto mappedOutContinuationTy =
961
+ continuationTy->mapTypeOutOfContext ()->getReducedType (sig);
885
962
auto resumeType =
886
- cast<BoundGenericType>(mappedContinuationTy).getGenericArgs ()[0 ];
887
- auto continuationTy = continuationBGT->getCanonicalType ();
963
+ cast<BoundGenericType>(mappedOutContinuationTy).getGenericArgs ()[0 ];
888
964
889
965
auto errorIntrinsic =
890
- SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
966
+ checkedBridging
967
+ ? SGF.SGM .getResumeCheckedThrowingContinuationWithError ()
968
+ : SGF.SGM .getResumeUnsafeThrowingContinuationWithError ();
969
+
891
970
Type replacementTypes[] = {
892
971
SGF.F .mapTypeIntoContext (resumeType)->getCanonicalType ()};
893
972
auto subs = SubstitutionMap::get (errorIntrinsic->getGenericSignature (),
894
973
replacementTypes,
895
974
ArrayRef<ProtocolConformanceRef>{});
896
- auto wrappedContinuation = SGF.B .createStruct (
897
- loc, SILType::getPrimitiveObjectType (continuationTy),
898
- {continuation});
899
975
900
- auto continuationMV = ManagedValue::forObjectRValueWithoutOwnership (
901
- SILValue (wrappedContinuation));
902
976
SGF.emitApplyOfLibraryIntrinsic (
903
977
loc, errorIntrinsic, subs,
904
- {continuationMV ,
978
+ {continuation ,
905
979
SGF.B .copyOwnedObjectRValue (loc, bridgedForeignError,
906
980
ManagedValue::ScopeKind::Lexical)},
907
981
SGFContext ());
@@ -924,7 +998,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
924
998
925
999
Scope errorScope (SGF, loc);
926
1000
927
- auto errorTy = SGF. getASTContext () .getErrorExistentialType ();
1001
+ auto errorTy = ctx .getErrorExistentialType ();
928
1002
auto errorVal = SGF.B .createTermResult (
929
1003
SILType::getPrimitiveObjectType (errorTy), OwnershipKind::Owned);
930
1004
0 commit comments