Merge pull request #78729 from rjmccall/isolated-sending-results-compiler-fix

Assorted fixes for runtime metadata mangling and demangling
This commit is contained in:
John McCall
2025-01-23 21:33:50 -05:00
committed by GitHub
10 changed files with 635 additions and 138 deletions

View File

@@ -135,7 +135,7 @@ RUNTIME_VERSION(
PLATFORM(macOS, (14, 4, 0))
PLATFORM(iOS, (17, 4, 0))
PLATFORM(watchOS, (10, 4, 0))
PLATFORM(xrOS, (1, 0, 0))
PLATFORM(visionOS,(1, 0, 0))
)
END_MAJOR_VERSION(5)
@@ -147,7 +147,7 @@ RUNTIME_VERSION(
PLATFORM(macOS, (15, 0, 0))
PLATFORM(iOS, (18, 0, 0))
PLATFORM(watchOS, (11, 0, 0))
PLATFORM(xrOS, (2, 0, 0))
PLATFORM(visionOS,(2, 0, 0))
)
RUNTIME_VERSION(

195
include/swift/Basic/Pack.h Normal file
View File

@@ -0,0 +1,195 @@
//===--- Pack.h - Helpers for wording with class template packs -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_BASIC_PACKS_H
#define SWIFT_BASIC_PACKS_H
namespace swift {
namespace packs {
/// A pack of types.
template <class...>
struct Pack;
/// A trait indicating whether the given type is a specialization
/// of Pack<...>.
template <class>
struct IsPack {
static constexpr bool value = false;
};
template <class... Components>
struct IsPack<Pack<Components...>> {
static constexpr bool value = true;
};
/// Transform a variadic list of types using the given transform, a class
/// template which is expected to define a `result` type providing the
/// result of the transform.
///
/// template <class Arg, class Component>
/// class Transform {
/// using result = ...;
/// };
///
/// In principle, this would be cleaner as a member template, but that
/// works out poorly because in practice the member template must be
/// partially specialized in order to destructure it.
template <template <class, class> class Transform,
class TransformArg, class... Values>
struct PackMapComponents {
using result = Pack<typename Transform<TransformArg, Values>::result...>;
};
/// Transform the components of a pack using the given transform, a class
/// template which is expected to define a `result` type providing the
/// result of the transform.
///
/// template <class Arg, class Component>
/// class Transform {
/// using result = ...;
/// };
template <template <class, class> class Transform, class TransformArg,
class P>
struct PackMap;
template <template <class, class> class Transform, class TransformArg,
class... Components>
struct PackMap<Transform, TransformArg, Pack<Components...>>
: PackMapComponents<Transform, TransformArg, Components...> {};
/// Concatenate the components of a variadic list of packs.
template <class... Packs>
struct PackConcat;
template <>
struct PackConcat<> {
using result = Pack<>;
};
template <class First>
struct PackConcat<First> {
static_assert(IsPack<First>::value, "argument is not a pack");
using result = First;
};
template <class... FirstComponents, class... SecondComponents>
struct PackConcat<Pack<FirstComponents...>, Pack<SecondComponents...>> {
using result = Pack<FirstComponents..., SecondComponents...>;
};
template <class Head, class... Tail>
struct PackConcat<Head, Tail...>
: PackConcat<Head, typename PackConcat<Tail...>::result> {};
/// Flatten a pack of packs by concatenating their components.
template <class>
struct PackFlatten;
template <class... PackComponents>
struct PackFlatten<Pack<PackComponents...>>
: PackConcat<PackComponents...> {};
/// Apply the given pack-producing transform to each component of a pack,
/// then concatenate the results.
///
/// For example, if we start with Pack<A, B, C>, and the transform turns:
/// A => Pack<X, Y>
/// B => Pack<>
/// C => Pack<Z>
/// then the result will be Pack<X, Y, Z>.
template <template <class, class> class Transform, class TransformArg, class P>
struct PackFlatMap
: PackFlatten<typename PackMap<Transform, TransformArg, P>::result> {};
/// Reverse a variadic list of types.
template <class... PackComponents>
struct PackReverseComponents;
template <>
struct PackReverseComponents<> {
using result = Pack<>;
};
template <class Head>
struct PackReverseComponents<Head> {
using result = Pack<Head>;
};
template <class Head, class... Tail>
struct PackReverseComponents<Head, Tail...>
: PackConcat<typename PackReverseComponents<Tail...>::result,
Pack<Head>> {};
/// Reverse a pack.
template <class>
struct PackReverse;
template <class... PackComponents>
struct PackReverse<Pack<PackComponents...>>
: PackReverseComponents<PackComponents...> {};
/// Determine whether the given pack is transitively ordered according to
/// the given predicate:
///
/// template <class First, class Second>
/// struct IsOrdered {
/// static constexpr bool value;
/// };
template <template <class, class> class IsOrdered,
class... Components>
struct PackComponentsAreOrdered;
template <template <class, class> class IsOrdered>
struct PackComponentsAreOrdered<IsOrdered> {
static constexpr bool value = true;
};
template <template <class, class> class IsOrdered,
class A>
struct PackComponentsAreOrdered<IsOrdered, A> {
static constexpr bool value = true;
};
template <template <class, class> class IsOrdered,
class A, class B>
struct PackComponentsAreOrdered<IsOrdered, A, B> : IsOrdered<A, B> {};
template <template <class, class> class IsOrdered,
class A, class B, class... C>
struct PackComponentsAreOrdered<IsOrdered, A, B, C...> {
static constexpr bool value =
IsOrdered<A, B>::value &&
PackComponentsAreOrdered<IsOrdered, B, C...>::value;
};
/// Determine whether the given pack is well-ordered according to the given
/// predicate:
///
/// template <class First, class Second>
/// struct IsOrdered {
/// static constexpr bool value;
/// };
template <template <class, class> class IsOrdered,
class P>
struct PackIsOrdered;
template <template <class, class> class IsOrdered,
class... Components>
struct PackIsOrdered<IsOrdered, Pack<Components...>>
: PackComponentsAreOrdered<IsOrdered, Components...> {};
} // end namespace packs
} // end namespace swift
#endif

View File

@@ -880,7 +880,7 @@ AvailabilityRange ASTContext::getSwiftAvailability(unsigned major,
#define PLATFORM_TEST_macOS target.isMacOSX()
#define PLATFORM_TEST_iOS target.isiOS()
#define PLATFORM_TEST_watchOS target.isWatchOS()
#define PLATFORM_TEST_xrOS target.isXROS()
#define PLATFORM_TEST_visionOS target.isXROS()
#define _SECOND(A, B) B
#define SECOND(T) _SECOND T
@@ -895,7 +895,7 @@ AvailabilityRange ASTContext::getSwiftAvailability(unsigned major,
#undef PLATFORM_TEST_macOS
#undef PLATFORM_TEST_iOS
#undef PLATFORM_TEST_watchOS
#undef PLATFORM_TEST_xrOS
#undef PLATFORM_TEST_visionOS
#undef _SECOND
#undef SECOND

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Pack.h"
#include "swift/Basic/Platform.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -431,145 +432,372 @@ llvm::Triple swift::getUnversionedTriple(const llvm::Triple &triple) {
unversionedOSName);
}
namespace {
// Here, we statically reflect the entire contents of RuntimeVersions.def
// into the template-argument structure of the type AllStaticSwiftReleases.
// We then use template metaprogramming on this type to synthesize arrays
// of PlatformSwiftRelease for each of the target platforms with
// deployment restrictions. This would be much simpler with the recent
// generalizations of constexpr and non-type template parameters, but
// those remain above our baseline for now, so we have to do this the
// old way.
/// A specific release of a platform that provides a specific Swift
/// runtime version. Ultimately, all the variadic goop below is just
/// building an array of these for each platform, which is what we'll
/// use at runtime.
struct PlatformSwiftRelease {
llvm::VersionTuple swiftVersion;
llvm::VersionTuple platformVersion;
};
/// A deployment-restricted platform.
enum class PlatformKind {
macOS,
iOS,
watchOS,
visionOS
};
/// A template which statically reflects a version tuple. Generalized
/// template parameters would theoretically let us just use
/// llvm::VersionTuple.
template <unsigned... Components>
struct StaticVersion;
/// A template which statically reflects a single PLATFORM in
/// RuntimeVersions.def.
template <PlatformKind Kind, class Version>
struct StaticPlatformRelease;
/// A template which statically reflects a single RUNTIME_VERSION in
/// RuntimeVersions.def.
template <class SwiftVersion, class PlatformReleases>
struct StaticSwiftRelease;
/// In the assumed context of a particular platform, the release
/// of the platform that first provided a particular Swift version.
template <class SwiftVersion, class PlatformVersion>
struct StaticPlatformSwiftRelease;
// C++ does not allow template argument lists to have trailing commas,
// so to make the macro metaprogramming side of this work, we have to
// include an extra type here (and special-case it in the transforms
// below) for the sole purpose of terminating the list without a comma.
struct Terminal;
#define UNPARENTHESIZE(...) __VA_ARGS__
using AllStaticSwiftReleases =
packs::Pack<
#define PLATFORM(NAME, VERSION) \
StaticPlatformRelease< \
PlatformKind::NAME, \
StaticVersion<UNPARENTHESIZE VERSION> \
>,
#define FUTURE
#define RUNTIME_VERSION(SWIFT_TUPLE, PROVIDERS) \
StaticSwiftRelease<StaticVersion<UNPARENTHESIZE SWIFT_TUPLE>, \
packs::Pack<PROVIDERS Terminal>>,
#include "swift/AST/RuntimeVersions.def"
Terminal
>;
#undef UNPARENTHESIZE
/// A template for comparing two StaticVersion type values.
template <class A, class B>
struct StaticVersionGT;
// 0.0 is not strictly greater than any version.
template <class Second>
struct StaticVersionGT<
StaticVersion<>,
Second
> {
static constexpr bool value = false;
};
// A version is strictly greater than 0.0 if it has any nonzero component.
template <unsigned FirstHead, unsigned... FirstTail>
struct StaticVersionGT<
StaticVersion<FirstHead, FirstTail...>,
StaticVersion<>
> {
static constexpr bool value =
(FirstHead > 0) ? true :
StaticVersionGT<StaticVersion<FirstTail...>,
StaticVersion<>>::value;
};
// a.b is strictly greater than c.d if (a > c || (a == c && b > d)).
template <unsigned FirstHead, unsigned... FirstTail,
unsigned SecondHead, unsigned... SecondTail>
struct StaticVersionGT<
StaticVersion<FirstHead, FirstTail...>,
StaticVersion<SecondHead, SecondTail...>
> {
static constexpr bool value =
(FirstHead > SecondHead) ? true :
(FirstHead < SecondHead) ? false :
StaticVersionGT<StaticVersion<FirstTail...>,
StaticVersion<SecondTail...>>::value;
};
/// A template for turning a StaticVersion into an llvm::VersionTuple.
template <class>
struct BuildVersionTuple;
template <unsigned... Components>
struct BuildVersionTuple<StaticVersion<Components...>> {
static constexpr llvm::VersionTuple get() {
return llvm::VersionTuple(Components...);
}
};
/// A transform that takes a StaticPlatformRelease, checks if it
/// matches the given platform, and turns it into a
/// StaticPlatformSwiftRelease if so. The result is returned as an
/// optional pack which will be empty if the release is for a different
/// platform.
template <class, class>
struct BuildStaticPlatformSwiftReleaseHelper;
template <PlatformKind Platform, class SwiftVersion>
struct BuildStaticPlatformSwiftReleaseHelper_Arg;
// Matching case.
template <PlatformKind Platform, class SwiftVersion, class PlatformVersion>
struct BuildStaticPlatformSwiftReleaseHelper<
BuildStaticPlatformSwiftReleaseHelper_Arg<Platform, SwiftVersion>,
StaticPlatformRelease<Platform, PlatformVersion>> {
using result = packs::Pack<
StaticPlatformSwiftRelease<SwiftVersion, PlatformVersion>
>;
};
// Non-matching case.
template <PlatformKind Platform, class SwiftVersion,
PlatformKind OtherPlatform, class PlatformVersion>
struct BuildStaticPlatformSwiftReleaseHelper<
BuildStaticPlatformSwiftReleaseHelper_Arg<Platform, SwiftVersion>,
StaticPlatformRelease<OtherPlatform, PlatformVersion>> {
using result = packs::Pack<>;
};
// Terminal case (see above).
template <PlatformKind Platform, class SwiftVersion>
struct BuildStaticPlatformSwiftReleaseHelper<
BuildStaticPlatformSwiftReleaseHelper_Arg<Platform, SwiftVersion>,
Terminal> {
using result = packs::Pack<>;
};
/// A transform that takes a StaticSwiftRelease, finds the platform
/// release in it that matches the given platform, and turns it into
/// StaticPlatformSwiftRelease. The result is returned as an optional
/// pack which will be empty if there is no release for the given
/// platform in this SSR.
template <class, class>
struct BuildStaticPlatformSwiftRelease;
template <PlatformKind Platform>
struct BuildStaticPlatformSwiftRelease_Arg;
// Main case: destructure the arguments, then flat-map our helper
// transform above. Note that we assume that there aren't multiple
// entries for the same platform in the platform releases of a given
// Swift release.
template <PlatformKind Platform, class SwiftVersion,
class StaticPlatformReleases>
struct BuildStaticPlatformSwiftRelease<
BuildStaticPlatformSwiftRelease_Arg<Platform>,
StaticSwiftRelease<SwiftVersion, StaticPlatformReleases>>
: packs::PackFlatMap<
BuildStaticPlatformSwiftReleaseHelper,
BuildStaticPlatformSwiftReleaseHelper_Arg<Platform, SwiftVersion>,
StaticPlatformReleases> {};
// Terminal case (see above).
template <PlatformKind Platform>
struct BuildStaticPlatformSwiftRelease<
BuildStaticPlatformSwiftRelease_Arg<Platform>,
Terminal> {
using result = packs::Pack<>;
};
/// A template for generating a PlatformSwiftRelease array element
/// from a StaticPlatformSwiftRelease type value.
template <class>
struct BuildPlatformSwiftRelease;
template <class SwiftVersion, class PlatformVersion>
struct BuildPlatformSwiftRelease<
StaticPlatformSwiftRelease<SwiftVersion, PlatformVersion>
> {
static constexpr PlatformSwiftRelease get() {
return { BuildVersionTuple<SwiftVersion>::get(),
BuildVersionTuple<PlatformVersion>::get() };
}
};
/// A template for comparing two StaticPlatformSwiftRelease type values,
/// for the purposes of a well-ordered assertion we want to make:
/// We don't call this GT because it's not really a general-purpose
/// comparison.
template <class, class>
struct StaticPlatformSwiftReleaseStrictlyDescend;
template <class FirstSwift, class FirstPlatform,
class SecondSwift, class SecondPlatform>
struct StaticPlatformSwiftReleaseStrictlyDescend<
StaticPlatformSwiftRelease<FirstSwift, FirstPlatform>,
StaticPlatformSwiftRelease<SecondSwift, SecondPlatform>
> {
static constexpr bool value =
StaticVersionGT<FirstSwift, SecondSwift>::value &&
StaticVersionGT<FirstPlatform, SecondPlatform>::value;
};
/// A helper template for BuildPlatformSwiftReleaseArray, below.
template <class P>
struct BuildPlatformSwiftReleaseArrayHelper;
template <class... StaticPlatformSwiftReleases>
struct BuildPlatformSwiftReleaseArrayHelper<
packs::Pack<StaticPlatformSwiftReleases...>
> {
// After we reverse the entries, we expect them to strictly
// descend in both the Swift version and the platform version.
static_assert(packs::PackComponentsAreOrdered<
StaticPlatformSwiftReleaseStrictlyDescend,
StaticPlatformSwiftReleases...
>::value,
"RuntimeVersions.def is not properly ordered?");
static constexpr PlatformSwiftRelease releases[] = {
BuildPlatformSwiftRelease<StaticPlatformSwiftReleases>::get()...
};
};
/// Build a static constexpr array of PlatformRelease objects matching
/// the given platform.
template <PlatformKind Platform>
struct BuildPlatformSwiftReleaseArray
: BuildPlatformSwiftReleaseArrayHelper<
// Turn each entry in AllStaticSwiftReleases into an optional
// StaticPlatformSwiftRelease representing whether there is a
// platform release providing that Swift release for the given
// platform. Flatten that pack, then reverse it so that it's in
// order of descending release versions. Finally, build an array
// of PlatformRelease objects for the remaining values.
typename packs::PackReverse<
typename packs::PackFlatMap<
BuildStaticPlatformSwiftRelease,
BuildStaticPlatformSwiftRelease_Arg<Platform>,
AllStaticSwiftReleases
>::result
>::result
> {};
} // end anonymous namespace
static std::optional<llvm::VersionTuple>
findSwiftRuntimeVersionHelper(llvm::VersionTuple targetPlatformVersion,
llvm::VersionTuple minimumSwiftVersion,
ArrayRef<PlatformSwiftRelease> allReleases) {
#define MAX(a, b) ((a) > (b) ? (a) : (b))
// Scan forward in our filtered platform release array for the given
// platform.
for (auto &release : allReleases) {
// If the provider version is <= the deployment target, then
// the deployment target includes support for the given Swift
// release. Since we're scanning in reverse order of Swift
// releases (because of the order of entries in RuntimeVersions.def),
// this must be the highest supported Swift release.
if (release.platformVersion <= targetPlatformVersion) {
return std::max(release.swiftVersion, minimumSwiftVersion);
}
}
// If we didn't find anything, but the target release is at least the
// notional future-release version, return that we aren't
// deployment-limited.
if (targetPlatformVersion >= llvm::VersionTuple(99, 99))
return std::nullopt;
// Otherwise, return the minimum Swift version.
return minimumSwiftVersion;
}
/// Return the highest Swift release that matches the given platform and
/// has a version no greater than the target version. Don't return a version
/// older that the minimum. Returns null if the target version matches the
/// notional future release version.
template <PlatformKind TargetPlatform>
static std::optional<llvm::VersionTuple>
findSwiftRuntimeVersion(llvm::VersionTuple targetPlatformVersion,
llvm::VersionTuple minimumSwiftVersion) {
auto &allReleases =
BuildPlatformSwiftReleaseArray<TargetPlatform>::releases;
return findSwiftRuntimeVersionHelper(targetPlatformVersion,
minimumSwiftVersion,
allReleases);
}
std::optional<llvm::VersionTuple>
swift::getSwiftRuntimeCompatibilityVersionForTarget(
const llvm::Triple &Triple) {
if (Triple.isMacOSX()) {
llvm::VersionTuple OSVersion;
Triple.getMacOSXVersion(OSVersion);
unsigned Major = OSVersion.getMajor();
unsigned Minor = OSVersion.getMinor().value_or(0);
auto floorFor64 = [&Triple](llvm::VersionTuple v) {
if (!Triple.isAArch64()) return v;
// macOS got first arm64(e) support in 11.0, i.e. VersionTuple(5, 3)
return std::max(v, llvm::VersionTuple(5, 3));
};
// macOS releases predate the stable ABI, so use Swift 5.0 as our base.
auto baseRelease = llvm::VersionTuple(5, 0);
if (Major == 10) {
if (Triple.isAArch64() && Minor <= 16)
return floorFor64(llvm::VersionTuple(5, 3));
// macOS got its first arm64(e) support in 11.0, which included Swift 5.3.
if (Triple.isAArch64())
baseRelease = llvm::VersionTuple(5, 3);
return findSwiftRuntimeVersion<PlatformKind::macOS>(OSVersion, baseRelease);
if (Minor <= 14) {
return floorFor64(llvm::VersionTuple(5, 0));
} else if (Minor <= 15) {
if (OSVersion.getSubminor().value_or(0) <= 3) {
return floorFor64(llvm::VersionTuple(5, 1));
} else {
return floorFor64(llvm::VersionTuple(5, 2));
}
}
} else if (Major == 11) {
if (Minor <= 2)
return floorFor64(llvm::VersionTuple(5, 3));
return floorFor64(llvm::VersionTuple(5, 4));
} else if (Major == 12) {
if (Minor <= 2)
return floorFor64(llvm::VersionTuple(5, 5));
return floorFor64(llvm::VersionTuple(5, 6));
} else if (Major == 13) {
if (Minor <= 2)
return floorFor64(llvm::VersionTuple(5, 7));
return floorFor64(llvm::VersionTuple(5, 8));
} else if (Major == 14) {
if (Minor <= 3)
return floorFor64(llvm::VersionTuple(5, 9));
return floorFor64(llvm::VersionTuple(5, 10));
}
} else if (Triple.isiOS()) { // includes tvOS
llvm::VersionTuple OSVersion = Triple.getiOSVersion();
unsigned Major = OSVersion.getMajor();
unsigned Minor = OSVersion.getMinor().value_or(0);
auto floorForArchitecture = [&Triple, Major](llvm::VersionTuple v) {
// arm64 simulators and macCatalyst are introduced in iOS 14.0/tvOS 14.0
// with Swift 5.3
if (Triple.isAArch64() && Major <= 14 &&
(Triple.isSimulatorEnvironment() ||
Triple.isMacCatalystEnvironment()))
return std::max(v, llvm::VersionTuple(5, 3));
// iOS releases predate the stable ABI, so use Swift 5.0 as our base.
auto baseRelease = llvm::VersionTuple(5, 0);
if (Triple.getArchName() != "arm64e") return v;
// arm64 simulators and macCatalyst were introduced in iOS 14.0/tvOS 14.0,
// which included Swift 5.3.
if (Triple.isAArch64() &&
(Triple.isSimulatorEnvironment() ||
Triple.isMacCatalystEnvironment()))
baseRelease = llvm::VersionTuple(5, 3);
// iOS got first arm64e support in 12.0, which has a Swift runtime version
// older than 5.0, so let's floor at VersionTuple(5, 0) instead.
return std::max(v, llvm::VersionTuple(5, 0));
};
// iOS first got arm64e support in 12.0, which did not yet support the
// Swift stable ABI, so it does not provide a useful version bump.
if (Major <= 12) {
return floorForArchitecture(llvm::VersionTuple(5, 0));
} else if (Major <= 13) {
if (Minor <= 3) {
return floorForArchitecture(llvm::VersionTuple(5, 1));
} else {
return floorForArchitecture(llvm::VersionTuple(5, 2));
}
} else if (Major <= 14) {
if (Minor <= 4)
return floorForArchitecture(llvm::VersionTuple(5, 3));
return findSwiftRuntimeVersion<PlatformKind::iOS>(OSVersion, baseRelease);
return floorForArchitecture(llvm::VersionTuple(5, 4));
} else if (Major <= 15) {
if (Minor <= 3)
return floorForArchitecture(llvm::VersionTuple(5, 5));
return floorForArchitecture(llvm::VersionTuple(5, 6));
} else if (Major <= 16) {
if (Minor <= 3)
return floorForArchitecture(llvm::VersionTuple(5, 7));
return floorForArchitecture(llvm::VersionTuple(5, 8));
} else if (Major <= 17) {
if (Minor <= 3)
return floorForArchitecture(llvm::VersionTuple(5, 9));
return floorForArchitecture(llvm::VersionTuple(5, 10));
}
} else if (Triple.isWatchOS()) {
llvm::VersionTuple OSVersion = Triple.getWatchOSVersion();
unsigned Major = OSVersion.getMajor();
unsigned Minor = OSVersion.getMinor().value_or(0);
auto floorFor64bits = [&Triple](llvm::VersionTuple v) {
if (!Triple.isArch64Bit()) return v;
// 64-bit watchOS was introduced with Swift 5.3
return std::max(v, llvm::VersionTuple(5, 3));
};
// watchOS releases predate the stable ABI, so use Swift 5.0 as our base.
auto baseRelease = llvm::VersionTuple(5, 0);
if (Major <= 5) {
return floorFor64bits(llvm::VersionTuple(5, 0));
} else if (Major <= 6) {
if (Minor <= 1) {
return floorFor64bits(llvm::VersionTuple(5, 1));
} else {
return floorFor64bits(llvm::VersionTuple(5, 2));
}
} else if (Major <= 7) {
if (Minor <= 3)
return floorFor64bits(llvm::VersionTuple(5, 3));
// 64-bit watchOS was first supported by watchOS 7, which provided
// Swift 5.3.
if (Triple.isArch64Bit())
baseRelease = llvm::VersionTuple(5, 3);
return floorFor64bits(llvm::VersionTuple(5, 4));
} else if (Major <= 8) {
if (Minor <= 4)
return floorFor64bits(llvm::VersionTuple(5, 5));
return floorFor64bits(llvm::VersionTuple(5, 6));
} else if (Major <= 9) {
if (Minor <= 3)
return floorFor64bits(llvm::VersionTuple(5, 7));
return floorFor64bits(llvm::VersionTuple(5, 8));
} else if (Major <= 10) {
if (Minor <= 3)
return floorFor64bits(llvm::VersionTuple(5, 9));
return floorFor64bits(llvm::VersionTuple(5, 10));
}
}
else if (Triple.isXROS()) {
return findSwiftRuntimeVersion<PlatformKind::watchOS>(OSVersion, baseRelease);
} else if (Triple.isXROS()) {
llvm::VersionTuple OSVersion = Triple.getOSVersion();
unsigned Major = OSVersion.getMajor();
unsigned Minor = OSVersion.getMinor().value_or(0);
if (Major <= 1) {
if (Minor <= 0)
return llvm::VersionTuple(5, 9);
return llvm::VersionTuple(5, 10);
}
// visionOS 1.0 provided Swift 5.9.
auto baseRelease = llvm::VersionTuple(5, 9);
return findSwiftRuntimeVersion<PlatformKind::visionOS>(OSVersion, baseRelease);
}
return std::nullopt;

View File

@@ -182,9 +182,10 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
Swift_5_2,
Swift_5_5,
Swift_6_0,
Swift_6_1,
// Short-circuit if we find this requirement.
Latest = Swift_6_0
Latest = Swift_6_1
};
VersionRequirement latestRequirement = None;
@@ -198,16 +199,29 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
(void) type.findIf([&](CanType t) -> bool {
if (auto fn = dyn_cast<AnyFunctionType>(t)) {
auto isolation = fn->getIsolation();
auto sendingResult = fn->hasSendingResult();
// The Swift 6.1 runtime fixes a bug preventing successful demangling
// when @isolated(any) or global actor isolation is combined with a
// sending result.
if (sendingResult &&
(isolation.isErased() || isolation.isGlobalActor()))
return addRequirement(Swift_6_1);
// The Swift 6.0 runtime is the first version able to demangle types
// that involve typed throws or @isolated(any), or for that matter
// represent them at all at runtime.
if (!fn.getThrownError().isNull() || fn->getIsolation().isErased())
// that involve typed throws, @isolated(any), or a sending result, or
// for that matter to represent them at all at runtime.
if (!fn.getThrownError().isNull() ||
isolation.isErased() ||
sendingResult)
return addRequirement(Swift_6_0);
// The Swift 5.5 runtime is the first version able to demangle types
// related to concurrency.
if (fn->isAsync() || fn->isSendable() ||
!fn->getIsolation().isNonIsolated())
if (fn->isAsync() ||
fn->isSendable() ||
!isolation.isNonIsolated())
return addRequirement(Swift_5_5);
return false;
@@ -255,6 +269,7 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
});
switch (latestRequirement) {
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);
case Swift_5_2: return llvm::VersionTuple(5, 2);

View File

@@ -1674,12 +1674,6 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
}
default:
assert((!params.empty() || type->isDifferentiable() ||
!type->getIsolation().isNonIsolated() ||
type->getThrownError()) &&
"0 parameter case should be specialized unless it is a "
"differentiable function or has a global actor");
llvm::SmallVector<llvm::Value *, 8> arguments;
arguments.push_back(flagsVal);

View File

@@ -758,6 +758,9 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
Dem.createNode(Node::Kind::GlobalActorFunctionType);
globalActorNode->addChild(globalActorTypeNode, Dem);
funcNode->addChild(globalActorNode, Dem);
} else if (func->getExtendedFlags().isIsolatedAny()) {
funcNode->addChild(Dem.createNode(
Node::Kind::IsolatedAnyFunctionType), Dem);
}
switch (func->getDifferentiabilityKind().Value) {
case FunctionMetadataDifferentiabilityKind::NonDifferentiable:

View File

@@ -8,7 +8,7 @@
// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s
// Doesn't autolink compatibility library because target OS doesn't need it
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.24 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx99.99 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s
// Only autolinks 5.1 compatibility library because target OS has 5.1
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.15 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-51 %s
@@ -23,9 +23,9 @@
// RUN: %target-swift-frontend -runtime-compatibility-version 5.0 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD %s
// RUN: %target-swift-frontend -runtime-compatibility-version 5.1 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-51 %s
// RUN: %target-swift-frontend -runtime-compatibility-version 5.5 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-55 %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.24 -runtime-compatibility-version 5.0 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.24 -runtime-compatibility-version 5.1 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-51 %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.24 -runtime-compatibility-version 5.5 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-55 %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx99.99 -runtime-compatibility-version 5.0 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx99.99 -runtime-compatibility-version 5.1 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-51 %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx99.99 -runtime-compatibility-version 5.5 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD-55 %s
public func foo() {}

View File

@@ -1,10 +1,13 @@
// RUN: %swift -emit-ir %s -target x86_64-apple-macosx10.10 -disable-legacy-type-info -parse-stdlib -module-name Swift | %FileCheck -DINT=i64 %s -check-prefixes=CHECK,CHECK-ACCESSOR
// RUN: %swift -emit-ir %s -target x86_64-unknown-linux-gnu -disable-legacy-type-info -parse-stdlib -module-name Swift | %FileCheck -DINT=i64 %s -check-prefixes=CHECK,CHECK-DEMANGLE
// RUN: %swift -emit-ir %s -target x86_64-apple-macosx10.10 -disable-legacy-type-info -parse-stdlib -module-name Swift | %FileCheck -DINT=i64 %s -check-prefixes=CHECK,CHECK-ACCESSOR,CHECK-COMBO-ACCESSOR
// RUN: %swift -emit-ir %s -target x86_64-apple-macos15.0 -disable-legacy-type-info -parse-stdlib -module-name Swift | %FileCheck -DINT=i64 %s -check-prefixes=CHECK,CHECK-DEMANGLE,CHECK-COMBO-ACCESSOR
// RUN: %swift -emit-ir %s -target x86_64-unknown-linux-gnu -disable-legacy-type-info -parse-stdlib -module-name Swift | %FileCheck -DINT=i64 %s -check-prefixes=CHECK,CHECK-DEMANGLE,CHECK-COMBO-DEMANGLE
// REQUIRES: concurrency
sil_stage canonical
struct NonSendable {}
// CHECK-LABEL: define{{.*}} swiftcc ptr @get_metadata
// CHECK: entry:
// CHECK-ACCESSOR-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$syyYbYAcMa"([[INT]] 0)
@@ -22,3 +25,20 @@ entry:
// 3288334336 == 0xc4000000 == (ExtendedFlags | Sendable | Escaping)
// 2 == IsolatedAny
// CHECK-ACCESSOR: call ptr @swift_getExtendedFunctionTypeMetadata([[INT]] 3288334336, [[INT]] 0, ptr null, ptr null, ptr getelementptr inbounds {{.*}} @"$sytN"{{.*}}), ptr null, i32 2, ptr null)
// CHECK-LABEL: define{{.*}} swiftcc ptr @get_combo_metadata
// CHECK: entry:
// CHECK-COMBO-ACCESSOR-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$ss11NonSendableVyYbYAYTcMa"([[INT]] 0)
// CHECK-COMBO-ACCESSOR-NEXT: [[METADATA:%.]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK-COMBO-DEMANGLE-NEXT: [[METADATA:%.*]] = call ptr @__swift_instantiateConcreteTypeFromMangledName(ptr @"$ss11NonSendableVyYbYAYTcMD")
// CHECK-NEXT: ret ptr [[METADATA]]
sil @get_combo_metadata : $() -> @thick Any.Type {
entry:
%type = metatype $@thick (@isolated(any) @Sendable () -> sending NonSendable).Type
%result = init_existential_metatype %type : $@thick (@isolated(any) @Sendable () -> sending NonSendable).Type, $@thick Any.Type
return %result : $@thick Any.Type
}
// CHECK-COMBO-ACCESSOR-LABEL: define{{.*}} swiftcc %swift.metadata_response @"$ss11NonSendableVyYbYAYTcMa"
// 18 == 0x12 == IsolatedAny | HasSendingResult
// CHECK-COMBO-ACCESSOR: call ptr @swift_getExtendedFunctionTypeMetadata([[INT]] 3288334336, [[INT]] 0, ptr null, ptr null, ptr getelementptr inbounds {{.*}} @"$ss11NonSendableVMf"{{.*}}), ptr null, i32 18, ptr null)

View File

@@ -0,0 +1,42 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -target %target-future-triple -parse-stdlib %s -module-name main -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %target-run %t/a.out
// REQUIRES: executable_test
// REQUIRES: concurrency
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime
import Swift
import StdlibUnittest
import _Concurrency
let MetadataPrintingTests = TestSuite("MetadataPrinting")
class NonSendable {
var x: Int = 0
}
func expect<T>(type: T.Type, printsAs string: String) {
expectEqual(string, "\(type)")
}
MetadataPrintingTests.test("@isolated(any) functions") {
expect(type: (@isolated(any) () -> ()).self,
printsAs: "@isolated(any) () -> ()")
expect(type: (@isolated(any) () -> NonSendable).self,
printsAs: "@isolated(any) () -> NonSendable")
expect(type: (@isolated(any) () -> sending NonSendable).self,
printsAs: "@isolated(any) () -> sending NonSendable")
}
MetadataPrintingTests.test("global actor functions") {
expect(type: (@MainActor () -> ()).self,
printsAs: "@MainActor () -> ()")
expect(type: (@MainActor () -> NonSendable).self,
printsAs: "@MainActor () -> NonSendable")
expect(type: (@MainActor () -> sending NonSendable).self,
printsAs: "@MainActor () -> sending NonSendable")
}
runAllTests()