mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #78729 from rjmccall/isolated-sending-results-compiler-fix
Assorted fixes for runtime metadata mangling and demangling
This commit is contained in:
@@ -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
195
include/swift/Basic/Pack.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
42
test/Runtime/metadata_printing.swift
Normal file
42
test/Runtime/metadata_printing.swift
Normal 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()
|
||||
Reference in New Issue
Block a user