Skip to content

SIL: Avoid serializing the bodies of the original copies of @_backDeploy functions #41961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ struct SILDeclRef {
bool isNoinline() const;
/// True if the function has __always inline attribute.
bool isAlwaysInline() const;
/// True if the function has the @_backDeploy attribute.
bool isBackDeployed() const;

/// Return the expected linkage of this declaration.
SILLinkage getLinkage(ForDefinition_t forDefinition) const;
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/SILLinkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ enum IsSerialized_t : unsigned char {
///
/// This flag is only valid for Public, PublicNonABI, PublicExternal,
/// HiddenExternal and Shared functions.
/// Functions with external linkage (PublicExternl, HiddenExternal) will not
/// Functions with external linkage (PublicExternal, HiddenExternal) will not
/// be serialized, because they are available in a different module (from which
/// they were de-serialized).
///
Expand Down
24 changes: 24 additions & 0 deletions lib/SIL/IR/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,19 @@ IsSerialized_t SILDeclRef::isSerialized() const {
if (isClangImported())
return IsSerialized;

// Handle back deployed functions. The original back deployed function
// should not be serialized, but the thunk and fallback should be since they
// need to be emitted into the client.
if (isBackDeployed()) {
switch (backDeploymentKind) {
case BackDeploymentKind::None:
return IsNotSerialized;
case BackDeploymentKind::Fallback:
case BackDeploymentKind::Thunk:
return IsSerialized;
}
}

// Otherwise, ask the AST if we're inside an @inlinable context.
if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal)
return IsSerialized;
Expand Down Expand Up @@ -736,6 +749,17 @@ bool SILDeclRef::isAlwaysInline() const {
return false;
}

bool SILDeclRef::isBackDeployed() const {
if (!hasDecl())
return false;

auto *decl = getDecl();
if (auto afd = dyn_cast<AbstractFunctionDecl>(decl))
return afd->isBackDeployed();

return false;
}

bool SILDeclRef::isAnyThunk() const {
return isForeignToNativeThunk() || isNativeToForeignThunk() ||
isDistributedThunk() || isBackDeploymentThunk();
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/back_deploy_attribute_accessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct TopLevelStruct {
// CHECK: return [[RETURN_BB_ARG]] : $TopLevelStruct

// -- Original definition of TopLevelStruct.property.getter
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV8propertyACvg : $@convention(method) (TopLevelStruct) -> TopLevelStruct
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV8propertyACvg : $@convention(method) (TopLevelStruct) -> TopLevelStruct
@available(macOS 10.51, *)
@_backDeploy(before: macOS 10.52)
public var property: TopLevelStruct { self }
Expand Down
4 changes: 2 additions & 2 deletions test/SILGen/back_deploy_attribute_func.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
// CHECK: return [[RESULT]] : $()

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

// -- Original definition of isNumber(_:)
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy8isNumberySbSiF : $@convention(thin) (Int) -> Bool
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy8isNumberySbSiF : $@convention(thin) (Int) -> Bool
@available(macOS 10.51, *)
@_backDeploy(before: macOS 10.52)
public func isNumber(_ x: Int) -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/back_deploy_attribute_generic_func.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
// CHECK: return [[RESULT]] : $()

// -- Original definition of genericFunc()
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy11genericFuncyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy11genericFuncyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
@available(macOS 10.51, *)
@_backDeploy(before: macOS 10.52)
public func genericFunc<T>(_ t: T) -> T {
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/back_deploy_attribute_struct_method.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public struct TopLevelStruct {
// CHECK: return [[RESULT]] : $()

// -- Original definition of TopLevelStruct.trivialMethod()
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV13trivialMethodyyF : $@convention(method) (TopLevelStruct) -> ()
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy14TopLevelStructV13trivialMethodyyF : $@convention(method) (TopLevelStruct) -> ()
@available(macOS 10.51, *)
@_backDeploy(before: macOS 10.52)
public func trivialMethod() {}
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/back_deploy_attribute_throwing_func.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
// CHECK: throw [[RETHROW_BB_ARG]] : $Error

// -- Original definition of throwingFunc()
// CHECK-LABEL: sil [serialized] [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error
// CHECK-LABEL: sil [available 10.51] [ossa] @$s11back_deploy12throwingFuncyyKF : $@convention(thin) () -> @error Error
@available(macOS 10.51, *)
@_backDeploy(before: macOS 10.52)
public func throwingFunc() throws {}
Expand Down
33 changes: 15 additions & 18 deletions test/attr/attr_backDeploy_evolution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@
// REQUIRES: executable_test
// REQUIRES: VENDOR=apple

// rdar://90525337
// UNSUPPORTED: swift_test_mode_optimize

// ---- (0) Prepare SDK
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/SDK_ABI)
Expand Down Expand Up @@ -119,34 +116,34 @@ testPrint(handle: #dsohandle, "check")
testPrint(handle: libraryHandle(), "check")

if isV2OrLater() {
assert(!v2APIsAreStripped())
precondition(!v2APIsAreStripped())
}

// CHECK-ABI: library: trivial
// CHECK-BD: client: trivial
trivial()

assert(try! pleaseThrow(false))
precondition(try! pleaseThrow(false))
do {
_ = try pleaseThrow(true)
fatalError("Should have thrown")
} catch {
assert(error as? BadError == BadError.bad)
precondition(error as? BadError == BadError.bad)
}

do {
let zero = MutableInt.zero
assert(zero.value == 0)
precondition(zero.value == 0)

var int = MutableInt(5)

// CHECK-ABI: library: 5
// CHECK-BD: client: 5
int.print()

assert(int.increment(by: 2) == 7)
assert(genericIncrement(&int, by: 3) == 10)
assert(int.decrement(by: 1) == 9)
precondition(int.increment(by: 2) == 7)
precondition(genericIncrement(&int, by: 3) == 10)
precondition(int.decrement(by: 1) == 9)

var incrementable: any Incrementable = int.toIncrementable()

Expand All @@ -156,13 +153,13 @@ do {

let int2 = MutableInt(0x7BB7914B)
for (i, expectedByte) in [0x4B, 0x91, 0xB7, 0x7B].enumerated() {
assert(int2[byteAt: i] == expectedByte)
precondition(int2[byteAt: i] == expectedByte)
}
}

do {
let zero = ReferenceInt.zero
assert(zero.value == 0)
precondition(zero.value == 0)

var int = ReferenceInt(42)

Expand All @@ -172,13 +169,13 @@ do {

do {
let copy = int.copy()
assert(int !== copy)
assert(copy.value == 42)
precondition(int !== copy)
precondition(copy.value == 42)
}

assert(int.increment(by: 2) == 44)
assert(genericIncrement(&int, by: 3) == 47)
assert(int.decrement(by: 46) == 1)
precondition(int.increment(by: 2) == 44)
precondition(genericIncrement(&int, by: 3) == 47)
precondition(int.decrement(by: 46) == 1)

var incrementable: any Incrementable = int.toIncrementable()

Expand All @@ -188,6 +185,6 @@ do {

let int2 = MutableInt(0x08AFAB76)
for (i, expectedByte) in [0x76, 0xAB, 0xAF, 0x08].enumerated() {
assert(int2[byteAt: i] == expectedByte)
precondition(int2[byteAt: i] == expectedByte)
}
}