@@ -259,6 +259,31 @@ static void convertOwnershipConventionsGivenParamInfos(
259259 });
260260}
261261
262+ static bool shouldApplyBackDeploymentThunk (ValueDecl *decl, ASTContext &ctx,
263+ ResilienceExpansion expansion) {
264+ auto backDeployBeforeVersion = decl->getBackDeployBeforeOSVersion (ctx);
265+ if (!backDeployBeforeVersion)
266+ return false ;
267+
268+ // If the context of the application is inlinable then we must always call the
269+ // back deployment thunk since we can't predict the deployment targets of
270+ // other modules.
271+ if (expansion != ResilienceExpansion::Maximal)
272+ return true ;
273+
274+ // In resilient function bodies skip calling the back deployment thunk when
275+ // the deployment target is high enough that the ABI implementation of the
276+ // back deployed function is guaranteed to be available.
277+ auto deploymentAvailability = AvailabilityContext::forDeploymentTarget (ctx);
278+ auto declAvailability =
279+ AvailabilityContext (VersionRange::allGTE (*backDeployBeforeVersion));
280+
281+ if (deploymentAvailability.isContainedIn (declAvailability))
282+ return false ;
283+
284+ return true ;
285+ }
286+
262287// ===----------------------------------------------------------------------===//
263288// Callee
264289// ===----------------------------------------------------------------------===//
@@ -1104,6 +1129,28 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11041129 }
11051130 }
11061131
1132+ SILDeclRef getDeclRefForStaticDispatchApply (DeclRefExpr *e) {
1133+ auto *afd = cast<AbstractFunctionDecl>(e->getDecl ());
1134+ auto &ctx = SGF.getASTContext ();
1135+
1136+ // A call to a `distributed` function may need to go through a thunk.
1137+ if (callSite && callSite->shouldApplyDistributedThunk ()) {
1138+ if (auto distributedThunk = afd->getDistributedThunk ())
1139+ return SILDeclRef (distributedThunk).asDistributed ();
1140+ }
1141+
1142+ // A call to `@_backDeploy` function may need to go through a thunk.
1143+ if (shouldApplyBackDeploymentThunk (afd, ctx,
1144+ SGF.F .getResilienceExpansion ())) {
1145+ return SILDeclRef (afd).asBackDeploymentKind (
1146+ SILDeclRef::BackDeploymentKind::Thunk);
1147+ }
1148+
1149+ return SILDeclRef (afd).asForeign (
1150+ !isConstructorWithGeneratedAllocatorThunk (afd) &&
1151+ requiresForeignEntryPoint (afd));
1152+ }
1153+
11071154 //
11081155 // Known callees.
11091156 //
@@ -1144,25 +1191,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11441191 }
11451192
11461193 // Otherwise, we have a statically-dispatched call.
1147- SILDeclRef constant = SILDeclRef (e->getDecl ());
1148-
1149- // / Some special handling may be necessary for thunks:
1150- if (callSite && callSite->shouldApplyDistributedThunk ()) {
1151- if (auto distributedThunk = cast<AbstractFunctionDecl>(e->getDecl ())->getDistributedThunk ()) {
1152- constant = SILDeclRef (distributedThunk).asDistributed ();
1153- }
1154- } else if (afd->isBackDeployed ()) {
1155- // If we're calling a back deployed function then we need to call a
1156- // thunk instead that will handle the fallback when the original
1157- // function is unavailable at runtime.
1158- constant =
1159- constant.asBackDeploymentKind (SILDeclRef::BackDeploymentKind::Thunk);
1160- } else {
1161- constant = constant.asForeign (
1162- !isConstructorWithGeneratedAllocatorThunk (e->getDecl ())
1163- && requiresForeignEntryPoint (e->getDecl ()));
1164- }
1165-
1194+ SILDeclRef constant = getDeclRefForStaticDispatchApply (e);
11661195 auto captureInfo = SGF.SGM .Types .getLoweredLocalCaptures (constant);
11671196 SGF.SGM .Types .setCaptureTypeExpansionContext (constant, SGF.SGM .M );
11681197
@@ -5943,9 +5972,11 @@ SILGenFunction::prepareSubscriptIndices(SubscriptDecl *subscript,
59435972 return result;
59445973}
59455974
5946- SILDeclRef SILGenModule::getAccessorDeclRef (AccessorDecl *accessor) {
5975+ SILDeclRef SILGenModule::getAccessorDeclRef (AccessorDecl *accessor,
5976+ ResilienceExpansion expansion) {
59475977 auto declRef = SILDeclRef (accessor, SILDeclRef::Kind::Func);
5948- if (accessor->isBackDeployed ())
5978+
5979+ if (shouldApplyBackDeploymentThunk (accessor, getASTContext (), expansion))
59495980 return declRef.asBackDeploymentKind (SILDeclRef::BackDeploymentKind::Thunk);
59505981
59515982 return declRef.asForeign (requiresForeignEntryPoint (accessor));
0 commit comments