@@ -451,6 +451,33 @@ class TupleInitializationResultPlan final : public ResultPlan {
451451 }
452452};
453453
454+ class ForeignAsyncInitializationPlan final : public ResultPlan {
455+ SILGenFunction &SGF;
456+ SILLocation loc;
457+ public:
458+ ForeignAsyncInitializationPlan (SILGenFunction &SGF, SILLocation loc)
459+ : SGF(SGF), loc(loc) {
460+ }
461+
462+ void
463+ gatherIndirectResultAddrs (SILGenFunction &SGF, SILLocation loc,
464+ SmallVectorImpl<SILValue> &outList) const override {
465+ // TODO: Move values from the continuation result buffer to the individual
466+ // out argument buffers, unless we were able to emit the resume buffer
467+ // in-place.
468+ }
469+
470+ RValue finish (SILGenFunction &SGF, SILLocation loc, CanType substType,
471+ ArrayRef<ManagedValue> &directResults) override {
472+ // There should be no direct results from the call.
473+ assert (directResults.empty ());
474+
475+ // TODO: Get the actual result values from the awaited continuation.
476+ // For now, produce an undef RValue.
477+ return SGF.emitUndefRValue (loc, substType);
478+ }
479+ };
480+
454481class ForeignErrorInitializationPlan final : public ResultPlan {
455482 SILLocation loc;
456483 LValue lvalue;
@@ -467,7 +494,7 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
467494 ResultPlanPtr &&subPlan)
468495 : loc(loc), subPlan(std::move(subPlan)) {
469496 unsigned errorParamIndex =
470- calleeTypeInfo.foreignError ->getErrorParameterIndex ();
497+ calleeTypeInfo.foreign . error ->getErrorParameterIndex ();
471498 auto substFnType = calleeTypeInfo.substFnType ;
472499 SILParameterInfo errorParameter =
473500 substFnType->getParameters ()[errorParamIndex];
@@ -543,51 +570,56 @@ class ForeignErrorInitializationPlan final : public ResultPlan {
543570// / If the initialization is non-null, the result plan will emit into it.
544571ResultPlanPtr ResultPlanBuilder::buildTopLevelResult (Initialization *init,
545572 SILLocation loc) {
546- // First check if we do not have a foreign error. If we don't, just call
547- // build.
548- auto foreignError = calleeTypeInfo.foreignError ;
549- if (!foreignError) {
573+ // First check if we have a foreign error and/or async convention.
574+ if (auto foreignAsync = calleeTypeInfo.foreign .async ) {
575+ // Create a result plan that gets the result schema from the completion
576+ // handler callback's arguments.
577+ // completion handler.
578+ return ResultPlanPtr (new ForeignAsyncInitializationPlan (SGF, loc));
579+
580+ } else if (auto foreignError = calleeTypeInfo.foreign .error ) {
581+ // Handle the foreign error first.
582+ //
583+ // The plan needs to be built using the formal result type after foreign-error
584+ // adjustment.
585+ switch (foreignError->getKind ()) {
586+ // These conventions make the formal result type ().
587+ case ForeignErrorConvention::ZeroResult:
588+ case ForeignErrorConvention::NonZeroResult:
589+ assert (calleeTypeInfo.substResultType ->isVoid ());
590+ allResults.clear ();
591+ break ;
592+
593+ // These conventions leave the formal result alone.
594+ case ForeignErrorConvention::ZeroPreservedResult:
595+ case ForeignErrorConvention::NonNilError:
596+ break ;
597+
598+ // This convention changes the formal result to the optional object type; we
599+ // need to make our own make SILResultInfo array.
600+ case ForeignErrorConvention::NilResult: {
601+ assert (allResults.size () == 1 );
602+ auto substFnTy = calleeTypeInfo.substFnType ;
603+ CanType objectType = allResults[0 ]
604+ .getReturnValueType (SGF.SGM .M , substFnTy,
605+ SGF.getTypeExpansionContext ())
606+ .getOptionalObjectType ();
607+ SILResultInfo optResult = allResults[0 ].getWithInterfaceType (objectType);
608+ allResults.clear ();
609+ allResults.push_back (optResult);
610+ break ;
611+ }
612+ }
613+
614+ ResultPlanPtr subPlan = build (init, calleeTypeInfo.origResultType .getValue (),
615+ calleeTypeInfo.substResultType );
616+ return ResultPlanPtr (new ForeignErrorInitializationPlan (
617+ SGF, loc, calleeTypeInfo, std::move (subPlan)));
618+ } else {
619+ // Otherwise, we can just call build.
550620 return build (init, calleeTypeInfo.origResultType .getValue (),
551621 calleeTypeInfo.substResultType );
552622 }
553-
554- // Otherwise, handle the foreign error first.
555- //
556- // The plan needs to be built using the formal result type after foreign-error
557- // adjustment.
558- switch (foreignError->getKind ()) {
559- // These conventions make the formal result type ().
560- case ForeignErrorConvention::ZeroResult:
561- case ForeignErrorConvention::NonZeroResult:
562- assert (calleeTypeInfo.substResultType ->isVoid ());
563- allResults.clear ();
564- break ;
565-
566- // These conventions leave the formal result alone.
567- case ForeignErrorConvention::ZeroPreservedResult:
568- case ForeignErrorConvention::NonNilError:
569- break ;
570-
571- // This convention changes the formal result to the optional object type; we
572- // need to make our own make SILResultInfo array.
573- case ForeignErrorConvention::NilResult: {
574- assert (allResults.size () == 1 );
575- auto substFnTy = calleeTypeInfo.substFnType ;
576- CanType objectType = allResults[0 ]
577- .getReturnValueType (SGF.SGM .M , substFnTy,
578- SGF.getTypeExpansionContext ())
579- .getOptionalObjectType ();
580- SILResultInfo optResult = allResults[0 ].getWithInterfaceType (objectType);
581- allResults.clear ();
582- allResults.push_back (optResult);
583- break ;
584- }
585- }
586-
587- ResultPlanPtr subPlan = build (init, calleeTypeInfo.origResultType .getValue (),
588- calleeTypeInfo.substResultType );
589- return ResultPlanPtr (new ForeignErrorInitializationPlan (
590- SGF, loc, calleeTypeInfo, std::move (subPlan)));
591623}
592624
593625// / Build a result plan for the results of an apply.
0 commit comments