Skip to content

Commit f7ff3f0

Browse files
committed
SILGen: Introduce macCatalyst support for @backDeployed.
Upstreams the necessary changes to compile references to `@backDeployed` declarations correctly when a `macabi` target triple or a `-target-variant` is specified.
1 parent 6fb6a56 commit f7ff3f0

File tree

7 files changed

+192
-14
lines changed

7 files changed

+192
-14
lines changed

include/swift/AST/Attr.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,7 +2316,7 @@ class BackDeployedAttr : public DeclAttribute {
23162316
const llvm::VersionTuple Version;
23172317

23182318
/// Returns true if this attribute is active given the current platform.
2319-
bool isActivePlatform(const ASTContext &ctx) const;
2319+
bool isActivePlatform(const ASTContext &ctx, bool forTargetVariant) const;
23202320

23212321
static bool classof(const DeclAttribute *DA) {
23222322
return DA->getKind() == DeclAttrKind::BackDeployed;
@@ -2745,7 +2745,8 @@ class DeclAttributes {
27452745

27462746
/// Returns the `@backDeployed` attribute that is active for the current
27472747
/// platform.
2748-
const BackDeployedAttr *getBackDeployed(const ASTContext &ctx) const;
2748+
const BackDeployedAttr *getBackDeployed(const ASTContext &ctx,
2749+
bool forTargetVariant) const;
27492750

27502751
SWIFT_DEBUG_DUMPER(dump(const Decl *D = nullptr));
27512752
void print(ASTPrinter &Printer, const PrintOptions &Options,

include/swift/AST/Decl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
10671067
/// Returns the OS version in which the decl became ABI as specified by the
10681068
/// `@backDeployed` attribute.
10691069
std::optional<llvm::VersionTuple>
1070-
getBackDeployedBeforeOSVersion(ASTContext &Ctx) const;
1070+
getBackDeployedBeforeOSVersion(ASTContext &Ctx,
1071+
bool forTargetVariant = false) const;
10711072

10721073
/// Returns true if the decl has an active `@backDeployed` attribute for the
10731074
/// given context.

lib/AST/Attr.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,8 @@ const AvailableAttr *DeclAttributes::getNoAsync(const ASTContext &ctx) const {
617617
}
618618

619619
const BackDeployedAttr *
620-
DeclAttributes::getBackDeployed(const ASTContext &ctx) const {
620+
DeclAttributes::getBackDeployed(const ASTContext &ctx,
621+
bool forTargetVariant) const {
621622
const BackDeployedAttr *bestAttr = nullptr;
622623

623624
for (auto attr : *this) {
@@ -626,7 +627,7 @@ DeclAttributes::getBackDeployed(const ASTContext &ctx) const {
626627
continue;
627628

628629
if (backDeployedAttr->isInvalid() ||
629-
!backDeployedAttr->isActivePlatform(ctx))
630+
!backDeployedAttr->isActivePlatform(ctx, forTargetVariant))
630631
continue;
631632

632633
// We have an attribute that is active for the platform, but
@@ -2226,8 +2227,9 @@ bool AvailableAttr::isActivePlatform(const ASTContext &ctx) const {
22262227
return isPlatformActive(Platform, ctx.LangOpts);
22272228
}
22282229

2229-
bool BackDeployedAttr::isActivePlatform(const ASTContext &ctx) const {
2230-
return isPlatformActive(Platform, ctx.LangOpts);
2230+
bool BackDeployedAttr::isActivePlatform(const ASTContext &ctx,
2231+
bool forTargetVariant) const {
2232+
return isPlatformActive(Platform, ctx.LangOpts, forTargetVariant);
22312233
}
22322234

22332235
AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const {

lib/AST/Decl.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,9 @@ Decl::getIntroducedOSVersion(PlatformKind Kind) const {
565565
}
566566

567567
std::optional<llvm::VersionTuple>
568-
Decl::getBackDeployedBeforeOSVersion(ASTContext &Ctx) const {
569-
if (auto *attr = getAttrs().getBackDeployed(Ctx)) {
568+
Decl::getBackDeployedBeforeOSVersion(ASTContext &Ctx,
569+
bool forTargetVariant) const {
570+
if (auto *attr = getAttrs().getBackDeployed(Ctx, forTargetVariant)) {
570571
auto version = attr->Version;
571572
StringRef ignoredPlatformString;
572573
AvailabilityInference::updateBeforePlatformForFallback(
@@ -582,13 +583,22 @@ Decl::getBackDeployedBeforeOSVersion(ASTContext &Ctx) const {
582583

583584
// Accessors may inherit `@backDeployed`.
584585
if (auto *AD = dyn_cast<AccessorDecl>(this))
585-
return AD->getStorage()->getBackDeployedBeforeOSVersion(Ctx);
586+
return AD->getStorage()->getBackDeployedBeforeOSVersion(Ctx,
587+
forTargetVariant);
586588

587589
return std::nullopt;
588590
}
589591

590592
bool Decl::isBackDeployed(ASTContext &Ctx) const {
591-
return getBackDeployedBeforeOSVersion(Ctx) != std::nullopt;
593+
if (getBackDeployedBeforeOSVersion(Ctx))
594+
return true;
595+
596+
if (Ctx.LangOpts.TargetVariant) {
597+
if (getBackDeployedBeforeOSVersion(Ctx, /*forTargetVariant=*/true))
598+
return true;
599+
}
600+
601+
return false;
592602
}
593603

594604
bool Decl::hasBackDeployedAttr() const {

lib/SILGen/SILGenBackDeploy.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "SILGenFunction.h"
1414
#include "SILGenFunctionBuilder.h"
1515
#include "Scope.h"
16+
#include "swift/Basic/Platform.h"
1617
#include "swift/Basic/Assertions.h"
1718
#include "swift/SIL/SILDeclRef.h"
1819

@@ -50,6 +51,26 @@ static Type getResultInterfaceType(AbstractFunctionDecl *AFD) {
5051
llvm_unreachable("Unhandled AbstractFunctionDecl type");
5152
}
5253

54+
static SILValue emitZipperedBackDeployIfAvailableBooleanTestValue(
55+
SILGenFunction &SGF, AbstractFunctionDecl *AFD, SILLocation loc,
56+
SILBasicBlock *availableBB, SILBasicBlock *unavailableBB) {
57+
auto &ctx = SGF.getASTContext();
58+
assert(ctx.LangOpts.TargetVariant);
59+
60+
VersionRange OSVersion = VersionRange::all();
61+
if (auto version = AFD->getBackDeployedBeforeOSVersion(ctx)) {
62+
OSVersion = VersionRange::allGTE(*version);
63+
}
64+
65+
VersionRange VariantOSVersion = VersionRange::all();
66+
if (auto version =
67+
AFD->getBackDeployedBeforeOSVersion(ctx, /*forTargetVariant=*/true)) {
68+
VariantOSVersion = VersionRange::allGTE(*version);
69+
}
70+
71+
return SGF.emitZipperedOSVersionRangeCheck(loc, OSVersion, VariantOSVersion);
72+
}
73+
5374
/// Emit the following branch SIL instruction:
5475
/// \verbatim
5576
/// if #available(OSVersion) {
@@ -63,6 +84,14 @@ static void emitBackDeployIfAvailableCondition(SILGenFunction &SGF,
6384
SILLocation loc,
6485
SILBasicBlock *availableBB,
6586
SILBasicBlock *unavailableBB) {
87+
if (SGF.getASTContext().LangOpts.TargetVariant) {
88+
SILValue booleanTestValue =
89+
emitZipperedBackDeployIfAvailableBooleanTestValue(
90+
SGF, AFD, loc, availableBB, unavailableBB);
91+
SGF.B.createCondBranch(loc, booleanTestValue, availableBB, unavailableBB);
92+
return;
93+
}
94+
6695
auto version = AFD->getBackDeployedBeforeOSVersion(SGF.SGM.getASTContext());
6796
VersionRange OSVersion = VersionRange::empty();
6897
if (version.has_value()) {
@@ -76,7 +105,10 @@ static void emitBackDeployIfAvailableCondition(SILGenFunction &SGF,
76105
SILType i1 = SILType::getBuiltinIntegerType(1, SGF.getASTContext());
77106
booleanTestValue = SGF.B.createIntegerLiteral(loc, i1, 1);
78107
} else {
79-
booleanTestValue = SGF.emitOSVersionRangeCheck(loc, OSVersion);
108+
bool isMacCatalyst =
109+
tripleIsMacCatalystEnvironment(SGF.getASTContext().LangOpts.Target);
110+
booleanTestValue =
111+
SGF.emitOSVersionRangeCheck(loc, OSVersion, isMacCatalyst);
80112
}
81113

82114
SGF.B.createCondBranch(loc, booleanTestValue, availableBB, unavailableBB);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4611,7 +4611,7 @@ void AttributeChecker::checkBackDeployedAttrs(
46114611
auto *VD = cast<ValueDecl>(D);
46124612
std::map<PlatformKind, SourceLoc> seenPlatforms;
46134613

4614-
auto *ActiveAttr = D->getAttrs().getBackDeployed(Ctx);
4614+
auto *ActiveAttr = D->getAttrs().getBackDeployed(Ctx, false);
46154615

46164616
for (auto *Attr : Attrs) {
46174617
// Back deployment only makes sense for public declarations.
@@ -4698,7 +4698,6 @@ void AttributeChecker::checkBackDeployedAttrs(
46984698
if (!inheritsAvailabilityFromPlatform(unavailableAttr->Platform,
46994699
Attr->Platform)) {
47004700
auto platformString = prettyPlatformString(Attr->Platform);
4701-
47024701
llvm::VersionTuple ignoredVersion;
47034702

47044703
AvailabilityInference::updateBeforePlatformForFallback(
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// RUN: %target-swift-emit-sil -parse-as-library -module-name back_deploy %s -target x86_64-apple-macosx10.15 -target-variant x86_64-apple-ios13.1-macabi -verify
2+
// RUN: %target-swift-emit-silgen -parse-as-library -module-name back_deploy %s -target x86_64-apple-macosx10.15 -target-variant x86_64-apple-ios13.1-macabi | %FileCheck %s
3+
4+
// REQUIRES: OS=macosx || OS=maccatalyst
5+
6+
// -- Fallback definition of trivialFunc_iOS()
7+
// CHECK-LABEL: sil non_abi [serialized] [ossa] @$s11back_deploy15trivialFunc_iOSyyFTwB : $@convention(thin) () -> ()
8+
// CHECK: bb0:
9+
// CHECK: [[RESULT:%.*]] = tuple ()
10+
// CHECK: return [[RESULT]] : $()
11+
12+
// -- Back deployment thunk for trivialFunc_iOS()
13+
// CHECK-LABEL: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy15trivialFunc_iOSyyFTwb : $@convention(thin) () -> ()
14+
// CHECK: bb0:
15+
// CHECK: [[IOS_MAJOR:%.*]] = integer_literal $Builtin.Word, 51
16+
// CHECK: [[IOS_MINOR:%.*]] = integer_literal $Builtin.Word, 1
17+
// CHECK: [[IOS_PATCH:%.*]] = integer_literal $Builtin.Word, 0
18+
// CHECK: [[OSVFN:%.*]] = function_ref @$ss33_stdlib_isVariantOSVersionAtLeastyBi1_Bw_BwBwtF : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
19+
// CHECK: [[AVAIL:%.*]] = apply [[OSVFN]]([[IOS_MAJOR]], [[IOS_MINOR]], [[IOS_PATCH]]) : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
20+
// CHECK: cond_br [[AVAIL]], [[AVAIL_BB:bb[0-9]+]], [[UNAVAIL_BB:bb[0-9]+]]
21+
//
22+
// CHECK: [[UNAVAIL_BB]]:
23+
// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy15trivialFunc_iOSyyFTwB : $@convention(thin) () -> ()
24+
// CHECK: {{%.*}} = apply [[FALLBACKFN]]() : $@convention(thin) () -> ()
25+
// CHECK: br [[RETURN_BB:bb[0-9]+]]
26+
//
27+
// CHECK: [[AVAIL_BB]]:
28+
// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy15trivialFunc_iOSyyF : $@convention(thin) () -> ()
29+
// CHECK: {{%.*}} = apply [[ORIGFN]]() : $@convention(thin) () -> ()
30+
// CHECK: br [[RETURN_BB]]
31+
//
32+
// CHECK: [[RETURN_BB]]
33+
// CHECK: [[RESULT:%.*]] = tuple ()
34+
// CHECK: return [[RESULT]] : $()
35+
36+
// -- Original definition of trivialFunc_iOS()
37+
// CHECK-LABEL: sil [ossa] @$s11back_deploy15trivialFunc_iOSyyF : $@convention(thin) () -> ()
38+
@backDeployed(before: iOS 51.1)
39+
public func trivialFunc_iOS() {}
40+
41+
// -- Fallback definition of trivialFunc_macOS()
42+
// CHECK-LABEL: sil non_abi [serialized] [ossa] @$s11back_deploy17trivialFunc_macOSyyFTwB : $@convention(thin) () -> ()
43+
// CHECK: bb0:
44+
// CHECK: [[RESULT:%.*]] = tuple ()
45+
// CHECK: return [[RESULT]] : $()
46+
47+
// -- Back deployment thunk for trivialFunc_macOS()
48+
// CHECK-LABEL: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy17trivialFunc_macOSyyFTwb : $@convention(thin) () -> ()
49+
// CHECK: bb0:
50+
// CHECK: [[MACOS_MAJOR:%.*]] = integer_literal $Builtin.Word, 10
51+
// CHECK: [[MACOS_MINOR:%.*]] = integer_literal $Builtin.Word, 53
52+
// CHECK: [[MACOS_PATCH:%.*]] = integer_literal $Builtin.Word, 0
53+
// CHECK: [[OSVFN:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
54+
// CHECK: [[AVAIL:%.*]] = apply [[OSVFN]]([[MACOS_MAJOR]], [[MACOS_MINOR]], [[MACOS_PATCH]]) : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
55+
// CHECK: cond_br [[AVAIL]], [[AVAIL_BB:bb[0-9]+]], [[UNAVAIL_BB:bb[0-9]+]]
56+
//
57+
// CHECK: [[UNAVAIL_BB]]:
58+
// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy17trivialFunc_macOSyyFTwB : $@convention(thin) () -> ()
59+
// CHECK: {{%.*}} = apply [[FALLBACKFN]]() : $@convention(thin) () -> ()
60+
// CHECK: br [[RETURN_BB:bb[0-9]+]]
61+
//
62+
// CHECK: [[AVAIL_BB]]:
63+
// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy17trivialFunc_macOSyyF : $@convention(thin) () -> ()
64+
// CHECK: {{%.*}} = apply [[ORIGFN]]() : $@convention(thin) () -> ()
65+
// CHECK: br [[RETURN_BB]]
66+
//
67+
// CHECK: [[RETURN_BB]]
68+
// CHECK: [[RESULT:%.*]] = tuple ()
69+
// CHECK: return [[RESULT]] : $()
70+
71+
// -- Original definition of trivialFunc_macOS()
72+
// CHECK-LABEL: sil [available 10.53] [ossa] @$s11back_deploy17trivialFunc_macOSyyF : $@convention(thin) () -> ()
73+
@backDeployed(before: macOS 10.53)
74+
public func trivialFunc_macOS() {}
75+
76+
// -- Fallback definition of trivialFunc_iOS_macOS()
77+
// CHECK-LABEL: sil non_abi [serialized] [ossa] @$s11back_deploy019trivialFunc_iOS_macE0yyFTwB : $@convention(thin) () -> ()
78+
// CHECK: bb0:
79+
// CHECK: [[RESULT:%.*]] = tuple ()
80+
// CHECK: return [[RESULT]] : $()
81+
82+
// -- Back deployment thunk for trivialFunc_iOS_macOS()
83+
// CHECK-LABEL: sil non_abi [serialized] [thunk] [ossa] @$s11back_deploy019trivialFunc_iOS_macE0yyFTwb : $@convention(thin) () -> ()
84+
// CHECK: bb0:
85+
// CHECK: [[MACOS_MAJOR:%.*]] = integer_literal $Builtin.Word, 10
86+
// CHECK: [[MACOS_MINOR:%.*]] = integer_literal $Builtin.Word, 53
87+
// CHECK: [[MACOS_PATCH:%.*]] = integer_literal $Builtin.Word, 0
88+
// CHECK: [[IOS_MAJOR:%.*]] = integer_literal $Builtin.Word, 51
89+
// CHECK: [[IOS_MINOR:%.*]] = integer_literal $Builtin.Word, 1
90+
// CHECK: [[IOS_PATCH:%.*]] = integer_literal $Builtin.Word, 0
91+
// CHECK: [[OSVFN:%.*]] = function_ref @$ss042_stdlib_isOSVersionAtLeastOrVariantVersiondE0yBi1_Bw_BwBwBwBwBwtF : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
92+
// CHECK: [[AVAIL:%.*]] = apply [[OSVFN]]([[MACOS_MAJOR]], [[MACOS_MINOR]], [[MACOS_PATCH]], [[IOS_MAJOR]], [[IOS_MINOR]], [[IOS_PATCH]]) : $@convention(thin) (Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
93+
// CHECK: cond_br [[AVAIL]], [[AVAIL_BB:bb[0-9]+]], [[UNAVAIL_BB:bb[0-9]+]]
94+
//
95+
// CHECK: [[UNAVAIL_BB]]:
96+
// CHECK: [[FALLBACKFN:%.*]] = function_ref @$s11back_deploy019trivialFunc_iOS_macE0yyFTwB : $@convention(thin) () -> ()
97+
// CHECK: {{%.*}} = apply [[FALLBACKFN]]() : $@convention(thin) () -> ()
98+
// CHECK: br [[RETURN_BB:bb[0-9]+]]
99+
//
100+
// CHECK: [[AVAIL_BB]]:
101+
// CHECK: [[ORIGFN:%.*]] = function_ref @$s11back_deploy019trivialFunc_iOS_macE0yyF : $@convention(thin) () -> ()
102+
// CHECK: {{%.*}} = apply [[ORIGFN]]() : $@convention(thin) () -> ()
103+
// CHECK: br [[RETURN_BB]]
104+
//
105+
// CHECK: [[RETURN_BB]]
106+
// CHECK: [[RESULT:%.*]] = tuple ()
107+
// CHECK: return [[RESULT]] : $()
108+
109+
// -- Original definition of trivialFunc_iOS_macOS()
110+
// CHECK-LABEL: sil [available 10.53] [ossa] @$s11back_deploy019trivialFunc_iOS_macE0yyF : $@convention(thin) () -> ()
111+
@backDeployed(before: iOS 51.1, macOS 10.53)
112+
public func trivialFunc_iOS_macOS() {}
113+
114+
// -- Original definition of trivialFunc_watchOS()
115+
// CHECK-LABEL: sil [ossa] @$s11back_deploy19trivialFunc_watchOSyyF : $@convention(thin) () -> ()
116+
@backDeployed(before: watchOS 43.2)
117+
public func trivialFunc_watchOS() {}
118+
119+
// CHECK-LABEL: sil hidden [ossa] @$s11back_deploy6calleryyF : $@convention(thin) () -> ()
120+
func caller() {
121+
// -- Verify the thunk is not called
122+
// These functions are not back deployed on macOS so they should be called directly.
123+
// CHECK: {{%.*}} = function_ref @$s11back_deploy15trivialFunc_iOSyyF : $@convention(thin) () -> ()
124+
trivialFunc_iOS()
125+
// CHECK: {{%.*}} = function_ref @$s11back_deploy19trivialFunc_watchOSyyF : $@convention(thin) () -> ()
126+
trivialFunc_watchOS()
127+
128+
// -- Verify the thunk is called
129+
// CHECK: {{%.*}} = function_ref @$s11back_deploy17trivialFunc_macOSyyFTwb : $@convention(thin) () -> ()
130+
trivialFunc_macOS()
131+
// CHECK: {{%.*}} = function_ref @$s11back_deploy019trivialFunc_iOS_macE0yyFTwb : $@convention(thin) () -> ()
132+
trivialFunc_iOS_macOS()
133+
}

0 commit comments

Comments
 (0)