Skip to content

[5.3] Compatibility51: Backport the 5.2 implementation of the conformance cache. #31281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/Runtime/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@
# elif SWIFT_BNI_XCODE_BUILD
# define SWIFT_CLASS_IS_SWIFT_MASK 1ULL

// Compatibility hook libraries cannot rely on the "is swift" bit being either
// value, since they must work with both OS and Xcode versions of the libraries.
// Generate a reference to a nonexistent symbol so that we get obvious linker
// errors if we try.
# elif SWIFT_COMPATIBILITY_LIBRARY
extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTLY__;
# define SWIFT_CLASS_IS_SWIFT_MASK __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTLY__

// Other builds (such as local builds on developers' computers)
// dynamically choose the bit at runtime based on the current OS
// version.
Expand Down
4 changes: 4 additions & 0 deletions stdlib/toolchain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ else()
add_compile_definitions(LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1)
endif()

# Compatibility libraries build in a special alternate universe that can't
# directly link to most OS runtime libraries, and have to access the
# runtime being patched only through public ABI.
list(APPEND CXX_COMPILE_FLAGS "-DSWIFT_COMPATIBILITY_LIBRARY=1")

add_subdirectory(legacy_layouts)
add_subdirectory(Compatibility50)
Expand Down
6 changes: 6 additions & 0 deletions stdlib/toolchain/Compatibility50/Overrides.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//

#include "Overrides.h"
#include "../Compatibility51/Overrides.h"
#include "../../public/runtime/CompatibilityOverride.h"

#include <dlfcn.h>
Expand All @@ -34,6 +35,11 @@ OverrideSection Swift50Overrides
__attribute__((used, section("__DATA,__swift_hooks"))) = {
.version = 0,
.conformsToProtocol = swift50override_conformsToProtocol,
// We use the same hook for conformsToSwiftProtocol as we do for a 5.1
// runtime, so reference the override from the Compatibility51 library.
// If we're back deploying to Swift 5.0, we also have to support 5.1, so
// the Compatibility51 library is always linked when the 50 library is.
.conformsToSwiftProtocol = swift51override_conformsToSwiftProtocol,
};

// Allow this library to get force-loaded by autolinking
Expand Down
4 changes: 2 additions & 2 deletions stdlib/toolchain/Compatibility50/Overrides.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//===--- Overrides.cpp - Compat overrides for Swift 5.0 runtime ----s------===//
//===--- Overrides.h --- Compat overrides for Swift 5.0 runtime ----s------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2020 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
Expand Down
43 changes: 4 additions & 39 deletions stdlib/toolchain/Compatibility50/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@ using mach_header_platform = mach_header;
/// This lives within SEG_TEXT.
constexpr const char ProtocolConformancesSection[] = "__swift5_proto";

// Clone of private function getRootSuperclass. This returns the SwiftObject
// class in the ABI-stable dylib, regardless of what the local runtime build
// does, since we're always patching an ABI-stable dylib.
__attribute__((visibility("hidden"), weak))
const ClassMetadata *swift::getRootSuperclass() {
auto theClass = SWIFT_LAZY_CONSTANT(objc_getClass("_TtCs12_SwiftObject"));
return (const ClassMetadata *)theClass;
}

// A dummy target context descriptor to use in conformance records which point
// to a NULL descriptor. It doesn't have to be completely valid, just something
// that code reading conformance descriptors will ignore.
Expand Down Expand Up @@ -90,35 +81,9 @@ static void registerAddImageCallback(void *) {
_dyld_register_func_for_add_image(addImageCallback);
}

static const Metadata *getObjCClassMetadata(const ClassMetadata *c) {
// Look up swift_getObjCClassMetadata dynamically. This handles the case
// where the main executable can't link against libswiftCore.dylib because
// it will be loaded dynamically from a location that isn't known at build
// time.
using FPtr = const Metadata *(*)(const ClassMetadata *);
FPtr func = SWIFT_LAZY_CONSTANT(
reinterpret_cast<FPtr>(dlsym(RTLD_DEFAULT, "swift_getObjCClassMetadata")));

return func(c);
}

// Clone of private helper swift::_swiftoverride_class_getSuperclass
// for use in the override implementation.
static const Metadata *_swift50override_class_getSuperclass(
const Metadata *theClass) {
if (const ClassMetadata *classType = theClass->getClassObject()) {
if (classHasSuperclass(classType))
return getObjCClassMetadata(classType->Superclass);
}

if (const ForeignClassMetadata *foreignClassType
= dyn_cast<ForeignClassMetadata>(theClass)) {
if (const Metadata *superclass = foreignClassType->Superclass)
return superclass;
}

return nullptr;
}
// Defined in libswiftCompatibility51, which is always linked if we link against
// libswiftCompatibility50
const Metadata *_swiftoverride_class_getSuperclass(const Metadata *theClass);

const WitnessTable *
swift::swift50override_conformsToProtocol(const Metadata *type,
Expand All @@ -138,7 +103,7 @@ swift::swift50override_conformsToProtocol(const Metadata *type,
auto result = original_conformsToProtocol(type, protocol);
if (result)
return result;
} while ((type = _swift50override_class_getSuperclass(type)));
} while ((type = _swiftoverride_class_getSuperclass(type)));

return nullptr;
}
1 change: 1 addition & 0 deletions stdlib/toolchain/Compatibility51/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ set(library_name "swiftCompatibility51")

add_swift_target_library("${library_name}" STATIC
Overrides.cpp
ProtocolConformance.cpp

TARGET_SDKS ${SWIFT_APPLE_PLATFORMS}

Expand Down
Loading