From 81dc98b0c852a68ec5f8b043032b2ea4397bc773 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Jul 2025 14:08:16 -0700 Subject: [PATCH 1/3] [IRGen] Don't use mangled names for metadata including Span et al when back-deploying If back-deploying prior to the introduction of name mangling and runtime support for invertible constraints (~Copyable, ~Escapable), don't use mangled names to access metadata. The code already existed for this, but had a carve-out that still used mangled names for standard library types that have always existed but got generalized to support non-copyable & non-escapable types. Tweak that carve-out to not apply to types like Span that come from a back-deployment library. Fixes crashes when using metadata for Span et al on older platforms. Fixes rdar://155639204. --- lib/IRGen/GenReflection.cpp | 27 +++++++++++++++++++++++---- test/IRGen/backward_deploy_span.swift | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 test/IRGen/backward_deploy_span.swift diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 11e24f0f6c44..af33a7da89ef 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -177,6 +177,25 @@ class PrintMetadataSource } }; +/// Determine whether the given generic nominal that involves inverse +/// requirements (e.g., Optional, Span) is always available for demangling +/// purposes. +static bool nominalIsAlwaysAvailableForDemangling(const NominalTypeDecl *nom) { + // Only consider standard library types for this. + if (!nom->getModuleContext()->isStdlibModule()) + return false; + + // If there's an @_originallyDefined(in:) attribute, then the nominal is + // not always available for demangling. + for (auto attr: nom->getAttrs().getAttributes()) { + if (!attr->isInvalid() && attr->isActivePlatform(nom->getASTContext())) + return false; + } + + // Everything else is available. + return true; +} + std::optional getRuntimeVersionThatSupportsDemanglingType(CanType type) { enum VersionRequirement { @@ -246,16 +265,16 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) { /// signature uses NoncopyableGenerics. Since inverses are mangled into /// symbols, a Swift 6.0+ runtime is generally needed to demangle them. /// - /// We make an exception for types in the stdlib, like Optional, since the - /// runtime should still be able to demangle them, based on the availability - /// of the type. + /// We make an exception for some types in the stdlib, like Optional, since + /// the runtime should still be able to demangle them, based on the + /// availability of the type. if (auto nominalTy = dyn_cast(t)) { auto *nom = nominalTy->getDecl(); if (auto sig = nom->getGenericSignature()) { SmallVector inverses; SmallVector reqs; sig->getRequirementsWithInverses(reqs, inverses); - if (!inverses.empty() && !nom->getModuleContext()->isStdlibModule()) { + if (!inverses.empty() && !nominalIsAlwaysAvailableForDemangling(nom)) { return addRequirement(Swift_6_0); } } diff --git a/test/IRGen/backward_deploy_span.swift b/test/IRGen/backward_deploy_span.swift new file mode 100644 index 000000000000..a7f78adbeb9a --- /dev/null +++ b/test/IRGen/backward_deploy_span.swift @@ -0,0 +1,17 @@ +// RUN: %target-swift-frontend -target %target-cpu-apple-macos12 -emit-ir -o - -primary-file %s | %FileCheck %s +// REQUIRES: concurrency +// REQUIRES: OS=macosx + +func useGenericMetatype(_ type: any ~Escapable.Type) { } + +// CHECK-LABEL: define hidden swiftcc void @"$s20backward_deploy_span11testSpanIntyyF"() +func testSpanInt() { + // CHECK: call swiftcc %swift.metadata_response @"$ss4SpanVySiGMa" + // CHECK: call swiftcc void @"$s20backward_deploy_span18useGenericMetatypeyyypRi0_s_XPXpF" + useGenericMetatype(Span.self) +} + +// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$ss4SpanVySiGMa"(i64 %0) +// CHECK: call swiftcc %swift.metadata_response @"$ss4SpanVMa"(i64 %0, ptr @"$sSiN") + + From 430b26c98370617fe1f4a22ea195a94a91379b52 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Jul 2025 14:23:45 -0700 Subject: [PATCH 2/3] Generalize test for 32-bit platforms --- test/IRGen/backward_deploy_span.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/IRGen/backward_deploy_span.swift b/test/IRGen/backward_deploy_span.swift index a7f78adbeb9a..5c88a8e163ca 100644 --- a/test/IRGen/backward_deploy_span.swift +++ b/test/IRGen/backward_deploy_span.swift @@ -1,5 +1,4 @@ // RUN: %target-swift-frontend -target %target-cpu-apple-macos12 -emit-ir -o - -primary-file %s | %FileCheck %s -// REQUIRES: concurrency // REQUIRES: OS=macosx func useGenericMetatype(_ type: any ~Escapable.Type) { } @@ -11,7 +10,5 @@ func testSpanInt() { useGenericMetatype(Span.self) } -// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$ss4SpanVySiGMa"(i64 %0) -// CHECK: call swiftcc %swift.metadata_response @"$ss4SpanVMa"(i64 %0, ptr @"$sSiN") - - +// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$ss4SpanVySiGMa" +// CHECK: call swiftcc %swift.metadata_response @"$ss4SpanVMa"({{i32|i64}} %0, ptr @"$sSiN") From d0d1a42b7c273eb313b8d0cad4ef46f756e58625 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Jul 2025 14:23:59 -0700 Subject: [PATCH 3/3] [IRGen] Mangling of nonisolated(nonsending) function types was introduced in Swift 6.2 We can't use mangled named when back-deploying earlier. --- lib/IRGen/GenReflection.cpp | 9 ++++++++- ...y_nonisolated_nonsending_function_type.swift | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/IRGen/backward_deploy_nonisolated_nonsending_function_type.swift diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index af33a7da89ef..51ad0a295abc 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -204,9 +204,10 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) { Swift_5_5, Swift_6_0, Swift_6_1, + Swift_6_2, // Short-circuit if we find this requirement. - Latest = Swift_6_1 + Latest = Swift_6_2 }; VersionRequirement latestRequirement = None; @@ -223,6 +224,11 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) { auto isolation = fn->getIsolation(); auto sendingResult = fn->hasSendingResult(); + // The mangling for nonisolated(nonsending) function types was introduced + // in Swift 6.2. + if (isolation.isNonIsolatedCaller()) + return addRequirement(Swift_6_2); + // The Swift 6.1 runtime fixes a bug preventing successful demangling // when @isolated(any) or global actor isolation is combined with a // sending result. @@ -290,6 +296,7 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) { }); switch (latestRequirement) { + case Swift_6_2: return llvm::VersionTuple(6, 2); case Swift_6_1: return llvm::VersionTuple(6, 1); case Swift_6_0: return llvm::VersionTuple(6, 0); case Swift_5_5: return llvm::VersionTuple(5, 5); diff --git a/test/IRGen/backward_deploy_nonisolated_nonsending_function_type.swift b/test/IRGen/backward_deploy_nonisolated_nonsending_function_type.swift new file mode 100644 index 000000000000..265146cf8b96 --- /dev/null +++ b/test/IRGen/backward_deploy_nonisolated_nonsending_function_type.swift @@ -0,0 +1,17 @@ +// RUN: %target-swift-frontend -target %target-cpu-apple-macos12 -emit-ir -o - -primary-file %s | %FileCheck %s +// REQUIRES: concurrency +// REQUIRES: OS=macosx + +func useGenericMetatype(_ type: Any.Type) { } + +// CHECK-LABEL: define hidden swiftcc void @"$s52backward_deploy_nonisolated_nonsending_function_type29testNonisolatedNonsendingTypeyyF"() +func testNonisolatedNonsendingType() { + typealias Fn = nonisolated(nonsending) () async throws -> Int + + // CHECK: call swiftcc %swift.metadata_response @"$sSiyYaKYCcMa" + // CHECK: call swiftcc void @"$s52backward_deploy_nonisolated_nonsending_function_type18useGenericMetatypeyyypXpF" + useGenericMetatype(Fn.self) +} + +// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSiyYaKYCcMa" +// CHECK: call ptr @swift_getExtendedFunctionTypeMetadata(i{{32|64}} 2768240640, {{i32|i64}} 0, ptr null, ptr null, ptr @"$sSiN"