Skip to content

Commit 62fce8a

Browse files
authored
Merge pull request swiftlang#67982 from tshortli/back-deployed-keypaths
SILGen: Don't reference external property descriptors for @backDeployed properties
2 parents 9ecb6b4 + d062489 commit 62fce8a

File tree

6 files changed

+54
-29
lines changed

6 files changed

+54
-29
lines changed

lib/SILGen/SILGen.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
351351
/// Emits a thunk from an actor function to a potentially distributed call.
352352
void emitDistributedThunk(SILDeclRef thunk);
353353

354+
/// Returns true if the given declaration must be referenced through a
355+
/// back deployment thunk in a context with the given resilience expansion.
356+
bool requiresBackDeploymentThunk(ValueDecl *decl,
357+
ResilienceExpansion expansion);
358+
354359
/// Emits a thunk that calls either the original function if it is available
355360
/// or otherwise calls a fallback variant of the function that was emitted
356361
/// into the client module.

lib/SILGen/SILGenApply.cpp

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -280,31 +280,6 @@ static void convertOwnershipConventionsGivenParamInfos(
280280
});
281281
}
282282

283-
static bool shouldApplyBackDeploymentThunk(ValueDecl *decl, ASTContext &ctx,
284-
ResilienceExpansion expansion) {
285-
auto backDeployBeforeVersion = decl->getBackDeployedBeforeOSVersion(ctx);
286-
if (!backDeployBeforeVersion)
287-
return false;
288-
289-
// If the context of the application is inlinable then we must always call the
290-
// back deployment thunk since we can't predict the deployment targets of
291-
// other modules.
292-
if (expansion != ResilienceExpansion::Maximal)
293-
return true;
294-
295-
// In resilient function bodies skip calling the back deployment thunk when
296-
// the deployment target is high enough that the ABI implementation of the
297-
// back deployed function is guaranteed to be available.
298-
auto deploymentAvailability = AvailabilityContext::forDeploymentTarget(ctx);
299-
auto declAvailability =
300-
AvailabilityContext(VersionRange::allGTE(*backDeployBeforeVersion));
301-
302-
if (deploymentAvailability.isContainedIn(declAvailability))
303-
return false;
304-
305-
return true;
306-
}
307-
308283
//===----------------------------------------------------------------------===//
309284
// Callee
310285
//===----------------------------------------------------------------------===//
@@ -1155,7 +1130,6 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11551130

11561131
SILDeclRef getDeclRefForStaticDispatchApply(DeclRefExpr *e) {
11571132
auto *afd = cast<AbstractFunctionDecl>(e->getDecl());
1158-
auto &ctx = SGF.getASTContext();
11591133

11601134
// A call to a `distributed` function may need to go through a thunk.
11611135
if (callSite && callSite->shouldApplyDistributedThunk()) {
@@ -1164,8 +1138,9 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
11641138
}
11651139

11661140
// A call to `@backDeployed` function may need to go through a thunk.
1167-
if (shouldApplyBackDeploymentThunk(afd, ctx,
1168-
SGF.F.getResilienceExpansion())) {
1141+
1142+
if (SGF.SGM.requiresBackDeploymentThunk(afd,
1143+
SGF.F.getResilienceExpansion())) {
11691144
return SILDeclRef(afd).asBackDeploymentKind(
11701145
SILDeclRef::BackDeploymentKind::Thunk);
11711146
}
@@ -6717,7 +6692,7 @@ SILDeclRef SILGenModule::getAccessorDeclRef(AccessorDecl *accessor,
67176692
ResilienceExpansion expansion) {
67186693
auto declRef = SILDeclRef(accessor, SILDeclRef::Kind::Func);
67196694

6720-
if (shouldApplyBackDeploymentThunk(accessor, getASTContext(), expansion))
6695+
if (requiresBackDeploymentThunk(accessor, expansion))
67216696
return declRef.asBackDeploymentKind(SILDeclRef::BackDeploymentKind::Thunk);
67226697

67236698
return declRef.asForeign(requiresForeignEntryPoint(accessor));

lib/SILGen/SILGenBackDeploy.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,36 @@ static void emitBackDeployForwardApplyAndReturnOrThrow(
168168
SGF.B.createBranch(loc, SGF.ReturnDest.getBlock(), directResults);
169169
}
170170

171+
bool SILGenModule::requiresBackDeploymentThunk(ValueDecl *decl,
172+
ResilienceExpansion expansion) {
173+
auto &ctx = getASTContext();
174+
auto backDeployBeforeVersion = decl->getBackDeployedBeforeOSVersion(ctx);
175+
if (!backDeployBeforeVersion)
176+
return false;
177+
178+
switch (expansion) {
179+
case ResilienceExpansion::Minimal:
180+
// In a minimal resilience expansion we must always call the back deployment
181+
// thunk since we can't predict the deployment targets of the modules that
182+
// might inline the call.
183+
return true;
184+
case ResilienceExpansion::Maximal:
185+
// FIXME: We can skip thunking if we're in the same module.
186+
break;
187+
}
188+
189+
// Use of a back deployment thunk is unnecessary if the deployment target is
190+
// high enough that the ABI implementation of the back deployed declaration is
191+
// guaranteed to be available.
192+
auto deploymentAvailability = AvailabilityContext::forDeploymentTarget(ctx);
193+
auto declAvailability =
194+
AvailabilityContext(VersionRange::allGTE(*backDeployBeforeVersion));
195+
if (deploymentAvailability.isContainedIn(declAvailability))
196+
return false;
197+
198+
return true;
199+
}
200+
171201
void SILGenFunction::emitBackDeploymentThunk(SILDeclRef thunk) {
172202
// Generate code equivalent to:
173203
//

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3821,6 +3821,12 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
38213821
return false;
38223822
}
38233823

3824+
// Back deployed properties have the same restrictions as
3825+
// always-emit-into-client properties.
3826+
if (requiresBackDeploymentThunk(baseDecl, expansion)) {
3827+
return false;
3828+
}
3829+
38243830
// Properties that only dispatch via ObjC lookup do not have nor
38253831
// need property descriptors, since the selector identifies the
38263832
// storage.

test/SILGen/back_deployed_attr_accessor.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,11 @@ func caller(_ s: TopLevelStruct) {
4545
// -- Verify the thunk is called
4646
// CHECK: {{%.*}} = function_ref @$s11back_deploy14TopLevelStructV8propertyACvgTwb : $@convention(method) (TopLevelStruct) -> TopLevelStruct
4747
_ = s.property
48+
49+
// -- Verify key path
50+
// CHECK: {{%.*}} = keypath $KeyPath<TopLevelStruct, TopLevelStruct>, (root $TopLevelStruct; gettable_property $TopLevelStruct, id @$s11back_deploy14TopLevelStructV8propertyACvg : $@convention(method) (TopLevelStruct) -> TopLevelStruct, getter @$s11back_deploy14TopLevelStructV8propertyACvpACTK : $@convention(thin) (@in_guaranteed TopLevelStruct) -> @out TopLevelStruct)
51+
_ = \TopLevelStruct.property
4852
}
53+
54+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s11back_deploy14TopLevelStructV8propertyACvpACTK : $@convention(thin) (@in_guaranteed TopLevelStruct) -> @out TopLevelStruct
55+
// CHECK: function_ref @$s11back_deploy14TopLevelStructV8propertyACvgTwb

test/attr/attr_backDeployed_evolution.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ do {
149149

150150
let empty = IntArray.empty
151151
precondition(empty.values == [])
152+
precondition(empty[keyPath: \.values] == [])
152153

153154
var array = IntArray([5])
154155

@@ -177,6 +178,7 @@ do {
177178
do {
178179
let defaulted = ReferenceIntArray()
179180
precondition(defaulted.values == [])
181+
precondition(defaulted[keyPath: \.values] == [])
180182

181183
let empty = ReferenceIntArray.empty
182184
precondition(empty.values == [])

0 commit comments

Comments
 (0)