Skip to content

Commit 7565ef4

Browse files
committed
Generate getSwiftRuntimeCompatibilityVersionForTarget from
RuntimeVersions.def. NFC except that it no longer treats arbitrary versions in the future as non-deployment-limited; you have to specifically use a future release to get that behavior.
1 parent 502082d commit 7565ef4

File tree

1 file changed

+120
-128
lines changed

1 file changed

+120
-128
lines changed

lib/Basic/Platform.cpp

Lines changed: 120 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -431,147 +431,139 @@ llvm::Triple swift::getUnversionedTriple(const llvm::Triple &triple) {
431431
unversionedOSName);
432432
}
433433

434+
namespace {
435+
436+
enum class Platform {
437+
macOS,
438+
iOS,
439+
watchOS,
440+
xrOS
441+
};
442+
443+
/// A specific platform release.
444+
struct PlatformRelease {
445+
Platform platform;
446+
llvm::VersionTuple version;
447+
};
448+
449+
struct SwiftRelease {
450+
/// The release version of the Swift runtime.
451+
llvm::VersionTuple version;
452+
453+
/// Platform releases that provide this release of the Swift runtime.
454+
std::initializer_list<PlatformRelease> providers;
455+
};
456+
457+
} // end anonymous namespace
458+
459+
// TODO: do some constexpr trickery to split these out by platform
460+
static constexpr SwiftRelease swiftReleases[] = {
461+
#define PLATFORM(NAME, VERSION) \
462+
{ \
463+
Platform::NAME, \
464+
llvm::VersionTuple VERSION \
465+
},
466+
#define FUTURE
467+
#define RUNTIME_VERSION(SWIFT_TUPLE, PROVIDERS) \
468+
{ \
469+
llvm::VersionTuple SWIFT_TUPLE, \
470+
{ \
471+
PROVIDERS \
472+
} \
473+
},
474+
#include "swift/AST/RuntimeVersions.def"
475+
};
476+
477+
/// Return the highest Swift release that matches the given platform and
478+
/// has a version no greater than the target version. Don't return a version
479+
/// older that the minimum. Returns null if the target version matches the
480+
/// notional future release version.
481+
static std::optional<llvm::VersionTuple>
482+
findSwiftRuntimeVersion(Platform targetPlatform,
483+
llvm::VersionTuple targetVersion,
484+
llvm::VersionTuple minimumRelease) {
485+
#define MAX(a, b) ((a) > (b) ? (a) : (b))
486+
487+
// Just do a simple reverse scan for now.
488+
for (auto &swiftRelease : llvm::reverse(llvm::ArrayRef(swiftReleases))) {
489+
for (auto &provider : swiftRelease.providers) {
490+
// If the provider version is <= the deployment target, then
491+
// the deployment target includes support for the given Swift
492+
// release. Since we're scanning in reverse order of Swift
493+
// releases (because of the order of entries in RuntimeVersions.def),
494+
// this must be the highest supported Swift release.
495+
if (provider.platform == targetPlatform &&
496+
provider.version <= targetVersion) {
497+
return MAX(swiftRelease.version, minimumRelease);
498+
}
499+
}
500+
}
501+
502+
// If we didn't find anything, but the target release is at least the
503+
// notional future-release version, return that we aren't
504+
// deployment-limited.
505+
if (targetVersion >= llvm::VersionTuple(99, 99))
506+
return std::nullopt;
507+
508+
// Otherwise, return the minimum release.
509+
return minimumRelease;
510+
}
511+
434512
std::optional<llvm::VersionTuple>
435513
swift::getSwiftRuntimeCompatibilityVersionForTarget(
436514
const llvm::Triple &Triple) {
437-
#define MAX(a, b) ((a) > (b) ? (a) : (b))
438515

439516
if (Triple.isMacOSX()) {
440517
llvm::VersionTuple OSVersion;
441518
Triple.getMacOSXVersion(OSVersion);
442-
unsigned Major = OSVersion.getMajor();
443-
unsigned Minor = OSVersion.getMinor().value_or(0);
444-
445-
auto floorFor64 = [&Triple](llvm::VersionTuple v) {
446-
if (!Triple.isAArch64()) return v;
447-
// macOS got first arm64(e) support in 11.0, i.e. VersionTuple(5, 3)
448-
return MAX(v, llvm::VersionTuple(5, 3));
449-
};
450-
451-
if (Major == 10) {
452-
if (Triple.isAArch64() && Minor <= 16)
453-
return floorFor64(llvm::VersionTuple(5, 3));
454-
455-
if (Minor <= 14) {
456-
return floorFor64(llvm::VersionTuple(5, 0));
457-
} else if (Minor <= 15) {
458-
if (OSVersion.getSubminor().value_or(0) <= 3) {
459-
return floorFor64(llvm::VersionTuple(5, 1));
460-
} else {
461-
return floorFor64(llvm::VersionTuple(5, 2));
462-
}
463-
}
464-
} else if (Major == 11) {
465-
if (Minor <= 2)
466-
return floorFor64(llvm::VersionTuple(5, 3));
467-
return floorFor64(llvm::VersionTuple(5, 4));
468-
} else if (Major == 12) {
469-
if (Minor <= 2)
470-
return floorFor64(llvm::VersionTuple(5, 5));
471-
return floorFor64(llvm::VersionTuple(5, 6));
472-
} else if (Major == 13) {
473-
if (Minor <= 2)
474-
return floorFor64(llvm::VersionTuple(5, 7));
475-
return floorFor64(llvm::VersionTuple(5, 8));
476-
} else if (Major == 14) {
477-
if (Minor <= 3)
478-
return floorFor64(llvm::VersionTuple(5, 9));
479-
return floorFor64(llvm::VersionTuple(5, 10));
480-
}
519+
520+
// macOS releases predate the stable ABI, so use Swift 5.0 as our base.
521+
auto baseRelease = llvm::VersionTuple(5, 0);
522+
523+
// macOS got its first arm64(e) support in 11.0, which included Swift 5.3.
524+
if (Triple.isAArch64())
525+
baseRelease = llvm::VersionTuple(5, 3);
526+
527+
return findSwiftRuntimeVersion(Platform::macOS, OSVersion, baseRelease);
528+
481529
} else if (Triple.isiOS()) { // includes tvOS
482530
llvm::VersionTuple OSVersion = Triple.getiOSVersion();
483-
unsigned Major = OSVersion.getMajor();
484-
unsigned Minor = OSVersion.getMinor().value_or(0);
485-
486-
auto floorForArchitecture = [&Triple, Major](llvm::VersionTuple v) {
487-
// arm64 simulators and macCatalyst are introduced in iOS 14.0/tvOS 14.0
488-
// with Swift 5.3
489-
if (Triple.isAArch64() && Major <= 14 &&
490-
(Triple.isSimulatorEnvironment() ||
491-
Triple.isMacCatalystEnvironment()))
492-
return MAX(v, llvm::VersionTuple(5, 3));
493-
494-
if (Triple.getArchName() != "arm64e") return v;
495-
496-
// iOS got first arm64e support in 12.0, which has a Swift runtime version
497-
// older than 5.0, so let's floor at VersionTuple(5, 0) instead.
498-
return MAX(v, llvm::VersionTuple(5, 0));
499-
};
500-
501-
if (Major <= 12) {
502-
return floorForArchitecture(llvm::VersionTuple(5, 0));
503-
} else if (Major <= 13) {
504-
if (Minor <= 3) {
505-
return floorForArchitecture(llvm::VersionTuple(5, 1));
506-
} else {
507-
return floorForArchitecture(llvm::VersionTuple(5, 2));
508-
}
509-
} else if (Major <= 14) {
510-
if (Minor <= 4)
511-
return floorForArchitecture(llvm::VersionTuple(5, 3));
512-
513-
return floorForArchitecture(llvm::VersionTuple(5, 4));
514-
} else if (Major <= 15) {
515-
if (Minor <= 3)
516-
return floorForArchitecture(llvm::VersionTuple(5, 5));
517-
return floorForArchitecture(llvm::VersionTuple(5, 6));
518-
} else if (Major <= 16) {
519-
if (Minor <= 3)
520-
return floorForArchitecture(llvm::VersionTuple(5, 7));
521-
return floorForArchitecture(llvm::VersionTuple(5, 8));
522-
} else if (Major <= 17) {
523-
if (Minor <= 3)
524-
return floorForArchitecture(llvm::VersionTuple(5, 9));
525-
return floorForArchitecture(llvm::VersionTuple(5, 10));
526-
}
531+
532+
// iOS releases predate the stable ABI, so use Swift 5.0 as our base.
533+
auto baseRelease = llvm::VersionTuple(5, 0);
534+
535+
// arm64 simulators and macCatalyst were introduced in iOS 14.0/tvOS 14.0,
536+
// which included Swift 5.3.
537+
if (Triple.isAArch64() &&
538+
(Triple.isSimulatorEnvironment() ||
539+
Triple.isMacCatalystEnvironment()))
540+
baseRelease = llvm::VersionTuple(5, 3);
541+
542+
// iOS first got arm64e support in 12.0, which did not yet support the
543+
// Swift stable ABI, so it does not provide a useful version bump.
544+
545+
return findSwiftRuntimeVersion(Platform::iOS, OSVersion, baseRelease);
546+
527547
} else if (Triple.isWatchOS()) {
528548
llvm::VersionTuple OSVersion = Triple.getWatchOSVersion();
529-
unsigned Major = OSVersion.getMajor();
530-
unsigned Minor = OSVersion.getMinor().value_or(0);
531-
532-
auto floorFor64bits = [&Triple](llvm::VersionTuple v) {
533-
if (!Triple.isArch64Bit()) return v;
534-
// 64-bit watchOS was introduced with Swift 5.3
535-
return MAX(v, llvm::VersionTuple(5, 3));
536-
};
537-
538-
if (Major <= 5) {
539-
return floorFor64bits(llvm::VersionTuple(5, 0));
540-
} else if (Major <= 6) {
541-
if (Minor <= 1) {
542-
return floorFor64bits(llvm::VersionTuple(5, 1));
543-
} else {
544-
return floorFor64bits(llvm::VersionTuple(5, 2));
545-
}
546-
} else if (Major <= 7) {
547-
if (Minor <= 3)
548-
return floorFor64bits(llvm::VersionTuple(5, 3));
549-
550-
return floorFor64bits(llvm::VersionTuple(5, 4));
551-
} else if (Major <= 8) {
552-
if (Minor <= 4)
553-
return floorFor64bits(llvm::VersionTuple(5, 5));
554-
return floorFor64bits(llvm::VersionTuple(5, 6));
555-
} else if (Major <= 9) {
556-
if (Minor <= 3)
557-
return floorFor64bits(llvm::VersionTuple(5, 7));
558-
return floorFor64bits(llvm::VersionTuple(5, 8));
559-
} else if (Major <= 10) {
560-
if (Minor <= 3)
561-
return floorFor64bits(llvm::VersionTuple(5, 9));
562-
return floorFor64bits(llvm::VersionTuple(5, 10));
563-
}
564-
}
565-
else if (Triple.isXROS()) {
549+
550+
// tvOS releases predate the stable ABI, so use Swift 5.0 as our base.
551+
auto baseRelease = llvm::VersionTuple(5, 0);
552+
553+
// 64-bit watchOS was first supported by watchOS 7, which provided
554+
// Swift 5.3.
555+
if (Triple.isArch64Bit())
556+
baseRelease = llvm::VersionTuple(5, 3);
557+
558+
return findSwiftRuntimeVersion(Platform::watchOS, OSVersion, baseRelease);
559+
560+
} else if (Triple.isXROS()) {
566561
llvm::VersionTuple OSVersion = Triple.getOSVersion();
567-
unsigned Major = OSVersion.getMajor();
568-
unsigned Minor = OSVersion.getMinor().value_or(0);
569562

570-
if (Major <= 1) {
571-
if (Minor <= 0)
572-
return llvm::VersionTuple(5, 9);
573-
return llvm::VersionTuple(5, 10);
574-
}
563+
// realityOS 1.0 provided Swift 5.9.
564+
auto baseRelease = llvm::VersionTuple(5, 9);
565+
566+
return findSwiftRuntimeVersion(Platform::xrOS, OSVersion, baseRelease);
575567
}
576568

577569
return std::nullopt;

0 commit comments

Comments
 (0)