Skip to content

Commit 2b20273

Browse files
authored
Merge pull request #39564 from DougGregor/back-deploy-more-fixes-5.5
Concurrency back-deployment fixes for exclusivity, isolated parameters, @objc actors
2 parents e21086d + fa578df commit 2b20273

27 files changed

+292
-187
lines changed

include/swift/Basic/Platform.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ namespace swift {
5555
bool triplesAreValidForZippering(const llvm::Triple &target,
5656
const llvm::Triple &targetVariant);
5757

58-
/// Returns true if the given triple represents an OS that ships with
59-
/// ABI-stable swift libraries (eg. in /usr/lib/swift).
60-
bool tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple);
58+
/// Returns true if the given triple represents an OS that has all the
59+
/// "built-in" ABI-stable libraries (stdlib and _Concurrency)
60+
/// (eg. in /usr/lib/swift).
61+
bool tripleRequiresRPathForSwiftLibrariesInOS(const llvm::Triple &triple);
6162

6263
/// Returns the platform name for a given target triple.
6364
///

include/swift/Runtime/BackDeployment.h

Lines changed: 0 additions & 45 deletions
This file was deleted.

include/swift/Runtime/Config.h

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,34 +100,21 @@
100100
/// from ObjC classes?
101101
#ifndef SWIFT_CLASS_IS_SWIFT_MASK
102102

103-
// Non-Apple platforms always use 1.
104-
# if !defined(__APPLE__)
105-
# define SWIFT_CLASS_IS_SWIFT_MASK 1ULL
106-
107-
// Builds for Swift-in-the-OS always use 2.
108-
# elif SWIFT_BNI_OS_BUILD
109-
# define SWIFT_CLASS_IS_SWIFT_MASK 2ULL
110-
111-
// Builds for Xcode always use 1.
112-
# elif SWIFT_BNI_XCODE_BUILD
113-
# define SWIFT_CLASS_IS_SWIFT_MASK 1ULL
114-
115103
// Compatibility hook libraries cannot rely on the "is swift" bit being either
116104
// value, since they must work with both OS and Xcode versions of the libraries.
117105
// Generate a reference to a nonexistent symbol so that we get obvious linker
118106
// errors if we try.
119-
# elif SWIFT_COMPATIBILITY_LIBRARY
107+
# if SWIFT_COMPATIBILITY_LIBRARY
120108
extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTLY__;
121109
# define SWIFT_CLASS_IS_SWIFT_MASK __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTLY__
122110

123-
// Other builds (such as local builds on developers' computers)
124-
// dynamically choose the bit at runtime based on the current OS
125-
// version.
111+
// Apple platforms always use 2
112+
# elif defined(__APPLE__)
113+
# define SWIFT_CLASS_IS_SWIFT_MASK 2ULL
114+
115+
// Non-Apple platforms always use 1.
126116
# else
127-
# define SWIFT_CLASS_IS_SWIFT_MASK _swift_classIsSwiftMask
128-
# define SWIFT_CLASS_IS_SWIFT_MASK_GLOBAL_VARIABLE 1
129-
# define SWIFT_BUILD_HAS_BACK_DEPLOYMENT 1
130-
# include "BackDeployment.h"
117+
# define SWIFT_CLASS_IS_SWIFT_MASK 1ULL
131118

132119
# endif
133120
#endif

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,12 @@ FUNCTION(LookUpClass, objc_lookUpClass, C_CC, AlwaysAvailable,
11241124
ARGS(Int8PtrTy),
11251125
ATTRS(NoUnwind, ReadNone))
11261126

1127+
// Class objc_setSuperclass(Class cls, Class newSuper);
1128+
FUNCTION(SetSuperclass, class_setSuperclass, C_CC, AlwaysAvailable,
1129+
RETURNS(ObjCClassPtrTy),
1130+
ARGS(ObjCClassPtrTy, ObjCClassPtrTy),
1131+
ATTRS(NoUnwind))
1132+
11271133
// Metadata *swift_getObjectType(id object);
11281134
FUNCTION(GetObjectType, swift_getObjectType, C_CC, AlwaysAvailable,
11291135
RETURNS(TypeMetadataPtrTy),
@@ -1384,6 +1390,10 @@ FUNCTION(ObjCGetClass, objc_getClass, C_CC, AlwaysAvailable,
13841390
RETURNS(ObjCClassPtrTy),
13851391
ARGS(Int8PtrTy),
13861392
ATTRS(NoUnwind))
1393+
FUNCTION(ObjCGetRequiredClass, objc_getRequiredClass, C_CC, AlwaysAvailable,
1394+
RETURNS(ObjCClassPtrTy),
1395+
ARGS(Int8PtrTy),
1396+
ATTRS(NoUnwind))
13871397
FUNCTION(ObjCGetMetaClass, objc_getMetaClass, C_CC, AlwaysAvailable,
13881398
RETURNS(ObjCClassPtrTy),
13891399
ARGS(Int8PtrTy),

lib/Basic/Platform.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,25 @@ bool swift::triplesAreValidForZippering(const llvm::Triple &target,
7979
return false;
8080
}
8181

82-
bool swift::tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple) {
82+
bool swift::tripleRequiresRPathForSwiftLibrariesInOS(
83+
const llvm::Triple &triple) {
8384
if (triple.isMacOSX()) {
84-
// macOS 10.14.4 contains a copy of Swift, but the linker will still use an
85-
// rpath-based install name until 10.15.
86-
return triple.isMacOSXVersionLT(10, 15);
85+
// macOS versions before 10.14.4 don't have Swift in the OS
86+
// (the linker still uses an rpath-based install name until 10.15).
87+
// macOS versions before 12.0 don't have _Concurrency in the OS.
88+
return triple.isMacOSXVersionLT(12, 0);
8789
}
8890

8991
if (triple.isiOS()) {
90-
return triple.isOSVersionLT(12, 2);
92+
// iOS versions before 12.2 don't have Swift in the OS.
93+
// iOS versions before 15.0 don't have _Concurrency in the OS.
94+
return triple.isOSVersionLT(15, 0);
9195
}
9296

9397
if (triple.isWatchOS()) {
94-
return triple.isOSVersionLT(5, 2);
98+
// watchOS versions before 5.2 don't have Swift in the OS.
99+
// watchOS versions before 8.0 don't have _Concurrency in the OS.
100+
return triple.isOSVersionLT(8, 0);
95101
}
96102

97103
// Other platforms don't have Swift installed as part of the OS by default.

lib/Driver/DarwinToolChains.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
452452
Arguments.push_back("-rpath");
453453
Arguments.push_back(context.Args.MakeArgString(path));
454454
}
455-
} else if (!tripleRequiresRPathForSwiftInOS(getTriple()) ||
455+
} else if (!tripleRequiresRPathForSwiftLibrariesInOS(getTriple()) ||
456456
context.Args.hasArg(options::OPT_no_stdlib_rpath)) {
457457
// If targeting an OS with Swift in /usr/lib/swift, the LC_ID_DYLIB
458458
// install_name the stdlib will be an absolute path like
@@ -480,9 +480,11 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
480480
// package isn't installed.
481481
Arguments.push_back("-rpath");
482482
Arguments.push_back(context.Args.MakeArgString("/usr/lib/swift"));
483-
// We don't need an rpath for /System/iOSSupport/usr/lib/swift because...
484-
assert(!tripleIsMacCatalystEnvironment(getTriple())
485-
&& "macCatalyst not supported without Swift-in-the-OS");
483+
// We don’t need an rpath for /System/iOSSupport/usr/lib/swift because:
484+
// 1. The standard library and overlays were part of the OS before
485+
// Catalyst was introduced, so they are always available for Catalyst.
486+
// 2. The _Concurrency back-deployment library is zippered, whereas only
487+
// unzippered frameworks need an unzippered twin in /System/iOSSupport.
486488
}
487489
}
488490

lib/FrontendTool/FrontendTool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1884,7 +1884,7 @@ static void printTripleInfo(const llvm::Triple &triple,
18841884
}
18851885

18861886
out << " \"librariesRequireRPath\": "
1887-
<< (tripleRequiresRPathForSwiftInOS(triple) ? "true" : "false")
1887+
<< (tripleRequiresRPathForSwiftLibrariesInOS(triple) ? "true" : "false")
18881888
<< "\n";
18891889

18901890
out << " }";

lib/IRGen/GenClass.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ void IRGenModule::emitClassDecl(ClassDecl *D) {
960960
emitFieldDescriptor(D);
961961

962962
IRGen.addClassForEagerInitialization(D);
963+
IRGen.addBackDeployedObjCActorInitialization(D);
963964

964965
emitNestedTypeDecls(D->getMembers());
965966
}
@@ -2527,15 +2528,24 @@ ClassDecl *irgen::getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *C) {
25272528

25282529
ClassDecl *
25292530
irgen::getSuperclassDeclForMetadata(IRGenModule &IGM, ClassDecl *C) {
2530-
if (C->isNativeNSObjectSubclass())
2531+
if (C->isNativeNSObjectSubclass()) {
2532+
// When concurrency isn't available in the OS, use NSObject instead.
2533+
if (!IGM.isConcurrencyAvailable()) {
2534+
return IGM.getObjCRuntimeBaseClass(
2535+
IGM.Context.getSwiftId(KnownFoundationEntity::NSObject),
2536+
IGM.Context.getIdentifier("NSObject"));
2537+
}
2538+
25312539
return IGM.getSwiftNativeNSObjectDecl();
2540+
}
25322541
return C->getSuperclassDecl();
25332542
}
25342543

25352544
CanType irgen::getSuperclassForMetadata(IRGenModule &IGM, ClassDecl *C) {
2536-
if (C->isNativeNSObjectSubclass())
2537-
return IGM.getSwiftNativeNSObjectDecl()->getDeclaredInterfaceType()
2538-
->getCanonicalType();
2545+
if (C->isNativeNSObjectSubclass()) {
2546+
return getSuperclassDeclForMetadata(IGM, C)->getDeclaredInterfaceType()
2547+
->getCanonicalType();
2548+
}
25392549
if (auto superclass = C->getSuperclass())
25402550
return superclass->getCanonicalType();
25412551
return CanType();
@@ -2544,9 +2554,10 @@ CanType irgen::getSuperclassForMetadata(IRGenModule &IGM, ClassDecl *C) {
25442554
CanType irgen::getSuperclassForMetadata(IRGenModule &IGM, CanType type,
25452555
bool useArchetypes) {
25462556
auto cls = type->getClassOrBoundGenericClass();
2547-
if (cls->isNativeNSObjectSubclass())
2548-
return IGM.getSwiftNativeNSObjectDecl()->getDeclaredInterfaceType()
2549-
->getCanonicalType();
2557+
if (cls->isNativeNSObjectSubclass()) {
2558+
return getSuperclassDeclForMetadata(IGM, cls)->getDeclaredInterfaceType()
2559+
->getCanonicalType();
2560+
}
25502561
if (auto superclass = type->getSuperclass(useArchetypes))
25512562
return superclass->getCanonicalType();
25522563
return CanType();

lib/IRGen/GenDecl.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,48 @@ void IRGenerator::emitEagerClassInitialization() {
18611861
llvm::appendToGlobalCtors(IGM->Module, RegisterFn, 60000, nullptr);
18621862
}
18631863

1864+
void IRGenerator::emitObjCActorsNeedingSuperclassSwizzle() {
1865+
if (ObjCActorsNeedingSuperclassSwizzle.empty())
1866+
return;
1867+
1868+
// Emit the register function in the primary module.
1869+
IRGenModule *IGM = getPrimaryIGM();
1870+
1871+
llvm::Function *RegisterFn = llvm::Function::Create(
1872+
llvm::FunctionType::get(IGM->VoidTy, false),
1873+
llvm::GlobalValue::PrivateLinkage,
1874+
"_swift_objc_actor_initialization");
1875+
IGM->Module.getFunctionList().push_back(RegisterFn);
1876+
IRGenFunction RegisterIGF(*IGM, RegisterFn);
1877+
RegisterFn->setAttributes(IGM->constructInitialAttributes());
1878+
RegisterFn->setCallingConv(IGM->DefaultCC);
1879+
1880+
// Look up the SwiftNativeNSObject class.
1881+
auto swiftNativeNSObjectName =
1882+
IGM->getAddrOfGlobalString("SwiftNativeNSObject");
1883+
auto swiftNativeNSObjectClass = RegisterIGF.Builder.CreateCall(
1884+
RegisterIGF.IGM.getObjCGetRequiredClassFn(), swiftNativeNSObjectName);
1885+
1886+
for (ClassDecl *CD : ObjCActorsNeedingSuperclassSwizzle) {
1887+
// The @objc actor class.
1888+
llvm::Value *classRef = RegisterIGF.emitTypeMetadataRef(
1889+
CD->getDeclaredInterfaceType()->getCanonicalType());
1890+
classRef = RegisterIGF.Builder.CreateBitCast(classRef, IGM->ObjCClassPtrTy);
1891+
1892+
// Set its superclass to SwiftNativeNSObject.
1893+
RegisterIGF.Builder.CreateCall(
1894+
RegisterIGF.IGM.getSetSuperclassFn(),
1895+
{ classRef, swiftNativeNSObjectClass});
1896+
}
1897+
RegisterIGF.Builder.CreateRetVoid();
1898+
1899+
// Add the registration function as a static initializer. We use a priority
1900+
// slightly lower than used for C++ global constructors, so that the code is
1901+
// executed before C++ global constructors (in case someone manages to access
1902+
// an @objc actor from a global constructor).
1903+
llvm::appendToGlobalCtors(IGM->Module, RegisterFn, 60000, nullptr);
1904+
}
1905+
18641906
/// Emit symbols for eliminated dead methods, which can still be referenced
18651907
/// from other modules. This happens e.g. if a public class contains a (dead)
18661908
/// private method.

lib/IRGen/GenReflection.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,15 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
178178
// related to concurrency.
179179
bool needsConcurrency = type.findIf([](CanType t) -> bool {
180180
if (auto fn = dyn_cast<AnyFunctionType>(t)) {
181-
return fn->isAsync() || fn->isSendable() || fn->hasGlobalActor();
181+
if (fn->isAsync() || fn->isSendable() || fn->hasGlobalActor())
182+
return true;
183+
184+
for (const auto param: fn->getParams()) {
185+
if (param.isIsolated())
186+
return true;
187+
}
188+
189+
return false;
182190
}
183191
return false;
184192
});

0 commit comments

Comments
 (0)