Skip to content

Commit 77aaa35

Browse files
committed
AST/SILGen: Use @_alwaysEmitIntoClient diagnostic helper in unavailable code.
The `_diagnoseUnavailableCodeReached()` function was introduced in the Swift 5.9 standard library and employs `@backDeployed` to support compilation of binaries that target OS releases aligned with earlier Swift releases. Unfortunately, though, this backdeployment strategy doesn't work well for some unusual build environments. Specifically, in some configurations code may be built with a compiler from a recent Swift toolchain and then linked against the dylibs in an older toolchain. When linking against the older dylibs, the `_diagnoseUnavailableCodeReached()` function does not exist but the `@backDeployed` thunks emitted into the binary reference that function and therefore linking fails. The idea of building with one toolchain and then linking to the dylibs in a different, older toolchain is extremely dubious. However, it exists and for now we need to support it. This PR introduces an alternative `_diagnoseUnavailableCodeReached()` function that is annotated with `@_alwaysEmitIntoClient`. Calls to the AEIC variant are now emitted by the compiler when the deployment target is before Swift 5.9. Once these unusual build environments upgrade and start linking against a Swift 5.9 toolchain or later we can revert all of this. Resolves rdar://119046537
1 parent f6dba90 commit 77aaa35

16 files changed

+55
-23
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,10 @@ class ASTContext final {
15261526
/// The declared interface type of Builtin.TheTupleType.
15271527
BuiltinTupleType *getBuiltinTupleType();
15281528

1529+
/// The declaration for the `_diagnoseUnavailableCodeReached()` declaration
1530+
/// that ought to be used for the configured deployment target.
1531+
FuncDecl *getDiagnoseUnavailableCodeReachedDecl();
1532+
15291533
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
15301534

15311535
/// Set the plugin loader.

include/swift/AST/KnownDecls.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ FUNC_DECL(DiagnoseUnexpectedNilOptional, "_diagnoseUnexpectedNilOptional")
7070
FUNC_DECL(DiagnoseUnexpectedEnumCase, "_diagnoseUnexpectedEnumCase")
7171
FUNC_DECL(DiagnoseUnexpectedEnumCaseValue, "_diagnoseUnexpectedEnumCaseValue")
7272
FUNC_DECL(DiagnoseUnavailableCodeReached, "_diagnoseUnavailableCodeReached")
73+
FUNC_DECL(DiagnoseUnavailableCodeReachedAEIC, "_diagnoseUnavailableCodeReached_aeic")
7374

7475
FUNC_DECL(GetErrorEmbeddedNSError, "_getErrorEmbeddedNSError")
7576

lib/AST/ASTContext.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6312,6 +6312,14 @@ BuiltinTupleType *ASTContext::getBuiltinTupleType() {
63126312
return result;
63136313
}
63146314

6315+
FuncDecl *ASTContext::getDiagnoseUnavailableCodeReachedDecl() {
6316+
// FIXME: Remove this with rdar://119892482
6317+
if (AvailabilityContext::forDeploymentTarget(*this).isContainedIn(
6318+
getSwift59Availability()))
6319+
return getDiagnoseUnavailableCodeReached();
6320+
return getDiagnoseUnavailableCodeReachedAEIC();
6321+
}
6322+
63156323
void ASTContext::setPluginLoader(std::unique_ptr<PluginLoader> loader) {
63166324
getImpl().Plugins = std::move(loader);
63176325
}

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6111,7 +6111,7 @@ void SILGenFunction::emitApplyOfUnavailableCodeReached() {
61116111
return;
61126112

61136113
auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation());
6114-
FuncDecl *fd = getASTContext().getDiagnoseUnavailableCodeReached();
6114+
FuncDecl *fd = getASTContext().getDiagnoseUnavailableCodeReachedDecl();
61156115

61166116
if (!fd) {
61176117
// Broken stdlib?

lib/Sema/DerivedConformances.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ DerivedConformance::createBuiltinCall(ASTContext &ctx,
495495

496496
CallExpr *DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr(
497497
ASTContext &ctx) {
498-
FuncDecl *diagnoseDecl = ctx.getDiagnoseUnavailableCodeReached();
498+
FuncDecl *diagnoseDecl = ctx.getDiagnoseUnavailableCodeReachedDecl();
499499
auto diagnoseDeclRefExpr =
500500
new (ctx) DeclRefExpr(diagnoseDecl, DeclNameLoc(), true);
501501
diagnoseDeclRefExpr->setType(diagnoseDecl->getInterfaceType());

stdlib/public/core/AssertCommon.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,18 @@ internal func _diagnoseUnexpectedEnumCase<SwitchedValue>(
329329
@_semantics("unavailable_code_reached")
330330
@usableFromInline // COMPILER_INTRINSIC
331331
internal func _diagnoseUnavailableCodeReached() -> Never {
332+
_diagnoseUnavailableCodeReached_aeic()
333+
}
334+
335+
// FIXME: Remove this with rdar://119892482
336+
/// An `@_alwaysEmitIntoClient` variant of `_diagnoseUnavailableCodeReached()`.
337+
/// This is temporarily needed by the compiler to reference from back deployed
338+
/// clients.
339+
@_alwaysEmitIntoClient
340+
@inline(never)
341+
@_semantics("unavailable_code_reached")
342+
@usableFromInline // COMPILER_INTRINSIC
343+
internal func _diagnoseUnavailableCodeReached_aeic() -> Never {
332344
_assertionFailure(
333345
"Fatal error", "Unavailable code reached", flags: _fatalErrorFlags())
334346
}

test/SILGen/unavailable_clang_enum_typedef.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ typedef MyOptions MyOptionsTypedef;
1919
let _ = MyOptionsTypedef(rawValue: 1)
2020

2121
// CHECK-LABEL: sil shared [transparent] [serialized]{{.*}} @$sSo9MyOptionsa8rawValueABs5Int32V_tcfC : $@convention(method) (Int32, @thin MyOptions.Type) -> MyOptions {
22-
// CHECK-NOT: ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb
22+
// CHECK-NOT: _diagnoseUnavailableCodeReached
2323
// CHECK: } // end sil function '$sSo9MyOptionsa8rawValueABs5Int32V_tcfC'

test/SILGen/unavailable_decl_optimization_stub.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public struct S {}
44

55
// CHECK-LABEL: sil{{.*}}@$s4Test15unavailableFuncAA1SVyF
6-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
6+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
77
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
88
// CHECK: function_ref @$s4Test1SVACycfC
99
// CHECK: } // end sil function '$s4Test15unavailableFuncAA1SVyF'

test/SILGen/unavailable_decl_optimization_stub_class.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ func foo() {}
77
public class ExplicitInitClass {
88
// ExplicitInitClass.s.getter
99
// CHECK-LABEL: sil{{.*}}@$s4Test17ExplicitInitClassC1sAA1SVvg
10-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
10+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
1111
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
1212
// CHECK: load
1313
// CHECK: } // end sil function '$s4Test17ExplicitInitClassC1sAA1SVvg'

test/SILGen/unavailable_decl_optimization_stub_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ func foo() {}
1010
@objc public class C: NSObject {
1111
// C.__allocating_init()
1212
// CHECK-LABEL: sil{{.*}}@$s4Test1CCACycfC
13-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
13+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
1414
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
1515
// CHECK: {{%.*}} = function_ref @$s4Test1CCACycfcTD
1616
// CHECK: } // end sil function '$s4Test1CCACycfC'

test/SILGen/unavailable_decl_optimization_stub_opaque_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public struct S {}
55
extension S: P {}
66

77
// CHECK-LABEL: sil{{.*}}@$s4Test27unavailableOpaqueReturnFuncQryF
8-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
8+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
99
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
1010
// CHECK: function_ref @$s4Test1SVACycfC
1111
// CHECK: } // end sil function '$s4Test27unavailableOpaqueReturnFuncQryF'

test/SILGen/unavailable_decl_optimization_stub_protocol_witness.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extension EnumWithProtocolWitness: P {}
1717
// protocol witness for static P.requirement(_:) in conformance EnumWithProtocolWitness
1818
//
1919
// CHECK-LABEL: sil{{.*}}@$s4Test23EnumWithProtocolWitnessOAA1PA2aDP11requirementyxAA1SVFZTW
20-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
20+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
2121
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
2222
// CHECK: {{%.*}} = function_ref @$s4Test23EnumWithProtocolWitnessO11requirementyAcA1SVcACmF
2323
// CHECK: } // end sil function '$s4Test23EnumWithProtocolWitnessOAA1PA2aDP11requirementyxAA1SVFZTW'

test/SILGen/unavailable_decl_optimization_stub_struct.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public struct S {}
55
@available(*, unavailable)
66
public struct ImplicitInitStruct {
77
// CHECK-LABEL: sil hidden {{.*}} @$s4Test18ImplicitInitStructVACycfC
8-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
8+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
99
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
1010
// CHECK: return
1111
// CHECK: } // end sil function '$s4Test18ImplicitInitStructVACycfC'

test/SILOptimizer/unavailable_decl_optimization_stub.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public struct S {}
44

55
// CHECK-LABEL: sil{{.*}}@$s4Test15unavailableFuncAA1SVyF
6-
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
6+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
77
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
88
// CHECK-NEXT: unreachable
99
// CHECK-NEXT: } // end sil function '$s4Test15unavailableFuncAA1SVyF'

test/decl/enum/derived_hashable_equatable.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ enum HasUnavailableElement: Hashable {
106106
// CHECK-NEXT: case .a:
107107
// CHECK-NEXT: index_a = 0
108108
// CHECK-NEXT: case .b:
109-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
109+
// CHECK-NEXT: _diagnoseUnavailableCodeReached_aeic()
110110
// CHECK-NEXT: }
111111
// CHECK-NEXT: private var index_b: Int
112112
// CHECK-NEXT: switch b {
113113
// CHECK-NEXT: case .a:
114114
// CHECK-NEXT: index_b = 0
115115
// CHECK-NEXT: case .b:
116-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
116+
// CHECK-NEXT: _diagnoseUnavailableCodeReached_aeic()
117117
// CHECK-NEXT: }
118118
// CHECK-NEXT: return index_a == index_b
119119
// CHECK-NEXT: }
@@ -124,7 +124,7 @@ enum HasUnavailableElement: Hashable {
124124
// CHECK-NEXT: case .a:
125125
// CHECK-NEXT: discriminator = 0
126126
// CHECK-NEXT: case .b:
127-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
127+
// CHECK-NEXT: _diagnoseUnavailableCodeReached_aeic()
128128
// CHECK-NEXT: }
129129
// CHECK-NEXT: hasher.combine(discriminator)
130130
// CHECK-NEXT: }
@@ -151,7 +151,7 @@ enum HasAssociatedValuesAndUnavailableElement: Hashable {
151151
// CHECK-NEXT: hasher.combine(0)
152152
// CHECK-NEXT: hasher.combine(a0)
153153
// CHECK-NEXT: case .b:
154-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
154+
// CHECK-NEXT: _diagnoseUnavailableCodeReached_aeic()
155155
// CHECK-NEXT: }
156156
// CHECK-NEXT: }
157157

@@ -163,7 +163,7 @@ enum HasAssociatedValuesAndUnavailableElement: Hashable {
163163
// CHECK-NEXT: }
164164
// CHECK-NEXT: return true
165165
// CHECK-NEXT: case (.b, .b):
166-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
166+
// CHECK-NEXT: _diagnoseUnavailableCodeReached_aeic()
167167
// CHECK-NEXT: default:
168168
// CHECK-NEXT: return false
169169
// CHECK-NEXT: }

test/decl/enum/derived_hashable_equatable_macos.swift

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s
2-
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.51 -print-ast %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-PRE-SWIFT5_9
2+
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.51 -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-PRE-SWIFT5_9
3+
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx14 -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_9
34
// REQUIRES: OS=macosx
45

56
// CHECK-LABEL: internal enum HasElementsWithAvailability : Hashable
@@ -29,9 +30,11 @@ enum HasElementsWithAvailability: Hashable {
2930
// CHECK-NEXT: case .alwaysAvailable:
3031
// CHECK-NEXT: index_a = 0
3132
// CHECK-NEXT: case .neverAvailable:
32-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
33+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
34+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
3335
// CHECK-NEXT: case .unavailableMacOS:
34-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
36+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
37+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
3538
// CHECK-NEXT: case .obsoleted10_50:
3639
// CHECK-NEXT: index_a = 1
3740
// CHECK-NEXT: case .introduced10_50:
@@ -42,9 +45,11 @@ enum HasElementsWithAvailability: Hashable {
4245
// CHECK-NEXT: case .alwaysAvailable:
4346
// CHECK-NEXT: index_b = 0
4447
// CHECK-NEXT: case .neverAvailable:
45-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
48+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
49+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
4650
// CHECK-NEXT: case .unavailableMacOS:
47-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
51+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
52+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
4853
// CHECK-NEXT: case .obsoleted10_50:
4954
// CHECK-NEXT: index_b = 1
5055
// CHECK-NEXT: case .introduced10_50:
@@ -59,9 +64,11 @@ enum HasElementsWithAvailability: Hashable {
5964
// CHECK-NEXT: case .alwaysAvailable:
6065
// CHECK-NEXT: discriminator = 0
6166
// CHECK-NEXT: case .neverAvailable:
62-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
67+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
68+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
6369
// CHECK-NEXT: case .unavailableMacOS:
64-
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
70+
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
71+
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
6572
// CHECK-NEXT: case .obsoleted10_50:
6673
// CHECK-NEXT: discriminator = 1
6774
// CHECK-NEXT: case .introduced10_50:

0 commit comments

Comments
 (0)