@@ -2695,6 +2695,28 @@ class DelayedArgument {
26952695 return LV ().Loc ;
26962696 }
26972697
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+
26982720 void emit (SILGenFunction &SGF, SmallVectorImpl<ManagedValue> &args,
26992721 size_t &argIndex) {
27002722 switch (Kind) {
@@ -2920,6 +2942,31 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29202942 MutableArrayRef<SmallVector<ManagedValue, 4 >> args) {
29212943 assert (!delayedArgs.empty ());
29222944
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+
29232970 SmallVector<std::pair<SILValue, SILLocation>, 4 > emittedInoutArgs;
29242971 auto delayedNext = delayedArgs.begin ();
29252972
@@ -2928,7 +2975,8 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29282975 // wherever there's a delayed argument to insert.
29292976 //
29302977 // Note that this also begins the formal accesses in evaluation order.
2931- for (auto &siteArgs : args) {
2978+ for (auto argsIt = args.begin (); argsIt != args.end (); ++argsIt) {
2979+ auto &siteArgs = *argsIt;
29322980 // NB: siteArgs.size() may change during iteration
29332981 for (size_t i = 0 ; i < siteArgs.size (); ) {
29342982 auto &siteArg = siteArgs[i];
@@ -2941,6 +2989,15 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29412989 assert (delayedNext != delayedArgs.end ());
29422990 auto &delayedArg = *delayedNext;
29432991
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+
29443001 // Emit the delayed argument and replace it in the arguments array.
29453002 delayedArg.emit (SGF, siteArgs, i);
29463003
@@ -2961,6 +3018,45 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29613018
29623019done:
29633020
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+
29643060 // Check to see if we have multiple inout arguments which obviously
29653061 // alias. Note that we could do this in a later SILDiagnostics pass
29663062 // as well: this would be stronger (more equivalences exposed) but
0 commit comments