@@ -546,6 +546,10 @@ class Callee {
546546 return cast<EnumElementDecl>(Constant.getDecl ());
547547 }
548548
549+ ValueDecl *getDecl () {
550+ return Constant.getDecl ();
551+ }
552+
549553 CalleeTypeInfo createCalleeTypeInfo (SILGenFunction &SGF,
550554 Optional<SILDeclRef> constant,
551555 SILType formalFnType) const & {
@@ -3646,14 +3650,16 @@ class CallEmission {
36463650 Callee callee;
36473651 FormalEvaluationScope initialWritebackScope;
36483652 unsigned expectedSiteCount;
3653+ bool implicitlyAsync;
36493654
36503655public:
36513656 // / Create an emission for a call of the given callee.
36523657 CallEmission (SILGenFunction &SGF, Callee &&callee,
36533658 FormalEvaluationScope &&writebackScope)
36543659 : SGF(SGF), callee(std::move(callee)),
36553660 initialWritebackScope (std::move(writebackScope)),
3656- expectedSiteCount(callee.getParameterListCount()) {}
3661+ expectedSiteCount(callee.getParameterListCount()),
3662+ implicitlyAsync(false ) {}
36573663
36583664 // / A factory method for decomposing the apply expr \p e into a call
36593665 // / emission.
@@ -3688,6 +3694,11 @@ class CallEmission {
36883694 return (callee.kind == Callee::Kind::EnumElement);
36893695 }
36903696
3697+ // / Sets a flag that indicates whether this call be treated as being
3698+ // / implicitly async, i.e., it requires a hop_to_executor prior to
3699+ // / invoking the sync callee, etc.
3700+ void setImplicitlyAsync (bool flag) { implicitlyAsync = flag; }
3701+
36913702 CleanupHandle applyCoroutine (SmallVectorImpl<ManagedValue> &yields);
36923703
36933704 RValue apply (SGFContext C = SGFContext()) {
@@ -3912,11 +3923,15 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
39123923
39133924 auto mv = callee.getFnValue (SGF, borrowedSelf);
39143925
3926+ Optional<ValueDecl*> calleeDeclInfo;
3927+ if (implicitlyAsync)
3928+ calleeDeclInfo = callee.getDecl ();
3929+
39153930 // Emit the uncurried call.
39163931 return SGF.emitApply (
39173932 std::move (resultPlan), std::move (argScope), uncurriedLoc.getValue (), mv,
39183933 callee.getSubstitutions (), uncurriedArgs, calleeTypeInfo, options,
3919- uncurriedContext);
3934+ uncurriedContext, calleeDeclInfo );
39203935}
39213936
39223937static void emitPseudoFunctionArguments (SILGenFunction &SGF,
@@ -4224,6 +4239,8 @@ CallEmission CallEmission::forApplyExpr(SILGenFunction &SGF, ApplyExpr *e) {
42244239
42254240 emission.addCallSite (apply.callSite , std::move (preparedArgs),
42264241 apply.callSite ->throws ());
4242+
4243+ emission.setImplicitlyAsync (apply.callSite ->implicitlyAsync ());
42274244 }
42284245
42294246 return emission;
@@ -4266,6 +4283,31 @@ bool SILGenModule::isNonMutatingSelfIndirect(SILDeclRef methodRef) {
42664283 return self.isFormalIndirect ();
42674284}
42684285
4286+ Optional<SILValue> SILGenFunction::EmitLoadActorExecutorForCallee (
4287+ SILGenFunction *SGF,
4288+ ValueDecl *calleeVD,
4289+ ArrayRef<ManagedValue> args) {
4290+ if (auto *funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(calleeVD)) {
4291+ auto actorIso = getActorIsolation (funcDecl);
4292+ switch (actorIso.getKind ()) {
4293+ case ActorIsolation::Unspecified:
4294+ case ActorIsolation::Independent:
4295+ case ActorIsolation::IndependentUnsafe:
4296+ break ;
4297+
4298+ case ActorIsolation::ActorInstance: {
4299+ assert (args.size () > 0 && " no self argument for actor-instance call?" );
4300+ auto calleeSelf = args.back ();
4301+ return calleeSelf.borrow (*SGF, SGF->F .getLocation ()).getValue ();
4302+ }
4303+
4304+ case ActorIsolation::GlobalActor:
4305+ return SGF->emitLoadGlobalActorExecutor (actorIso.getGlobalActor ());
4306+ }
4307+ }
4308+ return None;
4309+ }
4310+
42694311// ===----------------------------------------------------------------------===//
42704312// Top Level Entrypoints
42714313// ===----------------------------------------------------------------------===//
@@ -4279,7 +4321,8 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
42794321 ManagedValue fn, SubstitutionMap subs,
42804322 ArrayRef<ManagedValue> args,
42814323 const CalleeTypeInfo &calleeTypeInfo,
4282- ApplyOptions options, SGFContext evalContext) {
4324+ ApplyOptions options, SGFContext evalContext,
4325+ Optional<ValueDecl *> implicitlyAsyncApply) {
42834326 auto substFnType = calleeTypeInfo.substFnType ;
42844327 auto substResultType = calleeTypeInfo.substResultType ;
42854328
@@ -4365,15 +4408,31 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43654408 subs.getGenericSignature ().getCanonicalSignature ());
43664409 }
43674410
4368- auto rawDirectResult = [&] {
4411+ // The presence of `implicitlyAsyncApply` indicates that the callee is a
4412+ // synchronous function isolated to an actor other than our own.
4413+ // Such functions require the caller to hop to the callee's executor
4414+ // prior to invoking the callee.
4415+ if (implicitlyAsyncApply.hasValue ()) {
4416+ assert (F.isAsync () && " cannot hop_to_executor in a non-async func!" );
4417+
4418+ auto calleeVD = implicitlyAsyncApply.getValue ();
4419+ auto maybeExecutor = EmitLoadActorExecutorForCallee (this , calleeVD, args);
4420+
4421+ assert (maybeExecutor.hasValue ());
4422+ B.createHopToExecutor (loc, maybeExecutor.getValue ());
4423+ }
4424+
4425+ SILValue rawDirectResult;
4426+ {
43694427 SmallVector<SILValue, 1 > rawDirectResults;
43704428 emitRawApply (*this , loc, fn, subs, args, substFnType, options,
43714429 indirectResultAddrs, rawDirectResults);
43724430 assert (rawDirectResults.size () == 1 );
4373- return rawDirectResults[0 ];
4374- }();
4431+ rawDirectResult = rawDirectResults[0 ];
4432+ }
43754433
4376- if (substFnType->isAsync ())
4434+ // hop back to the current executor
4435+ if (substFnType->isAsync () || implicitlyAsyncApply.hasValue ())
43774436 emitHopToCurrentExecutor (loc);
43784437
43794438 // Pop the argument scope.
@@ -4482,7 +4541,7 @@ RValue SILGenFunction::emitMonomorphicApply(
44824541 *this , calleeTypeInfo, loc, evalContext);
44834542 ArgumentScope argScope (*this , loc);
44844543 return emitApply (std::move (resultPlan), std::move (argScope), loc, fn, {},
4485- args, calleeTypeInfo, options, evalContext);
4544+ args, calleeTypeInfo, options, evalContext, None );
44864545}
44874546
44884547// / Emit either an 'apply' or a 'try_apply', with the error branch of
@@ -4768,7 +4827,7 @@ SILGenFunction::emitApplyOfLibraryIntrinsic(SILLocation loc,
47684827 ResultPlanBuilder::computeResultPlan (*this , calleeTypeInfo, loc, ctx);
47694828 ArgumentScope argScope (*this , loc);
47704829 return emitApply (std::move (resultPlan), std::move (argScope), loc, mv, subMap,
4771- finalArgs, calleeTypeInfo, ApplyOptions::None, ctx);
4830+ finalArgs, calleeTypeInfo, ApplyOptions::None, ctx, None );
47724831}
47734832
47744833StringRef SILGenFunction::getMagicFunctionString () {
0 commit comments