@@ -2518,18 +2518,21 @@ class DelayedArgument {
25182518 AbstractionPattern origResultType;
25192519 ClaimedParamsRef paramsToEmit;
25202520 SILFunctionTypeRepresentation functionRepresentation;
2521-
2521+ bool implicitlyAsync;
2522+
25222523 DefaultArgumentStorage (SILLocation loc,
25232524 ConcreteDeclRef defaultArgsOwner,
25242525 unsigned destIndex,
25252526 CanType resultType,
25262527 AbstractionPattern origResultType,
25272528 ClaimedParamsRef paramsToEmit,
2528- SILFunctionTypeRepresentation functionRepresentation)
2529+ SILFunctionTypeRepresentation functionRepresentation,
2530+ bool implicitlyAsync)
25292531 : loc(loc), defaultArgsOwner(defaultArgsOwner), destIndex(destIndex),
25302532 resultType (resultType), origResultType(origResultType),
25312533 paramsToEmit(paramsToEmit),
2532- functionRepresentation(functionRepresentation)
2534+ functionRepresentation(functionRepresentation),
2535+ implicitlyAsync(implicitlyAsync)
25332536 {}
25342537 };
25352538 struct BorrowedLValueStorage {
@@ -2656,13 +2659,15 @@ class DelayedArgument {
26562659 CanType resultType,
26572660 AbstractionPattern origResultType,
26582661 ClaimedParamsRef params,
2659- SILFunctionTypeRepresentation functionTypeRepresentation)
2662+ SILFunctionTypeRepresentation functionTypeRepresentation,
2663+ bool implicitlyAsync)
26602664 : Kind(DefaultArgument) {
26612665 Value.emplace <DefaultArgumentStorage>(Kind, loc, defaultArgsOwner,
26622666 destIndex,
26632667 resultType,
26642668 origResultType, params,
2665- functionTypeRepresentation);
2669+ functionTypeRepresentation,
2670+ implicitlyAsync);
26662671 }
26672672
26682673 DelayedArgument (DelayedArgument &&other)
@@ -2690,6 +2695,28 @@ class DelayedArgument {
26902695 return LV ().Loc ;
26912696 }
26922697
2698+ bool isDefaultArg () const {
2699+ return Kind == DefaultArgument;
2700+ }
2701+
2702+ SILLocation getDefaultArgLoc () const {
2703+ assert (isDefaultArg ());
2704+ auto storage = Value.get <DefaultArgumentStorage>(Kind);
2705+ return storage.loc ;
2706+ }
2707+
2708+ llvm::Optional<ActorIsolation> getIsolation () const {
2709+ if (!isDefaultArg ())
2710+ return llvm::None;
2711+
2712+ auto storage = Value.get <DefaultArgumentStorage>(Kind);
2713+ if (!storage.implicitlyAsync )
2714+ return llvm::None;
2715+
2716+ auto callee = storage.defaultArgsOwner .getDecl ();
2717+ return getActorIsolation (callee);
2718+ }
2719+
26932720 void emit (SILGenFunction &SGF, SmallVectorImpl<ManagedValue> &args,
26942721 size_t &argIndex) {
26952722 switch (Kind) {
@@ -2915,6 +2942,31 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29152942 MutableArrayRef<SmallVector<ManagedValue, 4 >> args) {
29162943 assert (!delayedArgs.empty ());
29172944
2945+ // If any of the delayed arguments are isolated default arguments,
2946+ // argument evaluation happens in the following order:
2947+ //
2948+ // 1. Left-to-right evalution of explicit r-value arguments
2949+ // 2. Left-to-right evaluation of formal access arguments
2950+ // 3. Hop to the callee's isolation domain
2951+ // 4. Left-to-right evaluation of default arguments
2952+
2953+ // So, if any delayed arguments are isolated, all default arguments
2954+ // are collected during the first pass over the delayed arguments,
2955+ // and emitted separately after a hop to the callee's isolation domain.
2956+
2957+ llvm::Optional<ActorIsolation> defaultArgIsolation;
2958+ for (auto &arg : delayedArgs) {
2959+ if (auto isolation = arg.getIsolation ()) {
2960+ defaultArgIsolation = isolation;
2961+ break ;
2962+ }
2963+ }
2964+
2965+ SmallVector<std::tuple<
2966+ /* delayedArgIt*/ decltype (delayedArgs)::iterator,
2967+ /* siteArgsIt*/ decltype (args)::iterator,
2968+ /* index*/ size_t >, 2 > isolatedArgs;
2969+
29182970 SmallVector<std::pair<SILValue, SILLocation>, 4 > emittedInoutArgs;
29192971 auto delayedNext = delayedArgs.begin ();
29202972
@@ -2923,7 +2975,8 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29232975 // wherever there's a delayed argument to insert.
29242976 //
29252977 // Note that this also begins the formal accesses in evaluation order.
2926- for (auto &siteArgs : args) {
2978+ for (auto argsIt = args.begin (); argsIt != args.end (); ++argsIt) {
2979+ auto &siteArgs = *argsIt;
29272980 // NB: siteArgs.size() may change during iteration
29282981 for (size_t i = 0 ; i < siteArgs.size (); ) {
29292982 auto &siteArg = siteArgs[i];
@@ -2936,6 +2989,15 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29362989 assert (delayedNext != delayedArgs.end ());
29372990 auto &delayedArg = *delayedNext;
29382991
2992+ if (defaultArgIsolation && delayedArg.isDefaultArg ()) {
2993+ isolatedArgs.push_back (std::make_tuple (delayedNext, argsIt, i));
2994+ if (++delayedNext == delayedArgs.end ()) {
2995+ goto done;
2996+ } else {
2997+ continue ;
2998+ }
2999+ }
3000+
29393001 // Emit the delayed argument and replace it in the arguments array.
29403002 delayedArg.emit (SGF, siteArgs, i);
29413003
@@ -2956,6 +3018,45 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29563018
29573019done:
29583020
3021+ if (defaultArgIsolation) {
3022+ assert (SGF.F .isAsync ());
3023+ assert (!isolatedArgs.empty ());
3024+
3025+ auto &firstArg = *std::get<0 >(isolatedArgs[0 ]);
3026+ auto loc = firstArg.getDefaultArgLoc ();
3027+
3028+ SILValue executor;
3029+ switch (*defaultArgIsolation) {
3030+ case ActorIsolation::GlobalActor:
3031+ case ActorIsolation::GlobalActorUnsafe:
3032+ executor = SGF.emitLoadGlobalActorExecutor (
3033+ defaultArgIsolation->getGlobalActor ());
3034+ break ;
3035+
3036+ case ActorIsolation::ActorInstance:
3037+ llvm_unreachable (" default arg cannot be actor instance isolated" );
3038+
3039+ case ActorIsolation::Unspecified:
3040+ case ActorIsolation::Nonisolated:
3041+ case ActorIsolation::NonisolatedUnsafe:
3042+ llvm_unreachable (" Not isolated" );
3043+ }
3044+
3045+ // Hop to the target isolation domain once to evaluate all
3046+ // default arguments.
3047+ SGF.emitHopToTargetExecutor (loc, executor);
3048+
3049+ size_t argsEmitted = 0 ;
3050+ for (auto &isolatedArg : isolatedArgs) {
3051+ auto &delayedArg = *std::get<0 >(isolatedArg);
3052+ auto &siteArgs = *std::get<1 >(isolatedArg);
3053+ auto argIndex = std::get<2 >(isolatedArg) + argsEmitted;
3054+ auto origIndex = argIndex;
3055+ delayedArg.emit (SGF, siteArgs, argIndex);
3056+ argsEmitted += (argIndex - origIndex);
3057+ }
3058+ }
3059+
29593060 // Check to see if we have multiple inout arguments which obviously
29603061 // alias. Note that we could do this in a later SILDiagnostics pass
29613062 // as well: this would be stronger (more equivalences exposed) but
@@ -3261,7 +3362,7 @@ class ArgEmitter {
32613362 defArg->getParamIndex (),
32623363 substParamType, origParamType,
32633364 claimNextParameters (numParams),
3264- Rep);
3365+ Rep, defArg-> isImplicitlyAsync () );
32653366 Args.push_back (ManagedValue ());
32663367
32673368 maybeEmitForeignArgument ();
@@ -4255,7 +4356,8 @@ void DelayedArgument::emitDefaultArgument(SILGenFunction &SGF,
42554356 auto value = SGF.emitApplyOfDefaultArgGenerator (info.loc ,
42564357 info.defaultArgsOwner ,
42574358 info.destIndex ,
4258- info.resultType );
4359+ info.resultType ,
4360+ info.implicitlyAsync );
42594361
42604362 SmallVector<ManagedValue, 4 > loweredArgs;
42614363 SmallVector<DelayedArgument, 4 > delayedArgs;
0 commit comments