@@ -2718,6 +2718,28 @@ class DelayedArgument {
27182718 return LV ().Loc ;
27192719 }
27202720
2721+ bool isDefaultArg () const {
2722+ return Kind == DefaultArgument;
2723+ }
2724+
2725+ SILLocation getDefaultArgLoc () const {
2726+ assert (isDefaultArg ());
2727+ auto storage = Value.get <DefaultArgumentStorage>(Kind);
2728+ return storage.loc ;
2729+ }
2730+
2731+ llvm::Optional<ActorIsolation> getIsolation () const {
2732+ if (!isDefaultArg ())
2733+ return llvm::None;
2734+
2735+ auto storage = Value.get <DefaultArgumentStorage>(Kind);
2736+ if (!storage.implicitlyAsync )
2737+ return llvm::None;
2738+
2739+ auto callee = storage.defaultArgsOwner .getDecl ();
2740+ return getActorIsolation (callee);
2741+ }
2742+
27212743 void emit (SILGenFunction &SGF, SmallVectorImpl<ManagedValue> &args,
27222744 size_t &argIndex) {
27232745 switch (Kind) {
@@ -2943,6 +2965,31 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29432965 MutableArrayRef<SmallVector<ManagedValue, 4 >> args) {
29442966 assert (!delayedArgs.empty ());
29452967
2968+ // If any of the delayed arguments are isolated default arguments,
2969+ // argument evaluation happens in the following order:
2970+ //
2971+ // 1. Left-to-right evalution of explicit r-value arguments
2972+ // 2. Left-to-right evaluation of formal access arguments
2973+ // 3. Hop to the callee's isolation domain
2974+ // 4. Left-to-right evaluation of default arguments
2975+
2976+ // So, if any delayed arguments are isolated, all default arguments
2977+ // are collected during the first pass over the delayed arguments,
2978+ // and emitted separately after a hop to the callee's isolation domain.
2979+
2980+ llvm::Optional<ActorIsolation> defaultArgIsolation;
2981+ for (auto &arg : delayedArgs) {
2982+ if (auto isolation = arg.getIsolation ()) {
2983+ defaultArgIsolation = isolation;
2984+ break ;
2985+ }
2986+ }
2987+
2988+ SmallVector<std::tuple<
2989+ /* delayedArgIt*/ decltype (delayedArgs)::iterator,
2990+ /* siteArgsIt*/ decltype (args)::iterator,
2991+ /* index*/ size_t >, 2 > isolatedArgs;
2992+
29462993 SmallVector<std::pair<SILValue, SILLocation>, 4 > emittedInoutArgs;
29472994 auto delayedNext = delayedArgs.begin ();
29482995
@@ -2951,7 +2998,8 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29512998 // wherever there's a delayed argument to insert.
29522999 //
29533000 // Note that this also begins the formal accesses in evaluation order.
2954- for (auto &siteArgs : args) {
3001+ for (auto argsIt = args.begin (); argsIt != args.end (); ++argsIt) {
3002+ auto &siteArgs = *argsIt;
29553003 // NB: siteArgs.size() may change during iteration
29563004 for (size_t i = 0 ; i < siteArgs.size (); ) {
29573005 auto &siteArg = siteArgs[i];
@@ -2964,6 +3012,15 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29643012 assert (delayedNext != delayedArgs.end ());
29653013 auto &delayedArg = *delayedNext;
29663014
3015+ if (defaultArgIsolation && delayedArg.isDefaultArg ()) {
3016+ isolatedArgs.push_back (std::make_tuple (delayedNext, argsIt, i));
3017+ if (++delayedNext == delayedArgs.end ()) {
3018+ goto done;
3019+ } else {
3020+ continue ;
3021+ }
3022+ }
3023+
29673024 // Emit the delayed argument and replace it in the arguments array.
29683025 delayedArg.emit (SGF, siteArgs, i);
29693026
@@ -2984,6 +3041,45 @@ static void emitDelayedArguments(SILGenFunction &SGF,
29843041
29853042done:
29863043
3044+ if (defaultArgIsolation) {
3045+ assert (SGF.F .isAsync ());
3046+ assert (!isolatedArgs.empty ());
3047+
3048+ auto &firstArg = *std::get<0 >(isolatedArgs[0 ]);
3049+ auto loc = firstArg.getDefaultArgLoc ();
3050+
3051+ SILValue executor;
3052+ switch (*defaultArgIsolation) {
3053+ case ActorIsolation::GlobalActor:
3054+ case ActorIsolation::GlobalActorUnsafe:
3055+ executor = SGF.emitLoadGlobalActorExecutor (
3056+ defaultArgIsolation->getGlobalActor ());
3057+ break ;
3058+
3059+ case ActorIsolation::ActorInstance:
3060+ llvm_unreachable (" default arg cannot be actor instance isolated" );
3061+
3062+ case ActorIsolation::Unspecified:
3063+ case ActorIsolation::Nonisolated:
3064+ case ActorIsolation::NonisolatedUnsafe:
3065+ llvm_unreachable (" Not isolated" );
3066+ }
3067+
3068+ // Hop to the target isolation domain once to evaluate all
3069+ // default arguments.
3070+ SGF.emitHopToTargetExecutor (loc, executor);
3071+
3072+ size_t argsEmitted = 0 ;
3073+ for (auto &isolatedArg : isolatedArgs) {
3074+ auto &delayedArg = *std::get<0 >(isolatedArg);
3075+ auto &siteArgs = *std::get<1 >(isolatedArg);
3076+ auto argIndex = std::get<2 >(isolatedArg) + argsEmitted;
3077+ auto origIndex = argIndex;
3078+ delayedArg.emit (SGF, siteArgs, argIndex);
3079+ argsEmitted += (argIndex - origIndex);
3080+ }
3081+ }
3082+
29873083 // Check to see if we have multiple inout arguments which obviously
29883084 // alias. Note that we could do this in a later SILDiagnostics pass
29893085 // as well: this would be stronger (more equivalences exposed) but
0 commit comments