Skip to content

Commit 0bb6a7b

Browse files
committed
SIL: Avoid serializing the bodies of the original copies of @_backDeploy functions to prevent the optimizer from inlining those bodies into their back deployment thunks. This ensures that the copy of the function in the library dylib is reliably called when it is available, both with and without optimizations enabled. Also update the attr_backDeploy_evolution test case to use precondition() instead of assert() since asserts are compiled out with optimizations enabled.
Resolves rdar://90525337
1 parent b07b700 commit 0bb6a7b

9 files changed

+48
-25
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,8 @@ struct SILDeclRef {
372372
bool isNoinline() const;
373373
/// True if the function has __always inline attribute.
374374
bool isAlwaysInline() const;
375+
/// True if the function has the @_backDeploy attribute.
376+
bool isBackDeployed() const;
375377

376378
/// Return the expected linkage of this declaration.
377379
SILLinkage getLinkage(ForDefinition_t forDefinition) const;

include/swift/SIL/SILLinkage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ enum IsSerialized_t : unsigned char {
135135
///
136136
/// This flag is only valid for Public, PublicNonABI, PublicExternal,
137137
/// HiddenExternal and Shared functions.
138-
/// Functions with external linkage (PublicExternl, HiddenExternal) will not
138+
/// Functions with external linkage (PublicExternal, HiddenExternal) will not
139139
/// be serialized, because they are available in a different module (from which
140140
/// they were de-serialized).
141141
///

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,19 @@ IsSerialized_t SILDeclRef::isSerialized() const {
689689
if (isClangImported())
690690
return IsSerialized;
691691

692+
// Handle back deployed functions. The original back deployed function
693+
// should not be serialized, but the thunk and fallback should be since they
694+
// need to be emitted into the client.
695+
if (isBackDeployed()) {
696+
switch (backDeploymentKind) {
697+
case BackDeploymentKind::None:
698+
return IsNotSerialized;
699+
case BackDeploymentKind::Fallback:
700+
case BackDeploymentKind::Thunk:
701+
return IsSerialized;
702+
}
703+
}
704+
692705
// Otherwise, ask the AST if we're inside an @inlinable context.
693706
if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal)
694707
return IsSerialized;
@@ -736,6 +749,17 @@ bool SILDeclRef::isAlwaysInline() const {
736749
return false;
737750
}
738751

752+
bool SILDeclRef::isBackDeployed() const {
753+
if (!hasDecl())
754+
return false;
755+
756+
auto *decl = getDecl();
757+
if (auto afd = dyn_cast<AbstractFunctionDecl>(decl))
758+
return afd->isBackDeployed();
759+
760+
return false;
761+
}
762+
739763
bool SILDeclRef::isAnyThunk() const {
740764
return isForeignToNativeThunk() || isNativeToForeignThunk() ||
741765
isDistributedThunk() || isBackDeploymentThunk();

test/SILGen/back_deploy_attribute_accessor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public struct TopLevelStruct {
3636
// CHECK: return [[RETURN_BB_ARG]] : $TopLevelStruct
3737

3838
// -- Original definition of TopLevelStruct.property.getter
39-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV8propertyACvg : $@convention(method) (TopLevelStruct) -> TopLevelStruct
39+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV8propertyACvg : $@convention(method) (TopLevelStruct) -> TopLevelStruct
4040
@available(macOS 10.51, *)
4141
@_backDeploy(before: macOS 10.52)
4242
public var property: TopLevelStruct { self }

test/SILGen/back_deploy_attribute_func.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
// CHECK: return [[RESULT]] : $()
3737

3838
// -- Original definition of trivialFunc()
39-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy11trivialFuncyyF : $@convention(thin) () -> ()
39+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy11trivialFuncyyF : $@convention(thin) () -> ()
4040
@available(macOS 10.51, *)
4141
@_backDeploy(before: macOS 10.52)
4242
public func trivialFunc() {}
@@ -71,7 +71,7 @@ public func trivialFunc() {}
7171
// CHECK: return [[RETURN_BB_ARG]] : $Bool
7272

7373
// -- Original definition of isNumber(_:)
74-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy8isNumberySbSiF : $@convention(thin) (Int) -> Bool
74+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy8isNumberySbSiF : $@convention(thin) (Int) -> Bool
7575
@available(macOS 10.51, *)
7676
@_backDeploy(before: macOS 10.52)
7777
public func isNumber(_ x: Int) -> Bool {

test/SILGen/back_deploy_attribute_generic_func.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// CHECK: return [[RESULT]] : $()
3838

3939
// -- Original definition of genericFunc()
40-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy11genericFuncyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
40+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy11genericFuncyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
4141
@available(macOS 10.51, *)
4242
@_backDeploy(before: macOS 10.52)
4343
public func genericFunc<T>(_ t: T) -> T {

test/SILGen/back_deploy_attribute_struct_method.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public struct TopLevelStruct {
3838
// CHECK: return [[RESULT]] : $()
3939

4040
// -- Original definition of TopLevelStruct.trivialMethod()
41-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV13trivialMethodyyF : $@convention(method) (TopLevelStruct) -> ()
41+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV13trivialMethodyyF : $@convention(method) (TopLevelStruct) -> ()
4242
@available(macOS 10.51, *)
4343
@_backDeploy(before: macOS 10.52)
4444
public func trivialMethod() {}

test/SILGen/back_deploy_attribute_throwing_func.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
// CHECK: throw [[RETHROW_BB_ARG]] : $Error
5050

5151
// -- Original definition of throwingFunc()
52-
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error
52+
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error
5353
@available(macOS 10.51, *)
5454
@_backDeploy(before: macOS 10.52)
5555
public func throwingFunc() throws {}

test/attr/attr_backDeploy_evolution.swift

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232
// REQUIRES: executable_test
3333
// REQUIRES: VENDOR=apple
3434

35-
// rdar://90525337
36-
// UNSUPPORTED: swift_test_mode_optimize
37-
3835
// ---- (0) Prepare SDK
3936
// RUN: %empty-directory(%t)
4037
// RUN: %empty-directory(%t/SDK_ABI)
@@ -119,34 +116,34 @@ testPrint(handle: #dsohandle, "check")
119116
testPrint(handle: libraryHandle(), "check")
120117

121118
if isV2OrLater() {
122-
assert(!v2APIsAreStripped())
119+
precondition(!v2APIsAreStripped())
123120
}
124121

125122
// CHECK-ABI: library: trivial
126123
// CHECK-BD: client: trivial
127124
trivial()
128125

129-
assert(try! pleaseThrow(false))
126+
precondition(try! pleaseThrow(false))
130127
do {
131128
_ = try pleaseThrow(true)
132129
fatalError("Should have thrown")
133130
} catch {
134-
assert(error as? BadError == BadError.bad)
131+
precondition(error as? BadError == BadError.bad)
135132
}
136133

137134
do {
138135
let zero = MutableInt.zero
139-
assert(zero.value == 0)
136+
precondition(zero.value == 0)
140137

141138
var int = MutableInt(5)
142139

143140
// CHECK-ABI: library: 5
144141
// CHECK-BD: client: 5
145142
int.print()
146143

147-
assert(int.increment(by: 2) == 7)
148-
assert(genericIncrement(&int, by: 3) == 10)
149-
assert(int.decrement(by: 1) == 9)
144+
precondition(int.increment(by: 2) == 7)
145+
precondition(genericIncrement(&int, by: 3) == 10)
146+
precondition(int.decrement(by: 1) == 9)
150147

151148
var incrementable: any Incrementable = int.toIncrementable()
152149

@@ -156,13 +153,13 @@ do {
156153

157154
let int2 = MutableInt(0x7BB7914B)
158155
for (i, expectedByte) in [0x4B, 0x91, 0xB7, 0x7B].enumerated() {
159-
assert(int2[byteAt: i] == expectedByte)
156+
precondition(int2[byteAt: i] == expectedByte)
160157
}
161158
}
162159

163160
do {
164161
let zero = ReferenceInt.zero
165-
assert(zero.value == 0)
162+
precondition(zero.value == 0)
166163

167164
var int = ReferenceInt(42)
168165

@@ -172,13 +169,13 @@ do {
172169

173170
do {
174171
let copy = int.copy()
175-
assert(int !== copy)
176-
assert(copy.value == 42)
172+
precondition(int !== copy)
173+
precondition(copy.value == 42)
177174
}
178175

179-
assert(int.increment(by: 2) == 44)
180-
assert(genericIncrement(&int, by: 3) == 47)
181-
assert(int.decrement(by: 46) == 1)
176+
precondition(int.increment(by: 2) == 44)
177+
precondition(genericIncrement(&int, by: 3) == 47)
178+
precondition(int.decrement(by: 46) == 1)
182179

183180
var incrementable: any Incrementable = int.toIncrementable()
184181

@@ -188,6 +185,6 @@ do {
188185

189186
let int2 = MutableInt(0x08AFAB76)
190187
for (i, expectedByte) in [0x76, 0xAB, 0xAF, 0x08].enumerated() {
191-
assert(int2[byteAt: i] == expectedByte)
188+
precondition(int2[byteAt: i] == expectedByte)
192189
}
193190
}

0 commit comments

Comments
 (0)