Skip to content

Commit 6f28e27

Browse files
authored
Merge pull request swiftlang#63832 from tshortli/back-deployed-funcs-are-only-fragile-for-specified-oses
AST: Only treat `@backDeployed` functions as fragile on platforms with an active attribute
2 parents 6f31f84 + f1a8740 commit 6f28e27

File tree

11 files changed

+102
-44
lines changed

11 files changed

+102
-44
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -906,10 +906,14 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
906906
Optional<llvm::VersionTuple> getIntroducedOSVersion(PlatformKind Kind) const;
907907

908908
/// Returns the OS version in which the decl became ABI as specified by the
909-
/// @backDeployed attribute.
909+
/// `@backDeployed` attribute.
910910
Optional<llvm::VersionTuple>
911911
getBackDeployedBeforeOSVersion(ASTContext &Ctx) const;
912912

913+
/// Returns true if the decl has an active `@backDeployed` attribute for the
914+
/// given context.
915+
bool isBackDeployed(ASTContext &Ctx) const;
916+
913917
/// Returns the starting location of the entire declaration.
914918
SourceLoc getStartLoc() const { return getSourceRange().Start; }
915919

@@ -1177,6 +1181,9 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
11771181
// doesn't declare any @_spi.
11781182
ArrayRef<Identifier> getSPIGroups() const;
11791183

1184+
/// Returns true if this declaration has any `@backDeployed` attributes.
1185+
bool hasBackDeployedAttr() const;
1186+
11801187
/// Emit a diagnostic tied to this declaration.
11811188
template<typename ...ArgTypes>
11821189
InFlightDiagnostic diagnose(
@@ -6793,10 +6800,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
67936800
/// diagnosed errors during type checking.
67946801
FuncDecl *getDistributedThunk() const;
67956802

6796-
/// Returns 'true' if the function has (or inherits) the `@backDeployed`
6797-
/// attribute.
6798-
bool isBackDeployed() const;
6799-
68006803
PolymorphicEffectKind getPolymorphicEffectKind(EffectKind kind) const;
68016804

68026805
// FIXME: Hack that provides names with keyword arguments for accessors.

lib/AST/Decl.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,21 @@ Decl::getBackDeployedBeforeOSVersion(ASTContext &Ctx) const {
492492
return None;
493493
}
494494

495+
bool Decl::isBackDeployed(ASTContext &Ctx) const {
496+
return getBackDeployedBeforeOSVersion(Ctx) != None;
497+
}
498+
499+
bool Decl::hasBackDeployedAttr() const {
500+
if (getAttrs().hasAttribute<BackDeployedAttr>())
501+
return true;
502+
503+
// Accessors may inherit `@backDeployed`.
504+
if (auto *AD = dyn_cast<AccessorDecl>(this))
505+
return AD->getStorage()->hasBackDeployedAttr();
506+
507+
return false;
508+
}
509+
495510
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
496511
StaticSpellingKind SSK) {
497512
switch (SSK) {
@@ -8154,19 +8169,6 @@ bool AbstractFunctionDecl::isSendable() const {
81548169
return getAttrs().hasAttribute<SendableAttr>();
81558170
}
81568171

8157-
bool AbstractFunctionDecl::isBackDeployed() const {
8158-
if (getAttrs().hasAttribute<BackDeployedAttr>())
8159-
return true;
8160-
8161-
// Property and subscript accessors inherit the attribute.
8162-
if (auto *AD = dyn_cast<AccessorDecl>(this)) {
8163-
if (AD->getStorage()->getAttrs().hasAttribute<BackDeployedAttr>())
8164-
return true;
8165-
}
8166-
8167-
return false;
8168-
}
8169-
81708172
BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
81718173
if ((getBodyKind() == BodyKind::Synthesize ||
81728174
getBodyKind() == BodyKind::Unparsed) &&

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
478478
/*allowUsableFromInline=*/true};
479479
}
480480

481-
if (AFD->getAttrs().hasAttribute<BackDeployedAttr>()) {
481+
if (AFD->isBackDeployed(context->getASTContext())) {
482482
return {FragileFunctionKind::BackDeploy,
483483
/*allowUsableFromInline=*/true};
484484
}
@@ -495,7 +495,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
495495
return {FragileFunctionKind::AlwaysEmitIntoClient,
496496
/*allowUsableFromInline=*/true};
497497
}
498-
if (storage->getAttrs().hasAttribute<BackDeployedAttr>()) {
498+
if (storage->isBackDeployed(context->getASTContext())) {
499499
return {FragileFunctionKind::BackDeploy,
500500
/*allowUsableFromInline=*/true};
501501
}

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ bool SILDeclRef::isBackDeployed() const {
955955

956956
auto *decl = getDecl();
957957
if (auto afd = dyn_cast<AbstractFunctionDecl>(decl))
958-
return afd->isBackDeployed();
958+
return afd->isBackDeployed(getASTContext());
959959

960960
return false;
961961
}

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ void SILGenModule::emitAbstractFuncDecl(AbstractFunctionDecl *AFD) {
14051405
getFunction(thunk, ForDefinition));
14061406
}
14071407

1408-
if (AFD->isBackDeployed()) {
1408+
if (AFD->isBackDeployed(M.getASTContext())) {
14091409
// Emit the fallback function that will be used when the original function
14101410
// is unavailable at runtime.
14111411
auto fallback = SILDeclRef(AFD).asBackDeploymentKind(

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10771077
}
10781078

10791079
void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
1080-
assert(!afd->isBackDeployed() &&
1080+
assert(!afd->hasBackDeployedAttr() &&
10811081
"cannot back deploy dynamically dispatched methods");
10821082

10831083
ArgumentSource selfArgSource(selfApply->getBase());

lib/SILOptimizer/UtilityPasses/SILSkippingChecker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static bool shouldHaveSkippedFunction(const SILFunction &F) {
7878
// second resilient SILFunction is also emitted for back deployed functions.
7979
// Since the body of the function as written was not skipped, it's expected
8080
// that we see the SILFunction for the resilient copy here.
81-
if (func->isBackDeployed())
81+
if (func->hasBackDeployedAttr())
8282
return false;
8383

8484
// If none of those conditions trip, then this is something that _should_

test/ModuleInterface/back-deployed-attr.swift

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
// RUN: %target-swift-typecheck-module-from-interface(%t/Test.swiftinterface)
66
// RUN: %FileCheck %s < %t/Test.swiftinterface
77

8+
// REQUIRES: OS=macosx
9+
810
public struct TopLevelStruct {
911
// TODO: Print `@backDeployed` in swiftinterfaces (rdar://104920183)
1012
// CHECK: @_backDeploy(before: macOS 12.0)
11-
// CHECK: public func backDeployedFunc_SinglePlatform() -> Swift.Int { return 42 }
13+
// CHECK: public func backDeployedFunc_SinglePlatform() -> Swift.Int { return 41 }
1214
@backDeployed(before: macOS 12.0)
13-
public func backDeployedFunc_SinglePlatform() -> Int { return 42 }
15+
public func backDeployedFunc_SinglePlatform() -> Int { return 41 }
1416

1517
// CHECK: @_backDeploy(before: macOS 12.0, iOS 15.0)
16-
// CHECK: public func backDeployedFunc_MultiPlatform() -> Swift.Int { return 43 }
18+
// CHECK: public func backDeployedFunc_MultiPlatform() -> Swift.Int { return 42 }
1719
@backDeployed(before: macOS 12.0, iOS 15.0)
18-
public func backDeployedFunc_MultiPlatform() -> Int { return 43 }
20+
public func backDeployedFunc_MultiPlatform() -> Int { return 42 }
1921

2022
// CHECK: @_backDeploy(before: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0)
2123
// CHECK: public func backDeployedFunc_MultiPlatformSeparate() -> Swift.Int { return 43 }
@@ -27,43 +29,58 @@ public struct TopLevelStruct {
2729

2830
// CHECK: @_backDeploy(before: macOS 12.0)
2931
// CHECK: public var backDeployedComputedProperty: Swift.Int {
30-
// CHECK: get { 44 }
31-
// CHECK: }
32+
// CHECK-NEXT: get { 44 }
33+
// CHECK-NEXT: }
3234
@backDeployed(before: macOS 12.0)
3335
public var backDeployedComputedProperty: Int { 44 }
3436

3537
// CHECK: @_backDeploy(before: macOS 12.0)
3638
// CHECK: public var backDeployedPropertyWithAccessors: Swift.Int {
37-
// CHECK: get { 45 }
38-
// CHECK: }
39+
// CHECK-NEXT: get { 45 }
40+
// CHECK-NEXT: }
3941
@backDeployed(before: macOS 12.0)
4042
public var backDeployedPropertyWithAccessors: Int {
4143
get { 45 }
4244
}
4345

4446
// CHECK: @_backDeploy(before: macOS 12.0)
4547
// CHECK: public subscript(index: Swift.Int) -> Swift.Int {
46-
// CHECK: get { 46 }
47-
// CHECK: }
48+
// CHECK-NEXT: get { 46 }
49+
// CHECK-NEXT: }
4850
@backDeployed(before: macOS 12.0)
4951
public subscript(index: Int) -> Int {
5052
get { 46 }
5153
}
5254
}
5355

56+
// CHECK: @_backDeploy(before: iOS 15.0)
57+
// CHECK: public func backDeployedFunc_iOSOnly() -> Swift.Int
58+
// CHECK-NOT: return 99
59+
@backDeployed(before: iOS 15.0)
60+
public func backDeployedFunc_iOSOnly() -> Int { return 99 }
61+
5462
// CHECK: @_backDeploy(before: macOS 12.0)
55-
// CHECK: public func backDeployTopLevelFunc1() -> Swift.Int { return 47 }
63+
// CHECK: public func backDeployTopLevelFunc_macOS() -> Swift.Int {
64+
// CHECK-NEXT: return 47
65+
// CHECK-NEXT: }
66+
// CHECK-NOT: fatalError()
5667
@backDeployed(before: macOS 12.0)
57-
public func backDeployTopLevelFunc1() -> Int { return 47 }
68+
public func backDeployTopLevelFunc_macOS() -> Int {
69+
#if os(macOS)
70+
return 47
71+
#else
72+
fatalError()
73+
#endif
74+
}
5875

5976
// MARK: - Availability macros
6077

6178
// CHECK: @_backDeploy(before: macOS 12.1)
62-
// CHECK: public func backDeployTopLevelFunc2() -> Swift.Int { return 48 }
79+
// CHECK: public func backDeployTopLevelFunc_macOS12_1() -> Swift.Int { return 48 }
6380
@backDeployed(before: _macOS12_1)
64-
public func backDeployTopLevelFunc2() -> Int { return 48 }
81+
public func backDeployTopLevelFunc_macOS12_1() -> Int { return 48 }
6582

6683
// CHECK: @_backDeploy(before: macOS 12.1, iOS 15.1)
67-
// CHECK: public func backDeployTopLevelFunc3() -> Swift.Int { return 49 }
84+
// CHECK: public func backDeployTopLevelFunc_myProject() -> Swift.Int { return 49 }
6885
@backDeployed(before: _myProject 1.0)
69-
public func backDeployTopLevelFunc3() -> Int { return 49 }
86+
public func backDeployTopLevelFunc_myProject() -> Int { return 49 }

test/SILGen/back_deployed_attr.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@
66

77
// REQUIRES: OS=macosx
88

9+
// CHECK: sil non_abi [serialized] [ossa] @$s11back_deploy8someFuncyyFTwB
10+
// CHECK: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy8someFuncyyFTwb
11+
// CHECK: sil [available 10.52] [ossa] @$s11back_deploy8someFuncyyF
912
@backDeployed(before: macOS 10.52)
1013
public func someFunc() {}
1114

15+
// CHECK-NOT: @$s11back_deploy0A13DeployedOniOSyyFTwB
16+
// CHECK-NOT: @$s11back_deploy0A13DeployedOniOSyyFTwb
17+
// CHECK: sil [ossa] @$s11back_deploy0A13DeployedOniOSyyF
18+
@backDeployed(before: iOS 13.13)
19+
public func backDeployedOniOS() {}
20+
1221
public struct S<T> {
1322
@usableFromInline var _x: T
1423

@@ -28,6 +37,8 @@ func resilientCaller(_ s: inout S<Z>) {
2837
// CHECK-BACK-DEPLOY: function_ref @$s11back_deploy8someFuncyyFTwb : $@convention(thin) () -> ()
2938
// CHECK-NATIVE: function_ref @$s11back_deploy8someFuncyyF : $@convention(thin) () -> ()
3039
someFunc()
40+
// CHECK: function_ref @$s11back_deploy0A13DeployedOniOSyyF : $@convention(thin) () -> ()
41+
backDeployedOniOS()
3142
// CHECK-BACK-DEPLOY: function_ref @$s11back_deploy1SV1xxvgTwb : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @out τ_0_0
3243
// CHECK-NATIVE: function_ref @$s11back_deploy1SV1xxvg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @out τ_0_0
3344
_ = s.x
@@ -41,6 +52,8 @@ func resilientCaller(_ s: inout S<Z>) {
4152
func inlinableCaller(_ s: inout S<Z>) {
4253
// CHECK: function_ref @$s11back_deploy8someFuncyyFTwb : $@convention(thin) () -> ()
4354
someFunc()
55+
// CHECK: function_ref @$s11back_deploy0A13DeployedOniOSyyF : $@convention(thin) () -> ()
56+
backDeployedOniOS()
4457
// CHECK: function_ref @$s11back_deploy1SV1xxvgTwb : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @out τ_0_0
4558
_ = s.x
4659
// CHECK: function_ref @$s11back_deploy1SV1xxvsTwb : $@convention(method) <τ_0_0> (@in τ_0_0, @inout S<τ_0_0>) -> ()
@@ -52,6 +65,8 @@ func inlinableCaller(_ s: inout S<Z>) {
5265
func aeicCaller(_ s: inout S<Z>) {
5366
// CHECK: function_ref @$s11back_deploy8someFuncyyFTwb : $@convention(thin) () -> ()
5467
someFunc()
68+
// CHECK: function_ref @$s11back_deploy0A13DeployedOniOSyyF : $@convention(thin) () -> ()
69+
backDeployedOniOS()
5570
// CHECK: function_ref @$s11back_deploy1SV1xxvgTwb : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @out τ_0_0
5671
_ = s.x
5772
// CHECK: function_ref @$s11back_deploy1SV1xxvsTwb : $@convention(method) <τ_0_0> (@in τ_0_0, @inout S<τ_0_0>) -> ()
@@ -63,6 +78,8 @@ func aeicCaller(_ s: inout S<Z>) {
6378
public func backDeployedCaller(_ s: inout S<Z>) {
6479
// CHECK: function_ref @$s11back_deploy8someFuncyyFTwb : $@convention(thin) () -> ()
6580
someFunc()
81+
// CHECK: function_ref @$s11back_deploy0A13DeployedOniOSyyF : $@convention(thin) () -> ()
82+
backDeployedOniOS()
6683
// CHECK: function_ref @$s11back_deploy1SV1xxvgTwb : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @out τ_0_0
6784
_ = s.x
6885
// CHECK: function_ref @$s11back_deploy1SV1xxvsTwb : $@convention(method) <τ_0_0> (@in τ_0_0, @inout S<τ_0_0>) -> ()

test/SILGen/opaque_values_silgen.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,11 +637,13 @@ func giveKeyPathString() {
637637
takeKeyPathString(\StructWithAReadableStringProperty.s)
638638
}
639639

640-
// CHECK-LABEL: sil {{.*}}@$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb : {{.*}} <T> {{.*}} {
640+
#if os(macOS)
641+
// CHECK-OSX-LABEL: sil {{.*}}@$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb : {{.*}} <T> {{.*}} {
641642
// Ensure that there aren't any "normal" (in the sense of try_apply) blocks that
642643
// take unbound generic parameters (τ_0_0).
643-
// CHECK-NOT: {{bb[0-9]+}}({{%[^,]+}} : @owned $τ_0_0):
644-
// CHECK-LABEL: } // end sil function '$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb'
644+
// CHECK-OSX-NOT: {{bb[0-9]+}}({{%[^,]+}} : @owned $τ_0_0):
645+
// CHECK-OSX-LABEL: } // end sil function '$s20opaque_values_silgen29backDeployingReturningGenericyxxKlFTwb'
645646
@available(SwiftStdlib 5.1, *)
646647
@backDeployed(before: SwiftStdlib 5.8)
647648
public func backDeployingReturningGeneric<T>(_ t: T) throws -> T { t }
649+
#endif

0 commit comments

Comments
 (0)