mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
This commit is contained in:
@@ -1526,6 +1526,10 @@ public:
|
||||
/// The declared interface type of Builtin.TheTupleType.
|
||||
BuiltinTupleType *getBuiltinTupleType();
|
||||
|
||||
/// The declaration for the `_diagnoseUnavailableCodeReached()` declaration
|
||||
/// that ought to be used for the configured deployment target.
|
||||
FuncDecl *getDiagnoseUnavailableCodeReachedDecl();
|
||||
|
||||
Type getNamedSwiftType(ModuleDecl *module, StringRef name);
|
||||
|
||||
/// Set the plugin loader.
|
||||
|
||||
@@ -70,6 +70,7 @@ FUNC_DECL(DiagnoseUnexpectedNilOptional, "_diagnoseUnexpectedNilOptional")
|
||||
FUNC_DECL(DiagnoseUnexpectedEnumCase, "_diagnoseUnexpectedEnumCase")
|
||||
FUNC_DECL(DiagnoseUnexpectedEnumCaseValue, "_diagnoseUnexpectedEnumCaseValue")
|
||||
FUNC_DECL(DiagnoseUnavailableCodeReached, "_diagnoseUnavailableCodeReached")
|
||||
FUNC_DECL(DiagnoseUnavailableCodeReachedAEIC, "_diagnoseUnavailableCodeReached_aeic")
|
||||
|
||||
FUNC_DECL(GetErrorEmbeddedNSError, "_getErrorEmbeddedNSError")
|
||||
|
||||
|
||||
@@ -6312,6 +6312,14 @@ BuiltinTupleType *ASTContext::getBuiltinTupleType() {
|
||||
return result;
|
||||
}
|
||||
|
||||
FuncDecl *ASTContext::getDiagnoseUnavailableCodeReachedDecl() {
|
||||
// FIXME: Remove this with rdar://119892482
|
||||
if (AvailabilityContext::forDeploymentTarget(*this).isContainedIn(
|
||||
getSwift59Availability()))
|
||||
return getDiagnoseUnavailableCodeReached();
|
||||
return getDiagnoseUnavailableCodeReachedAEIC();
|
||||
}
|
||||
|
||||
void ASTContext::setPluginLoader(std::unique_ptr<PluginLoader> loader) {
|
||||
getImpl().Plugins = std::move(loader);
|
||||
}
|
||||
|
||||
@@ -6111,7 +6111,7 @@ void SILGenFunction::emitApplyOfUnavailableCodeReached() {
|
||||
return;
|
||||
|
||||
auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation());
|
||||
FuncDecl *fd = getASTContext().getDiagnoseUnavailableCodeReached();
|
||||
FuncDecl *fd = getASTContext().getDiagnoseUnavailableCodeReachedDecl();
|
||||
|
||||
if (!fd) {
|
||||
// Broken stdlib?
|
||||
|
||||
@@ -495,7 +495,7 @@ DerivedConformance::createBuiltinCall(ASTContext &ctx,
|
||||
|
||||
CallExpr *DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr(
|
||||
ASTContext &ctx) {
|
||||
FuncDecl *diagnoseDecl = ctx.getDiagnoseUnavailableCodeReached();
|
||||
FuncDecl *diagnoseDecl = ctx.getDiagnoseUnavailableCodeReachedDecl();
|
||||
auto diagnoseDeclRefExpr =
|
||||
new (ctx) DeclRefExpr(diagnoseDecl, DeclNameLoc(), true);
|
||||
diagnoseDeclRefExpr->setType(diagnoseDecl->getInterfaceType());
|
||||
|
||||
@@ -329,6 +329,17 @@ internal func _diagnoseUnexpectedEnumCase<SwitchedValue>(
|
||||
@_semantics("unavailable_code_reached")
|
||||
@usableFromInline // COMPILER_INTRINSIC
|
||||
internal func _diagnoseUnavailableCodeReached() -> Never {
|
||||
_diagnoseUnavailableCodeReached_aeic()
|
||||
}
|
||||
|
||||
// FIXME: Remove this with rdar://119892482
|
||||
/// An `@_alwaysEmitIntoClient` variant of `_diagnoseUnavailableCodeReached()`.
|
||||
/// This is temporarily needed by the compiler to reference from back deployed
|
||||
/// clients.
|
||||
@_alwaysEmitIntoClient
|
||||
@inline(never)
|
||||
@_semantics("unavailable_code_reached")
|
||||
internal func _diagnoseUnavailableCodeReached_aeic() -> Never {
|
||||
_assertionFailure(
|
||||
"Fatal error", "Unavailable code reached", flags: _fatalErrorFlags())
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ typedef MyOptions MyOptionsTypedef;
|
||||
let _ = MyOptionsTypedef(rawValue: 1)
|
||||
|
||||
// CHECK-LABEL: sil shared [transparent] [serialized]{{.*}} @$sSo9MyOptionsa8rawValueABs5Int32V_tcfC : $@convention(method) (Int32, @thin MyOptions.Type) -> MyOptions {
|
||||
// CHECK-NOT: ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb
|
||||
// CHECK-NOT: _diagnoseUnavailableCodeReached
|
||||
// CHECK: } // end sil function '$sSo9MyOptionsa8rawValueABs5Int32V_tcfC'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public struct S {}
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test15unavailableFuncAA1SVyF
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: function_ref @$s4Test1SVACycfC
|
||||
// CHECK: } // end sil function '$s4Test15unavailableFuncAA1SVyF'
|
||||
|
||||
@@ -7,7 +7,7 @@ func foo() {}
|
||||
public class ExplicitInitClass {
|
||||
// ExplicitInitClass.s.getter
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test17ExplicitInitClassC1sAA1SVvg
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: load
|
||||
// CHECK: } // end sil function '$s4Test17ExplicitInitClassC1sAA1SVvg'
|
||||
|
||||
@@ -10,7 +10,7 @@ func foo() {}
|
||||
@objc public class C: NSObject {
|
||||
// C.__allocating_init()
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test1CCACycfC
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: {{%.*}} = function_ref @$s4Test1CCACycfcTD
|
||||
// CHECK: } // end sil function '$s4Test1CCACycfC'
|
||||
|
||||
@@ -5,7 +5,7 @@ public struct S {}
|
||||
extension S: P {}
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test27unavailableOpaqueReturnFuncQryF
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: function_ref @$s4Test1SVACycfC
|
||||
// CHECK: } // end sil function '$s4Test27unavailableOpaqueReturnFuncQryF'
|
||||
|
||||
@@ -17,7 +17,7 @@ extension EnumWithProtocolWitness: P {}
|
||||
// protocol witness for static P.requirement(_:) in conformance EnumWithProtocolWitness
|
||||
//
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test23EnumWithProtocolWitnessOAA1PA2aDP11requirementyxAA1SVFZTW
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: {{%.*}} = function_ref @$s4Test23EnumWithProtocolWitnessO11requirementyAcA1SVcACmF
|
||||
// CHECK: } // end sil function '$s4Test23EnumWithProtocolWitnessOAA1PA2aDP11requirementyxAA1SVFZTW'
|
||||
|
||||
@@ -5,7 +5,7 @@ public struct S {}
|
||||
@available(*, unavailable)
|
||||
public struct ImplicitInitStruct {
|
||||
// CHECK-LABEL: sil hidden {{.*}} @$s4Test18ImplicitInitStructVACycfC
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK: return
|
||||
// CHECK: } // end sil function '$s4Test18ImplicitInitStructVACycfC'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public struct S {}
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}@$s4Test15unavailableFuncAA1SVyF
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:ss31_diagnoseUnavailableCodeReacheds5NeverOy(FTwb|F)]] : $@convention(thin) () -> Never
|
||||
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss36_diagnoseUnavailableCodeReached_aeics5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyF)]] : $@convention(thin) () -> Never
|
||||
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
|
||||
// CHECK-NEXT: unreachable
|
||||
// CHECK-NEXT: } // end sil function '$s4Test15unavailableFuncAA1SVyF'
|
||||
|
||||
@@ -106,14 +106,14 @@ enum HasUnavailableElement: Hashable {
|
||||
// CHECK-NEXT: case .a:
|
||||
// CHECK-NEXT: index_a = 0
|
||||
// CHECK-NEXT: case .b:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached{{.*}}()
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: private var index_b: Int
|
||||
// CHECK-NEXT: switch b {
|
||||
// CHECK-NEXT: case .a:
|
||||
// CHECK-NEXT: index_b = 0
|
||||
// CHECK-NEXT: case .b:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached{{.*}}()
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return index_a == index_b
|
||||
// CHECK-NEXT: }
|
||||
@@ -124,7 +124,7 @@ enum HasUnavailableElement: Hashable {
|
||||
// CHECK-NEXT: case .a:
|
||||
// CHECK-NEXT: discriminator = 0
|
||||
// CHECK-NEXT: case .b:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached{{.*}}()
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: hasher.combine(discriminator)
|
||||
// CHECK-NEXT: }
|
||||
@@ -151,7 +151,7 @@ enum HasAssociatedValuesAndUnavailableElement: Hashable {
|
||||
// CHECK-NEXT: hasher.combine(0)
|
||||
// CHECK-NEXT: hasher.combine(a0)
|
||||
// CHECK-NEXT: case .b:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached{{.*}}()
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@@ -163,7 +163,7 @@ enum HasAssociatedValuesAndUnavailableElement: Hashable {
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return true
|
||||
// CHECK-NEXT: case (.b, .b):
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached{{.*}}()
|
||||
// CHECK-NEXT: default:
|
||||
// CHECK-NEXT: return false
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.51 -print-ast %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-PRE-SWIFT5_9
|
||||
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.51 -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-PRE-SWIFT5_9
|
||||
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx14 -print-ast %s | %FileCheck %s --check-prefixes=CHECK,CHECK-SWIFT5_9
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
// CHECK-LABEL: internal enum HasElementsWithAvailability : Hashable
|
||||
@@ -29,9 +30,11 @@ enum HasElementsWithAvailability: Hashable {
|
||||
// CHECK-NEXT: case .alwaysAvailable:
|
||||
// CHECK-NEXT: index_a = 0
|
||||
// CHECK-NEXT: case .neverAvailable:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .unavailableMacOS:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .obsoleted10_50:
|
||||
// CHECK-NEXT: index_a = 1
|
||||
// CHECK-NEXT: case .introduced10_50:
|
||||
@@ -42,9 +45,11 @@ enum HasElementsWithAvailability: Hashable {
|
||||
// CHECK-NEXT: case .alwaysAvailable:
|
||||
// CHECK-NEXT: index_b = 0
|
||||
// CHECK-NEXT: case .neverAvailable:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .unavailableMacOS:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .obsoleted10_50:
|
||||
// CHECK-NEXT: index_b = 1
|
||||
// CHECK-NEXT: case .introduced10_50:
|
||||
@@ -59,9 +64,11 @@ enum HasElementsWithAvailability: Hashable {
|
||||
// CHECK-NEXT: case .alwaysAvailable:
|
||||
// CHECK-NEXT: discriminator = 0
|
||||
// CHECK-NEXT: case .neverAvailable:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .unavailableMacOS:
|
||||
// CHECK-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-PRE-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached_aeic()
|
||||
// CHECK-SWIFT5_9-NEXT: _diagnoseUnavailableCodeReached()
|
||||
// CHECK-NEXT: case .obsoleted10_50:
|
||||
// CHECK-NEXT: discriminator = 1
|
||||
// CHECK-NEXT: case .introduced10_50:
|
||||
|
||||
Reference in New Issue
Block a user