diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 4ff1060777427..9bf78418a4928 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -654,6 +654,10 @@ class ASTContext final { /// metadata. AvailabilityContext getPrespecializedGenericMetadataAvailability(); + /// Get the runtime availability of the swift_compareTypeContextDescriptors + /// for the target platform. + AvailabilityContext getCompareTypeContextDescriptorsAvailability(); + /// Get the runtime availability of features introduced in the Swift 5.2 /// compiler for the target platform. AvailabilityContext getSwift52Availability(); diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 6f4cefcdc35ed..e44996ebd6be8 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -307,6 +307,20 @@ const /// the same context. bool equalContexts(const ContextDescriptor *a, const ContextDescriptor *b); +/// Determines whether two type context descriptors describe the same type +/// context. +/// +/// Runtime availability: Swift 5.4. +/// +/// \param lhs The first type context descriptor to compare. +/// \param rhs The second type context descriptor to compare. +/// +/// \returns true if both describe the same type context, false otherwise. +SWIFT_RUNTIME_EXPORT +SWIFT_CC(swift) +bool swift_compareTypeContextDescriptors(const TypeContextDescriptor *lhs, + const TypeContextDescriptor *rhs); + /// Compute the bounds of class metadata with a resilient superclass. ClassMetadataBounds getResilientMetadataBounds( const ClassDescriptor *descriptor); diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index aad8ab980660a..052ef6e78b7f7 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -616,6 +616,18 @@ FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, ARGS(SizeTy, TypeMetadataPtrTy), ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields +// SWIFT_RUNTIME_EXPORT +// SWIFT_CC(swift) +// bool swift_compareTypeContextDescriptors(const TypeContextDescriptor *lhs, +// const TypeContextDescriptor *rhs); +FUNCTION(CompareTypeContextDescriptors, + swift_compareTypeContextDescriptors, SwiftCC, + CompareTypeContextDescriptorsAvailability, + RETURNS(Int1Ty), + ARGS(TypeContextDescriptorPtrTy, + TypeContextDescriptorPtrTy), + ATTRS(NoUnwind, ReadNone)) + // MetadataResponse swift_getSingletonMetadata(MetadataRequest request, // TypeContextDescriptor *type); FUNCTION(GetSingletonMetadata, swift_getSingletonMetadata, diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 7eacce69db72e..4d5f7a093806d 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -295,6 +295,10 @@ AvailabilityContext ASTContext::getPrespecializedGenericMetadataAvailability() { return getSwift53Availability(); } +AvailabilityContext ASTContext::getCompareTypeContextDescriptorsAvailability() { + return getSwiftFutureAvailability(); +} + AvailabilityContext ASTContext::getSwift52Availability() { auto target = LangOpts.Target; diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 87f3207b6ef09..e48694064d49c 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -650,6 +650,16 @@ namespace RuntimeConstants { } return RuntimeAvailability::AlwaysAvailable; } + + RuntimeAvailability + CompareTypeContextDescriptorsAvailability(ASTContext &Context) { + auto featureAvailability = + Context.getCompareTypeContextDescriptorsAvailability(); + if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) { + return RuntimeAvailability::ConditionallyAvailable; + } + return RuntimeAvailability::AlwaysAvailable; + } } // namespace RuntimeConstants // We don't use enough attributes to justify generalizing the diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 3bbc55b13f1ed..baef3814c72fe 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -1918,6 +1918,33 @@ bool swift::equalContexts(const ContextDescriptor *a, } } +SWIFT_CC(swift) +bool swift::swift_compareTypeContextDescriptors( + const TypeContextDescriptor *a, const TypeContextDescriptor *b) { + // The implementation is the same as the implementation of + // swift::equalContexts except that the handling of non-type + // context descriptors and casts to TypeContextDescriptor are removed. + + // Fast path: pointer equality. + if (a == b) return true; + + // If either context is null, we're done. + if (a == nullptr || b == nullptr) + return false; + + // If either descriptor is known to be unique, we're done. + if (a->isUnique() || b->isUnique()) return false; + + // Do the kinds match? + if (a->getKind() != b->getKind()) return false; + + // Do the parents match? + if (!equalContexts(a->Parent.get(), b->Parent.get())) + return false; + + return TypeContextIdentity(a) == TypeContextIdentity(b); +} + /***************************************************************************/ /*** Common value witnesses ************************************************/ /***************************************************************************/