Skip to content

Commit d9e028f

Browse files
authored
Merge pull request #64353 from tshortli/weak-link-unavailable-symbols
IRGen: Weakly link symbols for unavailable declarations
2 parents 1600c14 + 084ef39 commit d9e028f

File tree

4 files changed

+109
-8
lines changed

4 files changed

+109
-8
lines changed

lib/AST/Decl.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,14 @@ bool Decl::isAlwaysWeakImported() const {
11261126
if (getAttrs().hasAttribute<WeakLinkedAttr>())
11271127
return true;
11281128

1129+
// Declarations that are unavailable should be weak linked since they are
1130+
// meant to be unreachable at runtime and their removal should not affect
1131+
// clients. However, make an exception for unavailable declarations with
1132+
// explicit introduction versions, which are considered required ABI.
1133+
if (getSemanticUnavailableAttr() &&
1134+
getAvailabilityForLinkage().isAlwaysAvailable())
1135+
return true;
1136+
11291137
if (auto *accessor = dyn_cast<AccessorDecl>(this))
11301138
return accessor->getStorage()->isAlwaysWeakImported();
11311139

Original file line numberDiff line numberDiff line change
@@ -1,27 +1,55 @@
11
@available(macOS 10.50, *)
22
public func conditionallyAvailableFunction() {}
33

4+
@available(macOS, unavailable)
5+
public func unavailableFunction() {}
6+
7+
@available(macOS 10.50, *)
8+
@available(macOS, unavailable)
9+
public func unavailableButIntroducedFunction() {}
10+
411
@available(macOS 10.50, *)
512
public var conditionallyAvailableGlobal: Int {
613
get {return 0}
714
set {}
815
}
916

17+
@available(macOS, unavailable)
18+
public var unavailableGlobal: Int {
19+
get {return 0}
20+
set {}
21+
}
22+
1023
@available(macOS 10.50, *)
1124
public struct ConditionallyAvailableStruct {
1225
public func conditionallyAvailableMethod() {}
1326
}
1427

28+
extension ConditionallyAvailableStruct {
29+
public struct NestedStruct {}
30+
}
31+
32+
@available(macOS, unavailable)
33+
public struct UnvailableStruct {
34+
public func unavailableMethod() {}
35+
}
36+
1537
public protocol AlwaysAvailableProtocol {}
1638

1739
public struct AlwaysAvailableStruct {}
1840

1941
@available(macOS 10.50, *)
2042
extension AlwaysAvailableStruct : AlwaysAvailableProtocol {}
2143

44+
@available(macOS, unavailable)
45+
public protocol UnavailableProtocol {}
46+
47+
@available(macOS, unavailable)
48+
extension AlwaysAvailableStruct : UnavailableProtocol {}
49+
2250
public enum AlwaysAvailableEnum {
2351
case alwaysAvailableCase
2452

2553
@available(macOS 10.50, *)
2654
case conditionallyAvailableCase
27-
}
55+
}

test/IRGen/weak_import_availability.swift

+70-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/weak_import_availability_helper.swiftmodule -parse-as-library %S/Inputs/weak_import_availability_helper.swift -enable-library-evolution
2+
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.50 -emit-module -emit-module-path %t/weak_import_availability_helper.swiftmodule -parse-as-library %S/Inputs/weak_import_availability_helper.swift -enable-library-evolution
33
//
4-
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir | %FileCheck %s --check-prefix=CHECK-OLD
5-
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.50 | %FileCheck %s --check-prefix=CHECK-NEW
6-
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.60 | %FileCheck %s --check-prefix=CHECK-NEW
4+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-OLD
5+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.50 | %FileCheck %s --check-prefixes=CHECK,CHECK-NEW
6+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.60 | %FileCheck %s --check-prefixes=CHECK,CHECK-NEW
77

8-
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.50 -weak-link-at-target | %FileCheck %s --check-prefix=CHECK-OLD
9-
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.60 -weak-link-at-target | %FileCheck %s --check-prefix=CHECK-NEW
8+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.50 -weak-link-at-target | %FileCheck %s --check-prefixes=CHECK,CHECK-OLD
9+
// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir -target %target-cpu-apple-macosx10.60 -weak-link-at-target | %FileCheck %s --check-prefixes=CHECK,CHECK-NEW
1010

1111
// REQUIRES: OS=macosx
1212

@@ -35,6 +35,16 @@ public func useConditionallyAvailableConformance() {
3535
// CHECK-OLD-LABEL: @"$s31weak_import_availability_helper21AlwaysAvailableStructVAA0eF8ProtocolAAWP" = extern_weak global i8*
3636
// CHECK-NEW-LABEL: @"$s31weak_import_availability_helper21AlwaysAvailableStructVAA0eF8ProtocolAAWP" = external global i8*
3737

38+
@available(macOS, unavailable)
39+
func useUnavailableConformance<T : UnavailableProtocol>(_: T.Type) {}
40+
41+
@available(macOS, unavailable)
42+
public func useUnavailableConformance() {
43+
useUnavailableConformance(AlwaysAvailableStruct.self)
44+
}
45+
46+
// CHECK-LABEL: @"$s31weak_import_availability_helper21AlwaysAvailableStructVAA19UnavailableProtocolAAWP" = extern_weak global i8*, align 8
47+
3848
@available(macOS 10.50, *)
3949
public func callConditionallyAvailableFunction() {
4050
conditionallyAvailableFunction()
@@ -43,6 +53,21 @@ public func callConditionallyAvailableFunction() {
4353
// CHECK-OLD-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper30conditionallyAvailableFunctionyyF"()
4454
// CHECK-NEW-LABEL: declare swiftcc void @"$s31weak_import_availability_helper30conditionallyAvailableFunctionyyF"()
4555

56+
@available(macOS, unavailable)
57+
public func callUnavailableFunction() {
58+
unavailableFunction()
59+
}
60+
61+
// CHECK-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper19unavailableFunctionyyF"()
62+
63+
@available(macOS, unavailable)
64+
public func callUnavailableButIntroducedFunction() {
65+
unavailableButIntroducedFunction()
66+
}
67+
68+
// CHECK-OLD-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper32unavailableButIntroducedFunctionyyF"()
69+
// CHECK-NEW-LABEL: declare swiftcc void @"$s31weak_import_availability_helper32unavailableButIntroducedFunctionyyF"()
70+
4671
@available(macOS 10.50, *)
4772
public func useConditionallyAvailableGlobal() {
4873
_ = conditionallyAvailableGlobal
@@ -56,17 +81,56 @@ public func useConditionallyAvailableGlobal() {
5681
// CHECK-OLD-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper28conditionallyAvailableGlobalSivs"(i64)
5782
// CHECK-NEW-LABEL: declare swiftcc void @"$s31weak_import_availability_helper28conditionallyAvailableGlobalSivs"(i64)
5883

84+
// CHECK-OLD-LABEL: declare extern_weak swiftcc { i8*, %TSi* } @"$s31weak_import_availability_helper28conditionallyAvailableGlobalSivM"(i8* noalias dereferenceable(32))
85+
// CHECK-NEW-LABEL: declare swiftcc { i8*, %TSi* } @"$s31weak_import_availability_helper28conditionallyAvailableGlobalSivM"(i8* noalias dereferenceable(32))
86+
87+
@available(macOS, unavailable)
88+
public func useUnavailableGlobal() {
89+
_ = unavailableGlobal
90+
unavailableGlobal = 0
91+
unavailableGlobal += 1
92+
}
93+
94+
// CHECK-LABEL: declare extern_weak swiftcc i64 @"$s31weak_import_availability_helper17unavailableGlobalSivg"()
95+
// CHECK-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper17unavailableGlobalSivs"(i64)
96+
// CHECK-LABEL: declare extern_weak swiftcc { i8*, %TSi* } @"$s31weak_import_availability_helper17unavailableGlobalSivM"(i8* noalias dereferenceable(32))
97+
5998
func blackHole<T>(_: T) {}
6099

61100
@available(macOS 10.50, *)
62101
public func useConditionallyAvailableStruct() {
63102
blackHole(ConditionallyAvailableStruct.self)
64103
}
65104

105+
// CHECK-OLD-LABEL: declare extern_weak swiftcc %swift.metadata_response @"$s31weak_import_availability_helper28ConditionallyAvailableStructVMa"(i64)
106+
// CHECK-NEW-LABEL: declare swiftcc %swift.metadata_response @"$s31weak_import_availability_helper28ConditionallyAvailableStructVMa"(i64)
107+
108+
@available(macOS 10.50, *)
109+
public func useNestedConditionallyAvailableStruct() {
110+
blackHole(ConditionallyAvailableStruct.NestedStruct.self)
111+
}
112+
113+
// CHECK-OLD-LABEL: declare extern_weak swiftcc %swift.metadata_response @"$s31weak_import_availability_helper28ConditionallyAvailableStructV06NestedG0VMa"(i64)
114+
// CHECK-NEW-LABEL: declare swiftcc %swift.metadata_response @"$s31weak_import_availability_helper28ConditionallyAvailableStructV06NestedG0VMa"(i64)
115+
66116
@available(macOS 10.50, *)
67117
public func useConditionallyAvailableMethod(s: ConditionallyAvailableStruct) {
68118
s.conditionallyAvailableMethod()
69119
}
70120

71121
// CHECK-OLD-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper28ConditionallyAvailableStructV013conditionallyF6MethodyyF"(%swift.opaque* noalias nocapture swiftself)
72122
// CHECK-NEW-LABEL: declare swiftcc void @"$s31weak_import_availability_helper28ConditionallyAvailableStructV013conditionallyF6MethodyyF"(%swift.opaque* noalias nocapture swiftself)
123+
124+
@available(macOS, unavailable)
125+
public func useUnavailableStruct() {
126+
blackHole(UnvailableStruct.self)
127+
}
128+
129+
// CHECK-LABEL: declare extern_weak swiftcc %swift.metadata_response @"$s31weak_import_availability_helper16UnvailableStructVMa"(i64)
130+
131+
@available(macOS, unavailable)
132+
public func useUnavailableMethod(s: UnvailableStruct) {
133+
s.unavailableMethod()
134+
}
135+
136+
// CHECK-LABEL: declare extern_weak swiftcc void @"$s31weak_import_availability_helper16UnvailableStructV17unavailableMethodyyF"(%swift.opaque* noalias nocapture swiftself)

test/SILGen/objc_init_unavailable.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -enable-objc-interop -import-objc-header %S/Inputs/objc_init_unavailable.h %s | %FileCheck %s
22
// REQUIRES: objc_interop
3+
// REQUIRES: OS=macosx
34

45
@available(macOS, unavailable)
56
public func callUnavailableInit(name: String) -> ClassWithUnavailableInit {
67
return ClassWithUnavailableInit(bundleID: name)
78
}
89

9-
// CHECK-LABEL: sil [ossa] @$s21objc_init_unavailable19callUnavailableInit4nameSo09ClassWitheF0CSS_tF : $@convention(thin) (@guaranteed String) -> @owned ClassWithUnavailableInit {
10+
// CHECK-LABEL: sil [weak_imported] [ossa] @$s21objc_init_unavailable19callUnavailableInit4nameSo09ClassWitheF0CSS_tF : $@convention(thin) (@guaranteed String) -> @owned ClassWithUnavailableInit {
1011
// CHECK: function_ref @$sSo24ClassWithUnavailableInitC8bundleIDABSgSSSg_tcfC : $@convention(method) (@owned Optional<String>, @thick ClassWithUnavailableInit.Type) -> @owned Optional<ClassWithUnavailableInit>
1112
// CHECK: return
1213

0 commit comments

Comments
 (0)