diff --git a/SwiftCompilerSources/CMakeLists.txt b/SwiftCompilerSources/CMakeLists.txt index 7a32e273c5df5..cc24ca661126e 100644 --- a/SwiftCompilerSources/CMakeLists.txt +++ b/SwiftCompilerSources/CMakeLists.txt @@ -295,8 +295,6 @@ else() set(compatibility_libs "swiftCompatibility50-${platform}" "swiftCompatibility51-${platform}" - "swiftCompatibility56-${platform}" - "swiftCompatibilityConcurrency-${platform}" "swiftCompatibilityDynamicReplacements-${platform}") list(APPEND b0_deps ${compatibility_libs}) diff --git a/docs/CppInteroperability/SwiftTypeRepresentationInC++.md b/docs/CppInteroperability/SwiftTypeRepresentationInC++.md index 8a36a9bdea84e..8255dc56c1443 100644 --- a/docs/CppInteroperability/SwiftTypeRepresentationInC++.md +++ b/docs/CppInteroperability/SwiftTypeRepresentationInC++.md @@ -8,7 +8,7 @@ C++. ### Value Types -1) Primitive Swift types like `Int`, `Float` , `OpaquePointer`, `UnsafePointer?` are mapped to primitive C++ types. `int` , `float`, `void *`, int `* _Nullable` . +1) Primitive Swift types like `Int`, `Float` , `OpaquePointer`, `UnsafePointer?` are mapped to primitive C++ types. `int` , `float`, `void *`, `int * _Nullable`. * Debug info: Does C++ debug info suffices? @@ -29,13 +29,23 @@ class swift::String { ```c++ class Foundation::URL { ... - union { - alignas(8) char buffer[8]; // Swift value is stored here. - void *resilientPtr; - }; + uintptr_t pointer; // pointer has alignment to compute buffer offset? + alignas(N) char buffer[M]; // Swift value is stored here. }; ``` +concrete examples: + +```c++ +// representation for buffer aligned at 8: +{/*pointer=*/0x3, ....}; // buffer is alignas(2^3 = 8) + +// representation for buffer aligned at 16: +{/*pointer=*/0x4, ....}; // buffer is alignas(2^4 = 16) + +// where pointer < 10 for inline stores. +``` + * Debug info: ... @@ -44,10 +54,8 @@ class Foundation::URL { ```c++ class CryptoKit::SHA256 { ... - union { - alignas(8) char buffer[8]; - void *resilientPtr; // Swift value is stored on the heap pointed by this pointer. - }; + uintptr_t pointer; // Swift value is stored on the heap pointed by this pointer. + alignas(8) char buffer[8]; }; ``` @@ -66,15 +74,13 @@ class swift::Array { * Debug info: ... -6) Generic opaque-layout / resilient / opaque-layout template type params Swift value type, e.g. SHA256`?`, is mapped to a C++ class that stores the value boxed up on the heap, e.g.: +6) Generic opaque-layout / resilient / opaque-layout template type params Swift value type, e.g. `SHA256?`, is mapped to a C++ class that stores the value boxed up on the heap, e.g.: ```c++ class swift::Optional { ... - union { - alignas(8) char buffer[8]; - void *resilientPtr; // Swift value is stored on the heap pointed by this pointer. - }; + uintptr_t pointer; // Swift value is stored on the heap pointed by this pointer. + alignas(N) char buffer[M]; } ``` diff --git a/docs/Lexicon.md b/docs/Lexicon.md index 51264ef16a25a..fd24af590c699 100644 --- a/docs/Lexicon.md +++ b/docs/Lexicon.md @@ -49,7 +49,7 @@ thunk helpers" sometimes seen in Swift backtraces come from.) Broadly, an "access path" is a list of "accesses" which must be chained together to compute some output from an input. For instance, the generics system has a -type called a `ConformanceAccessPath` which explains how to, for example, +type called a `ConformancePath` which explains how to, for example, walk from `T: Collection` to `T: Sequence` to `T.Iterator: IteratorProtocol`. There are several different kinds of "access path" in different parts of the compiler, but they all follow this basic theme. diff --git a/include/swift/AST/ASTMangler.h b/include/swift/AST/ASTMangler.h index 87a8956b08b6e..0bd3fc15ad51d 100644 --- a/include/swift/AST/ASTMangler.h +++ b/include/swift/AST/ASTMangler.h @@ -25,7 +25,7 @@ class NamedDecl; namespace swift { class AbstractClosureExpr; -class ConformanceAccessPath; +class ConformancePath; class RootProtocolConformance; namespace Mangle { @@ -560,7 +560,7 @@ class ASTMangler : public Mangler { void appendConcreteProtocolConformance( const ProtocolConformance *conformance, GenericSignature sig); - void appendDependentProtocolConformance(const ConformanceAccessPath &path, + void appendDependentProtocolConformance(const ConformancePath &path, GenericSignature sig); void appendOpParamForLayoutConstraint(LayoutConstraint Layout); diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 4145bc87d3f46..b05d5cccca7f6 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -70,7 +70,7 @@ namespace rewriting { /// \c Sequence conformance of \c C (because \c Collection inherits /// \c Sequence). Finally, it extracts the conformance of the associated type /// \c Iterator to \c IteratorProtocol from the \c Sequence protocol. -class ConformanceAccessPath { +class ConformancePath { public: /// An entry in the conformance access path, which is described by the /// dependent type on which the conformance is stated as the protocol to @@ -80,7 +80,7 @@ class ConformanceAccessPath { private: ArrayRef path; - ConformanceAccessPath(ArrayRef path) : path(path) {} + ConformancePath(ArrayRef path) : path(path) {} friend class GenericSignatureImpl; friend class rewriting::RequirementMachine; @@ -213,9 +213,9 @@ class GenericSignature { SmallVector requirementsNotSatisfiedBy(GenericSignature otherSig) const; - /// Return the canonical version of the given type under this generic + /// Return the reduced version of the given type under this generic /// signature. - CanType getCanonicalTypeInContext(Type type) const; + CanType getReducedType(Type type) const; /// Check invariants. void verify() const; @@ -383,7 +383,7 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final /// generic signature. /// /// The type parameters must be known to not be concrete within the context. - bool areSameTypeParameterInContext(Type type1, Type type2) const; + bool areReducedTypeParametersEqual(Type type1, Type type2) const; /// Determine if \c sig can prove \c requirement, meaning that it can deduce /// T: Foo or T == U (etc.) with the information it knows. This includes @@ -392,26 +392,26 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final bool isRequirementSatisfied( Requirement requirement, bool allowMissing = false) const; - bool isCanonicalTypeInContext(Type type) const; + bool isReducedType(Type type) const; /// Determine whether the given type parameter is defined under this generic /// signature. - bool isValidTypeInContext(Type type) const; + bool isValidTypeParameter(Type type) const; - /// Retrieve the conformance access path used to extract the conformance of + /// Retrieve the conformance path used to extract the conformance of /// interface \c type to the given \c protocol. /// - /// \param type The interface type whose conformance access path is to be + /// \param type The type parameter whose conformance path is to be /// queried. /// \param protocol A protocol to which \c type conforms. /// - /// \returns the conformance access path that starts at a requirement of + /// \returns the conformance path that starts at a requirement of /// this generic signature and ends at the conformance that makes \c type /// conform to \c protocol. /// - /// \seealso ConformanceAccessPath - ConformanceAccessPath getConformanceAccessPath(Type type, - ProtocolDecl *protocol) const; + /// \seealso ConformancePath + ConformancePath getConformancePath(Type type, + ProtocolDecl *protocol) const; /// Lookup a nested type with the given name within this type parameter. TypeDecl *lookupNestedType(Type type, Identifier name) const; @@ -487,9 +487,9 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final SmallVector requirementsNotSatisfiedBy(GenericSignature otherSig) const; - /// Return the canonical version of the given type under this generic + /// Return the reduced version of the given type under this generic /// signature. - CanType getCanonicalTypeInContext(Type type) const; + CanType getReducedType(Type type) const; }; void simple_display(raw_ostream &out, GenericSignature sig); diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index d01a8c0bbd293..4d26b2801bfb2 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -503,9 +503,9 @@ class alignas(1 << TypeAlignInBits) TypeBase return const_cast(this)->computeCanonicalType(); } - /// getCanonicalType - Stronger canonicalization which folds away equivalent + /// getReducedType - Stronger canonicalization which folds away equivalent /// associated types, or type parameters that have been made concrete. - CanType getCanonicalType(GenericSignature sig); + CanType getReducedType(GenericSignature sig); /// Canonical protocol composition types are minimized only to a certain /// degree to preserve ABI compatibility. This routine enables performing diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def index 6300f1f0c1d0e..4f7d9d2ceb734 100644 --- a/include/swift/Basic/Statistics.def +++ b/include/swift/Basic/Statistics.def @@ -230,16 +230,8 @@ FRONTEND_STATISTIC(Sema, NumRequirementMachineCompletionSteps) /// Number of new rules added by concrete term unification. FRONTEND_STATISTIC(Sema, NumRequirementMachineUnifiedConcreteTerms) -/// Number of generic signature builders constructed. Rough proxy for -/// amount of work the GSB does analyzing type signatures. -FRONTEND_STATISTIC(Sema, NumGenericSignatureBuilders) - -/// Number of steps in the GSB's redundant requirements algorithm, which is in -/// the worst-case exponential. -FRONTEND_STATISTIC(Sema, NumRedundantRequirementSteps) - -/// Number of conformance access paths we had to compute. -FRONTEND_STATISTIC(Sema, NumConformanceAccessPathsRecorded) +/// Number of conformance paths we had to compute. +FRONTEND_STATISTIC(Sema, NumConformancePathsRecorded) /// Number of lazy requirement signatures registered. FRONTEND_STATISTIC(Sema, NumLazyRequirementSignatures) diff --git a/include/swift/Frontend/BackDeploymentLibs.def b/include/swift/Frontend/BackDeploymentLibs.def index 9f12ae773e7dc..58eefb62bf493 100644 --- a/include/swift/Frontend/BackDeploymentLibs.def +++ b/include/swift/Frontend/BackDeploymentLibs.def @@ -28,6 +28,5 @@ BACK_DEPLOYMENT_LIB((5, 0), all, "swiftCompatibility50") BACK_DEPLOYMENT_LIB((5, 1), all, "swiftCompatibility51") BACK_DEPLOYMENT_LIB((5, 0), executable, "swiftCompatibilityDynamicReplacements") BACK_DEPLOYMENT_LIB((5, 4), all, "swiftCompatibilityConcurrency") -BACK_DEPLOYMENT_LIB((5, 6), all, "swiftCompatibility56") #undef BACK_DEPLOYMENT_LIB diff --git a/include/swift/SIL/AbstractionPattern.h b/include/swift/SIL/AbstractionPattern.h index 4d3f8f1ec62ad..631717e24dda2 100644 --- a/include/swift/SIL/AbstractionPattern.h +++ b/include/swift/SIL/AbstractionPattern.h @@ -514,7 +514,7 @@ class AbstractionPattern { OrigType = origType; GenericSig = CanGenericSignature(); if (OrigType->hasTypeParameter()) { - assert(OrigType == signature.getCanonicalTypeInContext(origType)); + assert(OrigType == signature.getReducedType(origType)); GenericSig = signature; } } diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h index 0b6ee4942f1b3..72318d31584ca 100644 --- a/include/swift/SIL/SILGlobalVariable.h +++ b/include/swift/SIL/SILGlobalVariable.h @@ -125,6 +125,12 @@ class SILGlobalVariable return getLoweredTypeInContext(context).castTo(); } + void unsafeSetLoweredType(SILType newType) { LoweredType = newType; } + void unsafeAppend(SILInstruction *i) { StaticInitializerBlock.push_back(i); } + void unsafeRemove(SILInstruction *i, SILModule &mod) { + StaticInitializerBlock.erase(i, mod); + } + StringRef getName() const { return Name; } void setDeclaration(bool isD) { IsDeclaration = isD; } diff --git a/include/swift/SILOptimizer/Analysis/DifferentiableActivityAnalysis.h b/include/swift/SILOptimizer/Analysis/DifferentiableActivityAnalysis.h index 209aec0fdc252..b8b678fe0584c 100644 --- a/include/swift/SILOptimizer/Analysis/DifferentiableActivityAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/DifferentiableActivityAnalysis.h @@ -135,7 +135,7 @@ class DifferentiableActivityInfo { auto type = value->getType().getASTType(); // Remap archetypes in the derivative generic signature, if it exists. if (type->hasArchetype()) { - type = derivativeGenericSignature.getCanonicalTypeInContext( + type = derivativeGenericSignature.getReducedType( type->mapTypeOutOfContext()); } // Look up conformance in the current module. diff --git a/include/swift/SILOptimizer/Differentiation/LinearMapInfo.h b/include/swift/SILOptimizer/Differentiation/LinearMapInfo.h index 13735902d38dd..f6ce574362909 100644 --- a/include/swift/SILOptimizer/Differentiation/LinearMapInfo.h +++ b/include/swift/SILOptimizer/Differentiation/LinearMapInfo.h @@ -165,7 +165,7 @@ class LinearMapInfo { derivative->getLoweredFunctionType()->getSubstGenericSignature(); auto *linMapStruct = getLinearMapStruct(origBB); auto linMapStructType = - linMapStruct->getDeclaredInterfaceType()->getCanonicalType( + linMapStruct->getDeclaredInterfaceType()->getReducedType( derivativeGenSig); Lowering::AbstractionPattern pattern(derivativeGenSig, linMapStructType); return typeConverter.getLoweredType(pattern, linMapStructType, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a53383c3e1fe7..6ba12479ea20f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3541,7 +3541,7 @@ isGenericFunctionTypeCanonical(GenericSignature sig, return false; for (auto param : params) { - if (!sig->isCanonicalTypeInContext(param.getPlainType())) + if (!sig->isReducedType(param.getPlainType())) return false; if (!param.getInternalLabel().empty()) { // Canonical types don't have internal labels @@ -3549,7 +3549,7 @@ isGenericFunctionTypeCanonical(GenericSignature sig, } } - return sig->isCanonicalTypeInContext(result); + return sig->isReducedType(result); } AnyFunctionType *AnyFunctionType::withExtInfo(ExtInfo info) const { @@ -3771,7 +3771,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig, } // We have to construct this generic function type. Determine whether - // it's canonical. Unfortunately, isCanonicalTypeInContext can cause + // it's canonical. Unfortunately, isReducedType() can cause // new GenericFunctionTypes to be created and thus invalidate our insertion // point. bool isCanonical = isGenericFunctionTypeCanonical(sig, params, result); @@ -3788,7 +3788,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig, if (info.hasValue()) globalActor = info->getGlobalActor(); - if (globalActor && !sig->isCanonicalTypeInContext(globalActor)) + if (globalActor && !sig->isReducedType(globalActor)) isCanonical = false; size_t allocSize = totalSizeToAlloc( diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index ee66188b8b236..166a95f7593c5 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -3357,9 +3357,9 @@ void ASTMangler::appendProtocolConformanceRef( } /// Retrieve the index of the conformance requirement indicated by the -/// conformance access path entry within the given set of requirements. +/// conformance path entry within the given set of requirements. static unsigned conformanceRequirementIndex( - const ConformanceAccessPath::Entry &entry, + const ConformancePath::Entry &entry, ArrayRef requirements) { unsigned result = 0; for (const auto &req : requirements) { @@ -3377,7 +3377,7 @@ static unsigned conformanceRequirementIndex( } void ASTMangler::appendDependentProtocolConformance( - const ConformanceAccessPath &path, + const ConformancePath &path, GenericSignature sig) { ProtocolDecl *currentProtocol = nullptr; for (const auto &entry : path) { @@ -3441,19 +3441,19 @@ void ASTMangler::appendAnyProtocolConformance( if (conformingType->isTypeParameter()) { assert(genericSig && "Need a generic signature to resolve conformance"); - auto path = genericSig->getConformanceAccessPath(conformingType, - conformance.getAbstract()); + auto path = genericSig->getConformancePath(conformingType, + conformance.getAbstract()); appendDependentProtocolConformance(path, genericSig); } else if (auto opaqueType = conformingType->getAs()) { GenericSignature opaqueSignature = opaqueType->getDecl()->getOpaqueInterfaceGenericSignature(); - ConformanceAccessPath conformanceAccessPath = - opaqueSignature->getConformanceAccessPath( + ConformancePath conformancePath = + opaqueSignature->getConformancePath( opaqueType->getInterfaceType(), conformance.getAbstract()); - // Append the conformance access path with the signature of the opaque type. - appendDependentProtocolConformance(conformanceAccessPath, opaqueSignature); + // Append the conformance path with the signature of the opaque type. + appendDependentProtocolConformance(conformancePath, opaqueSignature); appendType(conformingType, genericSig); appendOperator("HO"); } else { @@ -3488,7 +3488,7 @@ void ASTMangler::appendConcreteProtocolConformance( auto type = conditionalReq.getFirstType(); if (type->hasArchetype()) type = type->mapTypeOutOfContext(); - CanType canType = type->getCanonicalType(sig); + CanType canType = type->getReducedType(sig); auto proto = conditionalReq.getProtocolDecl(); ProtocolConformanceRef conformance; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 247f75679588c..59730f407de9d 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4106,7 +4106,7 @@ findGenericParameterReferences(CanGenericSignature genericSig, // If the type parameter is beyond the domain of the existential generic // signature, ignore it. - if (!genericSig->isValidTypeInContext(type)) { + if (!genericSig->isValidTypeParameter(type)) { return GenericParameterReferenceInfo(); } diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 57d4bb6a14428..b29f1463054ee 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -29,7 +29,7 @@ using namespace swift; -void ConformanceAccessPath::print(raw_ostream &out) const { +void ConformancePath::print(raw_ostream &out) const { llvm::interleave( begin(), end(), [&](const Entry &entry) { @@ -39,7 +39,7 @@ void ConformanceAccessPath::print(raw_ostream &out) const { [&] { out << " -> "; }); } -void ConformanceAccessPath::dump() const { +void ConformancePath::dump() const { print(llvm::errs()); llvm::errs() << "\n"; } @@ -357,7 +357,7 @@ LayoutConstraint GenericSignatureImpl::getLayoutConstraint(Type type) const { return getRequirementMachine()->getLayoutConstraint(type); } -bool GenericSignatureImpl::areSameTypeParameterInContext(Type type1, +bool GenericSignatureImpl::areReducedTypeParametersEqual(Type type1, Type type2) const { assert(type1->isTypeParameter()); assert(type2->isTypeParameter()); @@ -365,7 +365,7 @@ bool GenericSignatureImpl::areSameTypeParameterInContext(Type type1, if (type1.getPointer() == type2.getPointer()) return true; - return getRequirementMachine()->areSameTypeParameterInContext(type1, type2); + return getRequirementMachine()->areReducedTypeParametersEqual(type1, type2); } bool GenericSignatureImpl::isRequirementSatisfied( @@ -431,43 +431,40 @@ SmallVector GenericSignatureImpl::requirementsNotSatisfiedBy( return result; } -bool GenericSignatureImpl::isCanonicalTypeInContext(Type type) const { - // If the type isn't independently canonical, it's certainly not canonical - // in this context. +bool GenericSignatureImpl::isReducedType(Type type) const { + // If the type isn't canonical, it's not reduced. if (!type->isCanonical()) return false; - // All the contextual canonicality rules apply to type parameters, so if the - // type doesn't involve any type parameters, it's already canonical. + // A fully concrete canonical type is reduced. if (!type->hasTypeParameter()) return true; - return getRequirementMachine()->isCanonicalTypeInContext(type); + return getRequirementMachine()->isReducedType(type); } -CanType GenericSignature::getCanonicalTypeInContext(Type type) const { +CanType GenericSignature::getReducedType(Type type) const { // The null generic signature has no requirements so cannot influence the // structure of the can type computed here. if (isNull()) { return type->getCanonicalType(); } - return getPointer()->getCanonicalTypeInContext(type); + return getPointer()->getReducedType(type); } -CanType GenericSignatureImpl::getCanonicalTypeInContext(Type type) const { +CanType GenericSignatureImpl::getReducedType(Type type) const { type = type->getCanonicalType(); - // All the contextual canonicality rules apply to type parameters, so if the - // type doesn't involve any type parameters, it's already canonical. + // A fully concrete type is already reduced. if (!type->hasTypeParameter()) return CanType(type); - return getRequirementMachine()->getCanonicalTypeInContext( + return getRequirementMachine()->getReducedType( type, { })->getCanonicalType(); } -bool GenericSignatureImpl::isValidTypeInContext(Type type) const { - return getRequirementMachine()->isValidTypeInContext(type); +bool GenericSignatureImpl::isValidTypeParameter(Type type) const { + return getRequirementMachine()->isValidTypeParameter(type); } ArrayRef> @@ -478,10 +475,10 @@ CanGenericSignature::getGenericParams() const { return {base, params.size()}; } -ConformanceAccessPath -GenericSignatureImpl::getConformanceAccessPath(Type type, - ProtocolDecl *protocol) const { - return getRequirementMachine()->getConformanceAccessPath(type, protocol); +ConformancePath +GenericSignatureImpl::getConformancePath(Type type, + ProtocolDecl *protocol) const { + return getRequirementMachine()->getConformancePath(type, protocol); } TypeDecl * @@ -850,8 +847,8 @@ void GenericSignature::verify(ArrayRef reqts) const { abort(); } - if (!canSig->isCanonicalTypeInContext(reqt.getFirstType())) { - llvm::errs() << "Left-hand side is not canonical: "; + if (!canSig->isReducedType(reqt.getFirstType())) { + llvm::errs() << "Left-hand side is not reduced: "; reqt.dump(llvm::errs()); llvm::errs() << "\n"; abort(); @@ -861,8 +858,8 @@ void GenericSignature::verify(ArrayRef reqts) const { // Check canonicalization of requirement itself. switch (reqt.getKind()) { case RequirementKind::Superclass: - if (!canSig->isCanonicalTypeInContext(reqt.getSecondType())) { - llvm::errs() << "Right-hand side is not canonical: "; + if (!canSig->isReducedType(reqt.getSecondType())) { + llvm::errs() << "Right-hand side is not reduced: "; reqt.dump(llvm::errs()); llvm::errs() << "\n"; abort(); @@ -873,9 +870,9 @@ void GenericSignature::verify(ArrayRef reqts) const { break; case RequirementKind::SameType: { - auto hasCanonicalOrConcreteParent = [&](Type type) { + auto hasReducedOrConcreteParent = [&](Type type) { if (auto *dmt = type->getAs()) { - return (canSig->isCanonicalTypeInContext(dmt->getBase()) || + return (canSig->isReducedType(dmt->getBase()) || canSig->isConcreteType(dmt->getBase())); } return type->is(); @@ -884,19 +881,19 @@ void GenericSignature::verify(ArrayRef reqts) const { auto firstType = reqt.getFirstType(); auto secondType = reqt.getSecondType(); - auto canType = canSig->getCanonicalTypeInContext(firstType); + auto canType = canSig->getReducedType(firstType); auto &component = sameTypeComponents[canType]; - if (!hasCanonicalOrConcreteParent(firstType)) { - llvm::errs() << "Left hand side does not have a canonical parent: "; + if (!hasReducedOrConcreteParent(firstType)) { + llvm::errs() << "Left hand side does not have a reduced parent: "; reqt.dump(llvm::errs()); llvm::errs() << "\n"; abort(); } if (reqt.getSecondType()->isTypeParameter()) { - if (!hasCanonicalOrConcreteParent(secondType)) { - llvm::errs() << "Right hand side does not have a canonical parent: "; + if (!hasReducedOrConcreteParent(secondType)) { + llvm::errs() << "Right hand side does not have a reduced parent: "; reqt.dump(llvm::errs()); llvm::errs() << "\n"; abort(); @@ -920,8 +917,8 @@ void GenericSignature::verify(ArrayRef reqts) const { component.push_back(secondType); } else { - if (!canSig->isCanonicalTypeInContext(secondType)) { - llvm::errs() << "Right hand side is not canonical: "; + if (!canSig->isReducedType(secondType)) { + llvm::errs() << "Right hand side is not reduced: "; reqt.dump(llvm::errs()); llvm::errs() << "\n"; abort(); @@ -1004,9 +1001,9 @@ void GenericSignature::verify(ArrayRef reqts) const { // Check same-type components for consistency. for (const auto &pair : sameTypeComponents) { if (pair.second.front()->isTypeParameter() && - !canSig->isCanonicalTypeInContext(pair.second.front())) { + !canSig->isReducedType(pair.second.front())) { llvm::errs() << "Abstract same-type requirement involving concrete types\n"; - llvm::errs() << "Canonical type: " << pair.first << "\n"; + llvm::errs() << "Reduced type: " << pair.first << "\n"; llvm::errs() << "Left hand side of first requirement: " << pair.second.front() << "\n"; abort(); diff --git a/lib/AST/RequirementMachine/GenericSignatureQueries.cpp b/lib/AST/RequirementMachine/GenericSignatureQueries.cpp index 1458c1de29143..f292d8ced5bbe 100644 --- a/lib/AST/RequirementMachine/GenericSignatureQueries.cpp +++ b/lib/AST/RequirementMachine/GenericSignatureQueries.cpp @@ -20,15 +20,15 @@ // Each query is generally implemented in the same manner: // // - First, convert the subject type parameter into a Term. -// - Simplify the Term to obtain a canonical Term. +// - Simplify the Term to obtain a reduced Term. // - Perform a property map lookup on the Term. // - Return the appropriate piece of information from the property map. // -// A few are slightly different; for example, getCanonicalTypeInContext() takes -// an arbitrary type, not just a type parameter, and recursively transforms the +// A few are slightly different; for example, getReducedType() takes an +// arbitrary type, not just a type parameter, and recursively transfozms the // type parameters it contains, if any. // -// Also, getConformanceAccessPath() is another one-off operation. +// Also, getConformancePath() is another one-off operation. // //===----------------------------------------------------------------------===// @@ -214,7 +214,7 @@ getConcreteType(Type depType, return props->getConcreteType(genericParams, term, Map); } -bool RequirementMachine::areSameTypeParameterInContext(Type depType1, +bool RequirementMachine::areReducedTypeParametersEqual(Type depType1, Type depType2) const { auto term1 = Context.getMutableTermForType(depType1->getCanonicalType(), /*proto=*/nullptr); @@ -282,11 +282,10 @@ RequirementMachine::getLongestValidPrefix(const MutableTerm &term) const { /// type parameter. /// /// Returns true if all structural components that are type parameters are -/// in their canonical form, and are not concrete (in which case they're -/// not considered canonical, since they can be replaced with their -/// concrete type). -bool RequirementMachine::isCanonicalTypeInContext(Type type) const { - // Look for non-canonical type parameters. +/// reduced, and in particular not concrete (in which case they're not +/// considered reduced, since they can be replaced with their concrete type). +bool RequirementMachine::isReducedType(Type type) const { + // Look for non-reduced type parameters. class Walker : public TypeWalker { const RequirementMachine &Self; @@ -315,7 +314,7 @@ bool RequirementMachine::isCanonicalTypeInContext(Type type) const { if (props && props->isConcreteType()) return Action::Stop; - // The parent of a canonical type parameter might be non-canonical + // The parent of a reduced type parameter might be non-reduced // because it is concrete. return Action::SkipChildren; } @@ -343,11 +342,11 @@ static Type substPrefixType(Type type, unsigned suffixLength, Type prefixType, /// type parameter. /// /// Replaces all structural components that are type parameters with their -/// most canonical form, which is either a (possibly different) -/// type parameter, or a concrete type, in which case we recursively -/// simplify any type parameters appearing in structural positions of -/// that concrete type as well, and so on. -Type RequirementMachine::getCanonicalTypeInContext( +/// reduced form, which is either a (possibly different) type parameter, +/// or a concrete type, in which case we recursively reduce any type +/// parameters appearing in structural positions of that concrete type +/// as well, and so on. +Type RequirementMachine::getReducedType( Type type, TypeArrayView genericParams) const { @@ -364,21 +363,21 @@ Type RequirementMachine::getCanonicalTypeInContext( System.simplify(term); // We need to handle "purely concrete" member types, eg if I have a - // signature , and we're asked to canonicalize the + // signature , and we're asked to reduce the // type T.[P:A] where Foo : A. // // This comes up because we can derive the signature // from a generic signature like ; adding the // concrete requirement 'T == Foo' renders 'T : P' redundant. We then // want to take interface types written against the original signature - // and canonicalize them with respect to the derived signature. + // and reduce them with respect to the derived signature. // // The problem is that T.[P:A] is not a valid term in the rewrite system // for , since we do not have the requirement T : P. // // A more principled solution would build a substitution map when // building a derived generic signature that adds new requirements; - // interface types would first be substituted before being canonicalized + // interface types would first be substituted before being reduced // in the new signature. // // For now, we handle this with a two-step process; we split a term up @@ -406,7 +405,7 @@ Type RequirementMachine::getCanonicalTypeInContext( return concreteType; // FIXME: Recursion guard is needed here - return getCanonicalTypeInContext(concreteType, genericParams); + return getReducedType(concreteType, genericParams); } // Skip this part if the entire input term is valid, because in that @@ -421,7 +420,7 @@ Type RequirementMachine::getCanonicalTypeInContext( return superclass; // FIXME: Recursion guard is needed here - return getCanonicalTypeInContext(superclass, genericParams); + return getReducedType(superclass, genericParams); } } @@ -438,7 +437,7 @@ Type RequirementMachine::getCanonicalTypeInContext( // If U is not concrete, we have an invalid member type of a dependent // type, which is not valid in this generic signature. Give up. if (prefixType->isTypeParameter()) { - llvm::errs() << "Invalid type parameter in getCanonicalTypeInContext()\n"; + llvm::errs() << "Invalid type parameter in getReducedType()\n"; llvm::errs() << "Original type: " << type << "\n"; llvm::errs() << "Simplified term: " << term << "\n"; llvm::errs() << "Longest valid prefix: " << prefix << "\n"; @@ -453,13 +452,13 @@ Type RequirementMachine::getCanonicalTypeInContext( prefixType, Sig); // FIXME: Recursion guard is needed here - return getCanonicalTypeInContext(substType, genericParams); + return getReducedType(substType, genericParams); }); } /// Determine if the given type parameter is valid with respect to this /// requirement machine's generic signature. -bool RequirementMachine::isValidTypeInContext(Type type) const { +bool RequirementMachine::isValidTypeParameter(Type type) const { assert(type->isTypeParameter()); auto term = Context.getMutableTermForType(type->getCanonicalType(), @@ -470,7 +469,7 @@ bool RequirementMachine::isValidTypeInContext(Type type) const { return (prefix == term); } -/// Retrieve the conformance access path used to extract the conformance of +/// Retrieve the conformance path used to extract the conformance of /// interface \c type to the given \c protocol. /// /// \param type The interface type whose conformance access path is to be @@ -481,10 +480,10 @@ bool RequirementMachine::isValidTypeInContext(Type type) const { /// this generic signature and ends at the conformance that makes \c type /// conform to \c protocol. /// -/// \seealso ConformanceAccessPath -ConformanceAccessPath -RequirementMachine::getConformanceAccessPath(Type type, - ProtocolDecl *protocol) { +/// \seealso ConformancePath +ConformancePath +RequirementMachine::getConformancePath(Type type, + ProtocolDecl *protocol) { assert(type->isTypeParameter()); auto mutTerm = Context.getMutableTermForType(type->getCanonicalType(), @@ -506,9 +505,9 @@ RequirementMachine::getConformanceAccessPath(Type type, auto term = Term::get(mutTerm, Context); // Check if we've already cached the result before doing anything else. - auto found = ConformanceAccessPaths.find( + auto found = ConformancePaths.find( std::make_pair(term, protocol)); - if (found != ConformanceAccessPaths.end()) { + if (found != ConformancePaths.end()) { return found->second; } @@ -517,25 +516,25 @@ RequirementMachine::getConformanceAccessPath(Type type, FrontendStatsTracer tracer(Stats, "get-conformance-access-path"); auto recordPath = [&](Term term, ProtocolDecl *proto, - ConformanceAccessPath path) { + ConformancePath path) { // Add the path to the buffer. - CurrentConformanceAccessPaths.emplace_back(term, path); + CurrentConformancePaths.emplace_back(term, path); // Add the path to the map. auto key = std::make_pair(term, proto); - auto inserted = ConformanceAccessPaths.insert( + auto inserted = ConformancePaths.insert( std::make_pair(key, path)); assert(inserted.second); (void) inserted; if (Stats) - ++Stats->getFrontendCounters().NumConformanceAccessPathsRecorded; + ++Stats->getFrontendCounters().NumConformancePathsRecorded; }; // If this is the first time we're asked to look up a conformance access path, // visit all of the root conformance requirements in our generic signature and // add them to the buffer. - if (ConformanceAccessPaths.empty()) { + if (ConformancePaths.empty()) { for (const auto &req : Sig.getRequirements()) { // We only care about conformance requirements. if (req.getKind() != RequirementKind::Conformance) @@ -544,9 +543,9 @@ RequirementMachine::getConformanceAccessPath(Type type, auto rootType = CanType(req.getFirstType()); auto *rootProto = req.getProtocolDecl(); - ConformanceAccessPath::Entry root(rootType, rootProto); - ArrayRef path(root); - ConformanceAccessPath result(ctx.AllocateCopy(path)); + ConformancePath::Entry root(rootType, rootProto); + ArrayRef path(root); + ConformancePath result(ctx.AllocateCopy(path)); auto mutTerm = Context.getMutableTermForType(rootType, nullptr); System.simplify(mutTerm); @@ -556,17 +555,17 @@ RequirementMachine::getConformanceAccessPath(Type type, } } - // We enumerate conformance access paths in shortlex order until we find the - // path whose corresponding type canonicalizes to the one we are looking for. + // We enumerate conformance paths in shortlex order until we find the + // path whose corresponding type reduces to the one we are looking for. while (true) { - auto found = ConformanceAccessPaths.find( + auto found = ConformancePaths.find( std::make_pair(term, protocol)); - if (found != ConformanceAccessPaths.end()) { + if (found != ConformancePaths.end()) { return found->second; } - if (CurrentConformanceAccessPaths.empty()) { - llvm::errs() << "Failed to find conformance access path for "; + if (CurrentConformancePaths.empty()) { + llvm::errs() << "Failed to find conformance path for "; llvm::errs() << type << " (" << term << ")" << " : "; llvm::errs() << protocol->getName() << ":\n"; type.dump(llvm::errs()); @@ -575,18 +574,18 @@ RequirementMachine::getConformanceAccessPath(Type type, abort(); } - // The buffer consists of all conformance access paths of length N. + // The buffer consists of all conformance paths of length N. // Swap it out with an empty buffer, and fill it with all paths of // length N+1. - std::vector> oldPaths; - std::swap(CurrentConformanceAccessPaths, oldPaths); + std::vector> oldPaths; + std::swap(CurrentConformancePaths, oldPaths); for (const auto &pair : oldPaths) { const auto &lastElt = pair.second.back(); auto *lastProto = lastElt.second; // A copy of the current path, populated as needed. - SmallVector entries; + SmallVector entries; auto reqs = lastProto->getRequirementSignature().getRequirements(); for (const auto &req : reqs) { @@ -608,7 +607,7 @@ RequirementMachine::getConformanceAccessPath(Type type, // don't add it to the buffer. Note that because we iterate over // conformance access paths in shortlex order, the existing // conformance access path is shorter than the one we found just now. - if (ConformanceAccessPaths.count( + if (ConformancePaths.count( std::make_pair(nextTerm, nextProto))) continue; @@ -621,7 +620,7 @@ RequirementMachine::getConformanceAccessPath(Type type, // Add the next entry. entries.emplace_back(nextSubjectType, nextProto); - ConformanceAccessPath result = ctx.AllocateCopy(entries); + ConformancePath result = ctx.AllocateCopy(entries); entries.pop_back(); recordPath(nextTerm, nextProto, result); diff --git a/lib/AST/RequirementMachine/RequirementMachine.cpp b/lib/AST/RequirementMachine/RequirementMachine.cpp index c82c4ffc92228..497d101be5d8d 100644 --- a/lib/AST/RequirementMachine/RequirementMachine.cpp +++ b/lib/AST/RequirementMachine/RequirementMachine.cpp @@ -18,7 +18,7 @@ // type parameters expressed by this set of generic requirements. These are // called "generic signature queries", and are defined as methods on the // GenericSignature class; for example, two of the more common ones are -// getCanonicalTypeInContext() and requiresProtocol(). +// getReducedType() and requiresProtocol(). // // The terms of the rewrite system describe all possible type parameters that // can be written -- the generic parameters themselves, together with all nested @@ -565,8 +565,8 @@ void RequirementMachine::dump(llvm::raw_ostream &out) const { System.dump(out); Map.dump(out); - out << "Conformance access paths: {\n"; - for (auto pair : ConformanceAccessPaths) { + out << "Conformance paths: {\n"; + for (auto pair : ConformancePaths) { out << "- " << pair.first.first << " : "; out << pair.first.second->getName() << " => "; pair.second.print(out); diff --git a/lib/AST/RequirementMachine/RequirementMachine.h b/lib/AST/RequirementMachine/RequirementMachine.h index 7dac363813a21..bb8f7c67a6081 100644 --- a/lib/AST/RequirementMachine/RequirementMachine.h +++ b/lib/AST/RequirementMachine/RequirementMachine.h @@ -71,16 +71,15 @@ class RequirementMachine final { UnifiedStatsReporter *Stats; - /// All conformance access paths computed so far. + /// All conformance paths computed so far. llvm::DenseMap, - ConformanceAccessPath> ConformanceAccessPaths; + ConformancePath> ConformancePaths; /// Conformance access paths computed during the last round. All elements /// have the same length. If a conformance access path of greater length - /// is requested, we refill CurrentConformanceAccessPaths with all paths of - /// length N+1, and add them to the ConformanceAccessPaths map. - std::vector> - CurrentConformanceAccessPaths; + /// is requested, we refill CurrentConformancePaths with all paths of + /// length N+1, and add them to the ConformancePaths map. + std::vector> CurrentConformancePaths; explicit RequirementMachine(RewriteContext &rewriteCtx); @@ -153,13 +152,12 @@ class RequirementMachine final { Type getConcreteType(Type depType, TypeArrayView genericParams, const ProtocolDecl *proto=nullptr) const; - bool areSameTypeParameterInContext(Type depType1, Type depType2) const; - bool isCanonicalTypeInContext(Type type) const; - Type getCanonicalTypeInContext(Type type, + bool areReducedTypeParametersEqual(Type depType1, Type depType2) const; + bool isReducedType(Type type) const; + Type getReducedType(Type type, TypeArrayView genericParams) const; - bool isValidTypeInContext(Type type) const; - ConformanceAccessPath getConformanceAccessPath(Type type, - ProtocolDecl *protocol); + bool isValidTypeParameter(Type type) const; + ConformancePath getConformancePath(Type type, ProtocolDecl *protocol); TypeDecl *lookupNestedType(Type depType, Identifier name) const; llvm::DenseMap diff --git a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp index 8c8fabedf3049..4c0dc291e17ce 100644 --- a/lib/AST/RequirementMachine/RequirementMachineRequests.cpp +++ b/lib/AST/RequirementMachine/RequirementMachineRequests.cpp @@ -482,7 +482,7 @@ RequirementMachine::computeMinimalGenericSignature( auto sig = GenericSignature::get(getGenericParams(), reqs); // Remember the signature for generic signature queries. In particular, - // getConformanceAccessPath() needs the current requirement machine's + // getConformancePath() needs the current requirement machine's // generic signature. Sig = sig.getCanonicalSignature(); @@ -920,14 +920,14 @@ InferredGenericSignatureRequest::evaluate( if (!allowConcreteGenericParams) { for (auto genericParam : result.getInnermostGenericParams()) { - auto canonical = result.getCanonicalTypeInContext(genericParam); + auto reduced = result.getReducedType(genericParam); - if (canonical->hasError() || canonical->isEqual(genericParam)) + if (reduced->hasError() || reduced->isEqual(genericParam)) continue; - if (canonical->isTypeParameter()) { + if (reduced->isTypeParameter()) { ctx.Diags.diagnose(loc, diag::requires_generic_params_made_equal, - genericParam, result->getSugaredType(canonical)) + genericParam, result->getSugaredType(reduced)) .warnUntilSwiftVersion(6); } else { ctx.Diags.diagnose(loc, diff --git a/lib/AST/RequirementMachine/RuleBuilder.cpp b/lib/AST/RequirementMachine/RuleBuilder.cpp index 41edacbd1d4db..dd6338528052f 100644 --- a/lib/AST/RequirementMachine/RuleBuilder.cpp +++ b/lib/AST/RequirementMachine/RuleBuilder.cpp @@ -104,7 +104,7 @@ void RuleBuilder::initWithProtocolSignatureRequirements( // If completion failed, we'll have a totally empty requirement signature, // but to maintain invariants around what constitutes a valid rewrite term - // between getTypeForTerm() and isValidTypeInContext(), we need to add rules + // between getTypeForTerm() and isValidTypeParameter(), we need to add rules // for inherited protocols. if (reqs.getErrors().contains(GenericSignatureErrorFlags::CompletionFailed)) { for (auto *inheritedProto : Context.getInheritedProtocols(proto)) { diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index a266225417523..6f697083bfc1d 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -299,9 +299,9 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const { return replacementType; } - // The generic parameter may not be canonical. Retrieve the canonical + // The generic parameter may not be reduced. Retrieve the reduced // type, which will be dependent. - CanType canonicalType = genericSig.getCanonicalTypeInContext(genericParam); + CanType canonicalType = genericSig.getReducedType(genericParam); // If nothing changed, we don't have a replacement. if (canonicalType == type) return Type(); @@ -367,11 +367,10 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { return ProtocolConformanceRef::forMissingOrInvalid(substType, proto); } - auto accessPath = - genericSig->getConformanceAccessPath(type, proto); + auto path = genericSig->getConformancePath(type, proto); ProtocolConformanceRef conformance; - for (const auto &step : accessPath) { + for (const auto &step : path) { // For the first step, grab the initial conformance. if (conformance.isInvalid()) { if (auto initialConformance = getSignatureConformance( diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 6cbe25c5c0aed..283fb7a65bf4e 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1537,7 +1537,7 @@ getCanonicalParams(AnyFunctionType *funcType, for (auto param : origParams) { // Canonicalize the type and drop the internal label to canonicalize the // Param. - canParams.emplace_back(param.getPlainType()->getCanonicalType(genericSig), + canParams.emplace_back(param.getPlainType()->getReducedType(genericSig), param.getLabel(), param.getParameterFlags(), /*InternalLabel=*/Identifier()); } @@ -1673,7 +1673,7 @@ CanType TypeBase::computeCanonicalType() { // Transform the parameter and result types. SmallVector canParams; getCanonicalParams(funcTy, genericSig, canParams); - auto resultTy = funcTy->getResult()->getCanonicalType(genericSig); + auto resultTy = funcTy->getResult()->getReducedType(genericSig); Optional extInfo = None; if (funcTy->hasExtInfo()) @@ -1775,8 +1775,8 @@ CanType TypeBase::computeCanonicalType() { return CanonicalType = CanType(Result); } -CanType TypeBase::getCanonicalType(GenericSignature sig) { - return sig.getCanonicalTypeInContext(this); +CanType TypeBase::getReducedType(GenericSignature sig) { + return sig.getReducedType(this); } CanType TypeBase::getMinimalCanonicalType(const DeclContext *useDC) const { @@ -2555,9 +2555,9 @@ class IsBindableVisitor for (unsigned i : indices(origSubs.getReplacementTypes())) { auto origType = - origSubs.getReplacementTypes()[i]->getCanonicalType(sig); + origSubs.getReplacementTypes()[i]->getReducedType(sig); auto substType = - substSubs.getReplacementTypes()[i]->getCanonicalType(sig); + substSubs.getReplacementTypes()[i]->getReducedType(sig); auto newType = visit(origType, substType, nullptr, {}); @@ -2585,9 +2585,9 @@ class IsBindableVisitor for (unsigned i : indices(origSubs.getReplacementTypes())) { auto origType = - origSubs.getReplacementTypes()[i]->getCanonicalType(sig); + origSubs.getReplacementTypes()[i]->getReducedType(sig); auto substType = - substSubs.getReplacementTypes()[i]->getCanonicalType(sig); + substSubs.getReplacementTypes()[i]->getReducedType(sig); auto newType = visit(origType, substType, nullptr, {}); @@ -3570,7 +3570,7 @@ SequenceArchetypeType::SequenceArchetypeType( CanType OpaqueTypeArchetypeType::getCanonicalInterfaceType(Type interfaceType) { auto sig = Environment->getOpaqueTypeDecl() ->getOpaqueInterfaceGenericSignature(); - CanType canonicalType = interfaceType->getCanonicalType(sig); + CanType canonicalType = interfaceType->getReducedType(sig); return Environment->maybeApplyOpaqueTypeSubstitutions(canonicalType) ->getCanonicalType(); } @@ -4001,7 +4001,7 @@ Type ArchetypeType::getNestedTypeByName(Identifier name) { Type interfaceType = getInterfaceType(); Type memberInterfaceType = DependentMemberType::get(interfaceType, name); auto genericSig = getGenericEnvironment()->getGenericSignature(); - if (genericSig->isValidTypeInContext(memberInterfaceType)) { + if (genericSig->isValidTypeParameter(memberInterfaceType)) { return getGenericEnvironment()->getOrCreateArchetypeFromInterfaceType( memberInterfaceType); } diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 704d892816f47..8b5933d8f9650 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -411,8 +411,6 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments, runtimeCompatibilityVersion = llvm::VersionTuple(5, 1); } else if (value.equals("5.5")) { runtimeCompatibilityVersion = llvm::VersionTuple(5, 5); - } else if (value.equals("5.6")) { - runtimeCompatibilityVersion = llvm::VersionTuple(5, 6); } else if (value.equals("none")) { runtimeCompatibilityVersion = None; } else { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 0c13a550e164a..dc2c2b579f1bd 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2292,8 +2292,6 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, runtimeCompatibilityVersion = llvm::VersionTuple(5, 1); } else if (version.equals("5.5")) { runtimeCompatibilityVersion = llvm::VersionTuple(5, 5); - } else if (version.equals("5.6")) { - runtimeCompatibilityVersion = llvm::VersionTuple(5, 6); } else { Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, versionArg->getAsString(Args), version); diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index 71e0833453915..c12460527f8d7 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -191,8 +191,7 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF, auto environment = archetype->getGenericEnvironment(); - // Otherwise, ask the generic signature for the environment for the best - // path to the conformance. + // Otherwise, ask the generic signature for the best path to the conformance. // TODO: this isn't necessarily optimal if the direct conformance isn't // concretely available; we really ought to be comparing the full paths // to this conformance from concrete sources. @@ -200,8 +199,7 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF, auto signature = environment->getGenericSignature().getCanonicalSignature(); auto archetypeDepType = archetype->getInterfaceType(); - auto astPath = signature->getConformanceAccessPath(archetypeDepType, - protocol); + auto astPath = signature->getConformancePath(archetypeDepType, protocol); auto i = astPath.begin(), e = astPath.end(); assert(i != e && "empty path!"); @@ -437,7 +435,7 @@ withOpaqueTypeGenericArgs(IRGenFunction &IGF, opaqueDecl->getGenericSignature().getCanonicalSignature(), [&](GenericRequirement reqt) { auto ty = reqt.TypeParameter.subst(archetype->getSubstitutions()) - ->getCanonicalType(opaqueDecl->getGenericSignature()); + ->getReducedType(opaqueDecl->getGenericSignature()); if (reqt.Protocol) { auto ref = ProtocolConformanceRef(reqt.Protocol) diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 90c8d79ae77a9..be40fe65675fe 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -1402,7 +1402,7 @@ void IRGenModule::emitSILProperty(SILProperty *prop) { prop->getDecl()->getInnermostDeclContext() ->getInnermostTypeContext() ->getSelfInterfaceType() - ->getCanonicalType(genericSig), + ->getReducedType(genericSig), {}, hasSubscriptIndices); diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 24e377df12b86..1ceb01f63b9a3 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -2189,7 +2189,7 @@ namespace { auto *genericParam = O->getOpaqueGenericParams()[opaqueParamIdx]; auto underlyingType = - Type(genericParam).subst(*unique)->getCanonicalType(sig); + Type(genericParam).subst(*unique)->getReducedType(sig); return IGM .getTypeRef(underlyingType, contextSig, MangledTypeRefRole::Metadata) @@ -2450,7 +2450,7 @@ namespace { auto type = Type(O->getOpaqueGenericParams()[OpaqueParamIndex]) .subst(substitutions) - ->getCanonicalType(O->getOpaqueInterfaceGenericSignature()); + ->getReducedType(O->getOpaqueInterfaceGenericSignature()); type = genericEnv ? genericEnv->mapTypeIntoContext(type)->getCanonicalType() diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index f83fd2aae53ab..788dcfda0d545 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -3310,7 +3310,7 @@ GenericTypeRequirements::GenericTypeRequirements(IRGenModule &IGM, // Figure out what we're actually still required to pass PolymorphicConvention convention(IGM, fnType); convention.enumerateUnfulfilledRequirements([&](GenericRequirement reqt) { - assert(generics->isCanonicalTypeInContext(reqt.TypeParameter)); + assert(generics->isReducedType(reqt.TypeParameter)); Requirements.push_back(reqt); }); diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index dd26d8c5ee51d..55daa5564e0eb 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -357,7 +357,7 @@ IRGenModule::getTypeRef(CanType type, CanGenericSignature sig, std::pair IRGenModule::getTypeRef(Type type, GenericSignature genericSig, MangledTypeRefRole role) { - return getTypeRef(type->getCanonicalType(genericSig), + return getTypeRef(type->getReducedType(genericSig), genericSig.getCanonicalSignature(), role); } @@ -554,7 +554,7 @@ class ReflectionMetadataBuilder { void addTypeRef(Type type, GenericSignature genericSig, MangledTypeRefRole role = MangledTypeRefRole::Reflection) { - addTypeRef(type->getCanonicalType(genericSig), + addTypeRef(type->getReducedType(genericSig), genericSig.getCanonicalSignature(), role); } diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index ce2dcc8ef848d..c7ca9b8f79761 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -1711,6 +1711,8 @@ class LoadableByAddress : public SILModuleTransform { bool recreateDifferentiabilityWitnessFunction( SILInstruction &I, SmallVectorImpl &Delete); + bool shouldTransformGlobal(SILGlobalVariable *global); + private: llvm::SetVector modFuncs; llvm::SetVector conversionInstrs; @@ -2907,6 +2909,24 @@ void LoadableByAddress::updateLoweredTypes(SILFunction *F) { F->rewriteLoweredTypeUnsafe(newFuncTy); } +bool LoadableByAddress::shouldTransformGlobal(SILGlobalVariable *global) { + SILInstruction *init = global->getStaticInitializerValue(); + if (!init) + return false; + auto silTy = global->getLoweredType(); + if (!isa(silTy.getASTType())) + return false; + + auto *decl = global->getDecl(); + IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule( + decl ? decl->getDeclContext() : nullptr); + auto silFnTy = global->getLoweredFunctionType(); + GenericEnvironment *genEnv = getSubstGenericEnvironment(silFnTy); + if (MapperCache.shouldTransformFunctionType(genEnv, silFnTy, *currIRMod)) + return true; + return false; +} + /// The entry point to this function transformation. void LoadableByAddress::run() { // Set the SIL state before the PassManager has a chance to run @@ -2922,10 +2942,23 @@ void LoadableByAddress::run() { // Scan the module for all references of the modified functions: llvm::SetVector funcRefs; + llvm::SetVector globalRefs; for (SILFunction &CurrF : *getModule()) { for (SILBasicBlock &BB : CurrF) { for (SILInstruction &I : BB) { - if (auto *FRI = dyn_cast(&I)) { + if (auto *allocGlobal = dyn_cast(&I)) { + auto *global = allocGlobal->getReferencedGlobal(); + if (shouldTransformGlobal(global)) + globalRefs.insert(allocGlobal); + } else if (auto *globalAddr = dyn_cast(&I)) { + auto *global = globalAddr->getReferencedGlobal(); + if (shouldTransformGlobal(global)) + globalRefs.insert(globalAddr); + } else if (auto *globalVal = dyn_cast(&I)) { + auto *global = globalVal->getReferencedGlobal(); + if (shouldTransformGlobal(global)) + globalRefs.insert(globalVal); + } else if (auto *FRI = dyn_cast(&I)) { SILFunction *RefF = FRI->getInitiallyReferencedFunction(); if (modFuncs.count(RefF) != 0) { // Go over the uses and add them to lists to modify @@ -2954,7 +2987,7 @@ void LoadableByAddress::run() { case SILInstructionKind::LinearFunctionExtractInst: case SILInstructionKind::DifferentiableFunctionExtractInst: { conversionInstrs.insert( - cast(currInstr)); + cast(currInstr)); break; } case SILInstructionKind::BuiltinInst: { @@ -3032,6 +3065,99 @@ void LoadableByAddress::run() { updateLoweredTypes(F); } + auto computeNewResultType = [&](SILType ty, IRGenModule *mod) -> SILType { + auto currSILFunctionType = ty.castTo(); + GenericEnvironment *genEnv = + getSubstGenericEnvironment(currSILFunctionType); + return SILType::getPrimitiveObjectType( + MapperCache.getNewSILFunctionType(genEnv, currSILFunctionType, *mod)); + }; + + // Update globals' initializer. + SmallVector deadGlobals; + for (SILGlobalVariable &global : getModule()->getSILGlobals()) { + SILInstruction *init = global.getStaticInitializerValue(); + if (!init) + continue; + auto silTy = global.getLoweredType(); + if (!isa(silTy.getASTType())) + continue; + auto *decl = global.getDecl(); + IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule( + decl ? decl->getDeclContext() : nullptr); + auto silFnTy = global.getLoweredFunctionType(); + GenericEnvironment *genEnv = getSubstGenericEnvironment(silFnTy); + + // Update the global's type. + if (MapperCache.shouldTransformFunctionType(genEnv, silFnTy, *currIRMod)) { + auto newSILFnType = + MapperCache.getNewSILFunctionType(genEnv, silFnTy, *currIRMod); + global.unsafeSetLoweredType( + SILType::getPrimitiveObjectType(newSILFnType)); + + // Rewrite the init basic block... + SmallVector initBlockInsts; + for (auto it = global.begin(), end = global.end(); it != end; ++it) { + initBlockInsts.push_back(const_cast(&*it)); + } + for (auto *oldInst : initBlockInsts) { + if (auto *f = dyn_cast(oldInst)) { + SILBuilder builder(&global); + auto *newInst = builder.createFunctionRef( + f->getLoc(), f->getInitiallyReferencedFunction(), f->getKind()); + f->replaceAllUsesWith(newInst); + global.unsafeRemove(f, *getModule()); + } else if (auto *cvt = dyn_cast(oldInst)) { + auto newType = computeNewResultType(cvt->getType(), currIRMod); + SILBuilder builder(&global); + auto *newInst = builder.createConvertFunction( + cvt->getLoc(), cvt->getOperand(), newType, + cvt->withoutActuallyEscaping()); + cvt->replaceAllUsesWith(newInst); + global.unsafeRemove(cvt, *getModule()); + } else if (auto *thinToThick = + dyn_cast(oldInst)) { + auto newType = + computeNewResultType(thinToThick->getType(), currIRMod); + SILBuilder builder(&global); + auto *newInstr = builder.createThinToThickFunction( + thinToThick->getLoc(), thinToThick->getOperand(), newType); + thinToThick->replaceAllUsesWith(newInstr); + global.unsafeRemove(thinToThick, *getModule()); + } else { + auto *sv = cast(oldInst); + auto *newInst = cast(oldInst->clone()); + global.unsafeAppend(newInst); + sv->replaceAllUsesWith(newInst); + global.unsafeRemove(oldInst, *getModule()); + } + } + } + } + + // Rewrite global variable users. + for (auto *inst : globalRefs) { + if (auto *allocGlobal = dyn_cast(inst)) { + // alloc_global produces no results. + SILBuilderWithScope builder(inst); + builder.createAllocGlobal(allocGlobal->getLoc(), + allocGlobal->getReferencedGlobal()); + allocGlobal->eraseFromParent(); + } else if (auto *globalAddr = dyn_cast(inst)) { + SILBuilderWithScope builder(inst); + auto *newInst = builder.createGlobalAddr( + globalAddr->getLoc(), globalAddr->getReferencedGlobal()); + globalAddr->replaceAllUsesWith(newInst); + globalAddr->eraseFromParent(); + } else if (auto *globalVal = dyn_cast(inst)) { + SILBuilderWithScope builder(inst); + auto *newInst = builder.createGlobalValue( + globalVal->getLoc(), globalVal->getReferencedGlobal()); + globalVal->replaceAllUsesWith(newInst); + globalVal->eraseFromParent(); + } + } + // Update all references: // Note: We don't need to update the witness tables and vtables // They just contain a pointer to the function diff --git a/lib/PrintAsClang/PrintClangClassType.cpp b/lib/PrintAsClang/PrintClangClassType.cpp index 081365d9e16cf..3dd242e4f0848 100644 --- a/lib/PrintAsClang/PrintClangClassType.cpp +++ b/lib/PrintAsClang/PrintClangClassType.cpp @@ -94,47 +94,8 @@ void ClangClassTypePrinter::printClassTypeDecl( os << "};\n"; }); - // FIXME: avoid popping out of the module's namespace here. - os << "} // end namespace \n\n"; - os << "namespace swift {\n"; - - os << "#pragma clang diagnostic push\n"; - os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n"; - os << "template<>\n"; - os << "static inline const constexpr bool isUsableInGenericContext<"; - printer.printBaseName(typeDecl->getModuleContext()); - os << "::"; - printer.printBaseName(typeDecl); - os << "> = true;\n"; - os << "#pragma clang diagnostic pop\n"; - - os << "template<>\n"; - os << "inline void * _Nonnull getTypeMetadata<"; - printer.printBaseName(typeDecl->getModuleContext()); - os << "::"; - printer.printBaseName(typeDecl); - os << ">() {\n"; - os << " return "; - printer.printBaseName(typeDecl->getModuleContext()); - os << "::" << cxx_synthesis::getCxxImplNamespaceName() - << "::" << typeMetadataFuncName << "(0)._0;\n"; - os << "}\n"; - os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << "{\n"; - os << "template<>\n"; - os << "struct implClassFor<"; - printer.printBaseName(typeDecl->getModuleContext()); - os << "::"; - printer.printBaseName(typeDecl); - os << "> { using type = "; - printer.printBaseName(typeDecl->getModuleContext()); - os << "::" << cxx_synthesis::getCxxImplNamespaceName() << "::"; - printCxxImplClassName(os, typeDecl); - os << "; };\n"; - os << "} // namespace\n"; - os << "} // namespace swift\n"; - os << "\nnamespace "; - printer.printBaseName(typeDecl->getModuleContext()); - os << " {\n"; + ClangValueTypePrinter::printTypeGenericTraits(os, typeDecl, + typeMetadataFuncName); } void ClangClassTypePrinter::printClassTypeReturnScaffold( diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 78aa66c732e8f..fe586222e4116 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -347,7 +347,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature( bool isIndirectReturnType = kind == FunctionSignatureKind::CFunctionProto && !isKnownCType(resultTy, typeMapping) && - (isResilientType(resultTy) || isGenericType(resultTy) || + ((isResilientType(resultTy) && !resultTy->isAnyClassReferenceType()) || + isGenericType(resultTy) || interopContext.getIrABIDetails().shouldReturnIndirectly(resultTy)); if (!isIndirectReturnType) { OptionalTypeKind retKind; @@ -450,13 +451,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse( if (type->getAs() && type->getAs() ->getInterfaceType() ->is()) { - // FIXME: NEED to handle boxed resilient type. - // os << "swift::" << cxx_synthesis::getCxxImplNamespaceName() << - // "::getOpaquePointer("; - os << "reinterpret_cast<"; - if (!isInOut) - os << "const "; - os << "void *>(&"; + os << "swift::" << cxx_synthesis::getCxxImplNamespaceName() + << "::getOpaquePointer("; namePrinter(); os << ')'; return; @@ -575,10 +571,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody( if (!isKnownCxxType(resultTy, typeMapping) && !hasKnownOptionalNullableCxxMapping(resultTy)) { if (isGenericType(resultTy)) { - // FIXME: Support returning value types. std::string returnAddress; llvm::raw_string_ostream ros(returnAddress); ros << "reinterpret_cast(&returnValue)"; + StringRef resultTyName = "T"; // FIXME os << " if constexpr (std::is_base_of<::swift::" << cxx_synthesis::getCxxImplNamespaceName() @@ -588,6 +584,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody( os << ";\n"; os << " return ::swift::" << cxx_synthesis::getCxxImplNamespaceName() << "::implClassFor::type::makeRetained(returnValue);\n"; + os << " } else if constexpr (::swift::" + << cxx_synthesis::getCxxImplNamespaceName() << "::isValueType<" + << resultTyName << ">) {\n"; + os << " return ::swift::" << cxx_synthesis::getCxxImplNamespaceName() + << "::implClassFor<" << resultTyName + << ">::type::returnNewValue([&](void * _Nonnull returnValue) {\n"; + printCallToCFunc(/*additionalParam=*/StringRef("returnValue")); + os << ";\n });\n"; os << " } else {\n"; os << " T returnValue;\n"; printCallToCFunc(/*additionalParam=*/StringRef(ros.str())); diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 9fe2d0463afca..8d3773d823b10 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -152,7 +152,8 @@ void ClangValueTypePrinter::printValueTypeDecl( if (isOpaqueLayout) { os << " _storage = "; printer.printSwiftImplQualifier(); - os << cxx_synthesis::getCxxOpaqueStorageClassName() << "(vwTable);\n"; + os << cxx_synthesis::getCxxOpaqueStorageClassName() + << "(vwTable->size, vwTable->getAlignment());\n"; } os << " vwTable->initializeWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0);\n"; @@ -172,10 +173,12 @@ void ClangValueTypePrinter::printValueTypeDecl( // Print out private default constructor. os << " inline "; printer.printBaseName(typeDecl); + // FIXME: make noexcept. if (isOpaqueLayout) { os << "("; printer.printSwiftImplQualifier(); - os << "ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable) {}\n"; + os << "ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, " + "vwTable->getAlignment()) {}\n"; } else { os << "() {}\n"; } @@ -281,6 +284,8 @@ void ClangValueTypePrinter::printValueTypeDecl( if (!isOpaqueLayout) printCValueTypeStorageStruct(cPrologueOS, typeDecl, *typeSizeAlign); + + printTypeGenericTraits(os, typeDecl, typeMetadataFuncName); } /// Print the name of the C stub struct for passing/returning a value type @@ -456,3 +461,68 @@ void ClangValueTypePrinter::printValueTypeDirectReturnScaffold( os << ");\n"; os << " });\n"; } + +void ClangValueTypePrinter::printTypeGenericTraits( + raw_ostream &os, const NominalTypeDecl *typeDecl, + StringRef typeMetadataFuncName) { + ClangSyntaxPrinter printer(os); + // FIXME: avoid popping out of the module's namespace here. + os << "} // end namespace \n\n"; + os << "namespace swift {\n"; + + os << "#pragma clang diagnostic push\n"; + os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n"; + os << "template<>\n"; + os << "static inline const constexpr bool isUsableInGenericContext<"; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::"; + printer.printBaseName(typeDecl); + os << "> = true;\n"; + os << "template<>\n"; + os << "inline void * _Nonnull getTypeMetadata<"; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::"; + printer.printBaseName(typeDecl); + os << ">() {\n"; + os << " return "; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::" << cxx_synthesis::getCxxImplNamespaceName() + << "::" << typeMetadataFuncName << "(0)._0;\n"; + os << "}\n"; + + os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << "{\n"; + + if (!isa(typeDecl)) { + os << "template<>\n"; + os << "static inline const constexpr bool isValueType<"; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::"; + printer.printBaseName(typeDecl); + os << "> = true;\n"; + if (typeDecl->isResilient()) { + os << "template<>\n"; + os << "static inline const constexpr bool isOpaqueLayout<"; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::"; + printer.printBaseName(typeDecl); + os << "> = true;\n"; + } + } + + os << "template<>\n"; + os << "struct implClassFor<"; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::"; + printer.printBaseName(typeDecl); + os << "> { using type = "; + printer.printBaseName(typeDecl->getModuleContext()); + os << "::" << cxx_synthesis::getCxxImplNamespaceName() << "::"; + printCxxImplClassName(os, typeDecl); + os << "; };\n"; + os << "} // namespace\n"; + os << "#pragma clang diagnostic pop\n"; + os << "} // namespace swift\n"; + os << "\nnamespace "; + printer.printBaseName(typeDecl->getModuleContext()); + os << " {\n"; +} diff --git a/lib/PrintAsClang/PrintClangValueType.h b/lib/PrintAsClang/PrintClangValueType.h index 3be80722ea47f..a457506f28784 100644 --- a/lib/PrintAsClang/PrintClangValueType.h +++ b/lib/PrintAsClang/PrintClangValueType.h @@ -94,6 +94,10 @@ class ClangValueTypePrinter { StringRef metadataVarName = "metadata", StringRef vwTableVarName = "vwTable"); + static void printTypeGenericTraits(raw_ostream &os, + const NominalTypeDecl *typeDecl, + StringRef typeMetadataFuncName); + private: /// Prints out the C stub name used to pass/return value directly for the /// given value type. diff --git a/lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp b/lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp index 213120db42984..f79d3afc1e31c 100644 --- a/lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp +++ b/lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp @@ -111,6 +111,8 @@ static void printValueWitnessTable(raw_ostream &os) { #define VOID_TYPE "void" #include "swift/ABI/ValueWitness.def" + membersOS << "\n constexpr size_t getAlignment() const { return (flags & " + << TargetValueWitnessFlags::AlignmentMask << ") + 1; }\n"; os << "\nstruct ValueWitnessTable {\n" << membersOS.str() << "};\n\n"; membersOS.str().clear(); @@ -154,43 +156,7 @@ static void printTypeMetadataResponseType(SwiftToClangInteropContext &ctx, funcSig.parameterTypes[0]); } -static void printSwiftResilientStorageClass(raw_ostream &os) { - auto name = cxx_synthesis::getCxxOpaqueStorageClassName(); - static_assert(TargetValueWitnessFlags::AlignmentMask == - TargetValueWitnessFlags::AlignmentMask, - "alignment mask doesn't match"); - os << "/// Container for an opaque Swift value, like resilient struct.\n"; - os << "class " << name << " {\n"; - os << "public:\n"; - os << " inline " << name << "() noexcept : storage(nullptr) { }\n"; - os << " inline " << name - << "(ValueWitnessTable * _Nonnull vwTable) noexcept : storage(" - "reinterpret_cast(opaqueAlloc(vwTable->size, (vwTable->flags &" - << TargetValueWitnessFlags::AlignmentMask << ") + 1))) { }\n"; - os << " inline " << name << "(" << name - << "&& other) noexcept : storage(other.storage) { other.storage = " - "nullptr; }\n"; - os << " inline " << name << "(const " << name << "&) noexcept = delete;\n"; - os << " inline ~" << name - << "() noexcept { if (storage) { opaqueFree(static_cast(storage)); } }\n"; - os << " void operator =(" << name - << "&& other) noexcept { auto temp = storage; storage = other.storage; " - "other.storage = temp; }\n"; - os << " void operator =(const " << name << "&) noexcept = delete;\n"; - os << " inline char * _Nonnull getOpaquePointer() noexcept { return " - "static_cast(storage); }\n"; - os << " inline const char * _Nonnull getOpaquePointer() const noexcept { " - "return " - "static_cast(storage); }\n"; - os << "private:\n"; - os << " char * _Nullable storage;\n"; - os << "};\n"; -} - void printCxxNaiveException(raw_ostream &os) { - os << "\n"; os << "/// Naive exception class that should be thrown\n"; os << "class NaiveException {\n"; os << "public:\n"; @@ -273,7 +239,6 @@ void swift::printSwiftToClangCoreScaffold(SwiftToClangInteropContext &ctx, /*isCForwardDefinition=*/true); }); os << "\n"; - printSwiftResilientStorageClass(os); printCxxNaiveException(os); }); os << "\n"; diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index cc65465cfb238..826802e7dff97 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -50,7 +50,7 @@ TypeConverter::getAbstractionPattern(AbstractStorageDecl *decl, AbstractionPattern TypeConverter::getAbstractionPattern(SubscriptDecl *decl, bool isNonObjC) { auto sig = decl->getGenericSignatureOfContext().getCanonicalSignature(); - auto type = sig.getCanonicalTypeInContext(decl->getElementInterfaceType()); + auto type = sig.getReducedType(decl->getElementInterfaceType()); return AbstractionPattern(sig, type); } @@ -79,7 +79,7 @@ TypeConverter::getAbstractionPattern(VarDecl *var, bool isNonObjC) { auto sig = var->getDeclContext() ->getGenericSignatureOfContext() .getCanonicalSignature(); - auto swiftType = sig.getCanonicalTypeInContext(var->getInterfaceType()); + auto swiftType = sig.getReducedType(var->getInterfaceType()); if (isNonObjC) return AbstractionPattern(sig, swiftType); @@ -111,7 +111,7 @@ AbstractionPattern TypeConverter::getAbstractionPattern(EnumElementDecl *decl) { auto sig = decl->getParentEnum() ->getGenericSignatureOfContext() .getCanonicalSignature(); - auto type = sig.getCanonicalTypeInContext(decl->getArgumentInterfaceType()); + auto type = sig.getReducedType(decl->getArgumentInterfaceType()); return AbstractionPattern(sig, type); } @@ -1231,7 +1231,7 @@ const { case Kind::Discard: auto memberTy = getType()->getTypeOfMember(member->getModuleContext(), member, origMemberInterfaceType) - ->getCanonicalType(getGenericSignature()); + ->getReducedType(getGenericSignature()); return AbstractionPattern(getGenericSignature(), memberTy); } @@ -1253,7 +1253,7 @@ AbstractionPattern AbstractionPattern::getAutoDiffDerivativeFunctionType( assert(derivativeFnTy); return AbstractionPattern( getGenericSignature(), - derivativeFnTy->getCanonicalType(getGenericSignature())); + derivativeFnTy->getReducedType(getGenericSignature())); } case Kind::Opaque: return getOpaqueDerivativeFunction(); @@ -1882,10 +1882,10 @@ const { auto yieldType = visitor.substYieldType; if (yieldType) - yieldType = yieldType->getCanonicalType(substSig); + yieldType = yieldType->getReducedType(substSig); return std::make_tuple( - AbstractionPattern(substSig, substTy->getCanonicalType(substSig)), + AbstractionPattern(substSig, substTy->getReducedType(substSig)), subMap, yieldType ? AbstractionPattern(substSig, yieldType) diff --git a/lib/SIL/IR/SIL.cpp b/lib/SIL/IR/SIL.cpp index 11f189b6f28ee..bb7815b12cbbe 100644 --- a/lib/SIL/IR/SIL.cpp +++ b/lib/SIL/IR/SIL.cpp @@ -353,7 +353,7 @@ bool AbstractStorageDecl::exportsPropertyDescriptor() const { return false; auto indexTy = index->getInterfaceType() - ->getCanonicalType(sub->getGenericSignatureOfContext()); + ->getReducedType(sub->getGenericSignatureOfContext()); // TODO: Handle reabstraction and tuple explosion in thunk generation. // This wasn't previously a concern because anything that was Hashable diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index bceac099ce847..38412802f9c9d 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -485,7 +485,7 @@ static CanSILFunctionType getAutoDiffDifferentialType( auto sig = buildDifferentiableGenericSignature( originalFnTy->getSubstGenericSignature(), tanType, origTypeOfAbstraction); - tanType = tanType->getCanonicalType(sig); + tanType = tanType->getReducedType(sig); AbstractionPattern pattern(sig, tanType); auto &tl = TC.getTypeLowering(pattern, tanType, TypeExpansionContext::minimal()); @@ -513,7 +513,7 @@ static CanSILFunctionType getAutoDiffDifferentialType( auto sig = buildDifferentiableGenericSignature( originalFnTy->getSubstGenericSignature(), tanType, origTypeOfAbstraction); - tanType = tanType->getCanonicalType(sig); + tanType = tanType->getReducedType(sig); AbstractionPattern pattern(sig, tanType); auto &tl = TC.getTypeLowering(pattern, tanType, TypeExpansionContext::minimal()); @@ -633,7 +633,7 @@ static CanSILFunctionType getAutoDiffPullbackType( auto sig = buildDifferentiableGenericSignature( originalFnTy->getSubstGenericSignature(), tanType, origTypeOfAbstraction); - tanType = tanType->getCanonicalType(sig); + tanType = tanType->getReducedType(sig); AbstractionPattern pattern(sig, tanType); auto &tl = TC.getTypeLowering(pattern, tanType, TypeExpansionContext::minimal()); @@ -664,7 +664,7 @@ static CanSILFunctionType getAutoDiffPullbackType( auto sig = buildDifferentiableGenericSignature( originalFnTy->getSubstGenericSignature(), tanType, origTypeOfAbstraction); - tanType = tanType->getCanonicalType(sig); + tanType = tanType->getReducedType(sig); AbstractionPattern pattern(sig, tanType); auto &tl = TC.getTypeLowering(pattern, tanType, TypeExpansionContext::minimal()); @@ -801,7 +801,7 @@ static SILFunctionType *getConstrainedAutoDiffOriginalFunctionType( newParameters.reserve(original->getNumParameters()); for (auto ¶m : original->getParameters()) { newParameters.push_back( - param.getWithInterfaceType(param.getInterfaceType()->getCanonicalType( + param.getWithInterfaceType(param.getInterfaceType()->getReducedType( constrainedInvocationGenSig))); } @@ -809,7 +809,7 @@ static SILFunctionType *getConstrainedAutoDiffOriginalFunctionType( newResults.reserve(original->getNumResults()); for (auto &result : original->getResults()) { newResults.push_back( - result.getWithInterfaceType(result.getInterfaceType()->getCanonicalType( + result.getWithInterfaceType(result.getInterfaceType()->getReducedType( constrainedInvocationGenSig))); } return SILFunctionType::get( @@ -1680,7 +1680,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, auto selfMetatype = MetatypeType::get(dynamicSelfInterfaceType, MetatypeRepresentation::Thick); - auto canSelfMetatype = selfMetatype->getCanonicalType(origGenericSig); + auto canSelfMetatype = selfMetatype->getReducedType(origGenericSig); SILParameterInfo param(canSelfMetatype, convention); inputs.push_back(param); @@ -1690,7 +1690,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, if (capture.isOpaqueValue()) { OpaqueValueExpr *opaqueValue = capture.getOpaqueValue(); auto canType = opaqueValue->getType()->mapTypeOutOfContext() - ->getCanonicalType(origGenericSig); + ->getReducedType(origGenericSig); auto &loweredTL = TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType, expansion); @@ -1710,7 +1710,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, auto *VD = capture.getDecl(); auto type = VD->getInterfaceType(); - auto canType = type->getCanonicalType(origGenericSig); + auto canType = type->getReducedType(origGenericSig); auto &loweredTL = TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType, @@ -1962,7 +1962,7 @@ static CanSILFunctionType getSILFunctionType( valueType = valueType.subst(*reqtSubs); } - coroutineSubstYieldType = valueType->getCanonicalType(genericSig); + coroutineSubstYieldType = valueType->getReducedType(genericSig); } bool shouldBuildSubstFunctionType = [&]{ @@ -2645,7 +2645,7 @@ CanSILFunctionType swift::buildSILFunctionThunkType( } auto mapTypeOutOfContext = [&](CanType type) -> CanType { - return type->mapTypeOutOfContext()->getCanonicalType(genericSig); + return type->mapTypeOutOfContext()->getCanonicalType(); }; // Map the parameter and expected types out of context to get the interface diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index bc4e7256d8015..7c4e20dffc6fc 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2055,7 +2055,7 @@ namespace { // would, we use the substituted field type in order to accurately // preserve the properties of the aggregate. auto sig = field->getDeclContext()->getGenericSignatureOfContext(); - auto interfaceTy = field->getInterfaceType()->getCanonicalType(sig); + auto interfaceTy = field->getInterfaceType()->getReducedType(sig); auto origFieldType = origType.unsafeGetSubstFieldType(field, interfaceTy); @@ -2116,7 +2116,7 @@ namespace { auto origEltType = origType.unsafeGetSubstFieldType(elt, elt->getArgumentInterfaceType() - ->getCanonicalType(D->getGenericSignature())); + ->getReducedType(D->getGenericSignature())); properties.addSubobject(classifyType(origEltType, substEltType, TC, Expansion)); } @@ -2734,7 +2734,7 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType( // The result type might be written in terms of type parameters // that have been made fully concrete. - CanType canResultTy = resultTy->getCanonicalType( + CanType canResultTy = resultTy->getReducedType( vd->getInnermostDeclContext() ->getGenericSignatureOfContext()); @@ -2812,7 +2812,7 @@ static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd, bool isDeallocating, bool isForeign) { auto classType = dd->getDeclContext()->getDeclaredInterfaceType() - ->getCanonicalType(dd->getGenericSignatureOfContext()); + ->getReducedType(dd->getGenericSignatureOfContext()); assert((!isForeign || isDeallocating) && "There are no foreign destroying destructors"); @@ -2848,7 +2848,7 @@ static CanAnyFunctionType getIVarInitDestroyerInterfaceType(ClassDecl *cd, bool isObjC, bool isDestroyer) { auto classType = cd->getDeclaredInterfaceType() - ->getCanonicalType(cd->getGenericSignatureOfContext()); + ->getReducedType(cd->getGenericSignatureOfContext()); auto resultType = (isDestroyer ? TupleType::getEmpty(cd->getASTContext()) @@ -3778,12 +3778,7 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured, /*captures generics*/ false); // Instantiate the layout with identity substitutions. - auto subMap = SubstitutionMap::get( - signature, - [&](SubstitutableType *type) -> Type { - return signature.getCanonicalTypeInContext(type); - }, - MakeAbstractConformanceForGenericType()); + auto subMap = signature->getIdentitySubstitutionMap(); auto boxTy = SILBoxType::get(C, layout, subMap); #ifndef NDEBUG @@ -3817,7 +3812,7 @@ TypeConverter::getContextBoxTypeForCapture(ValueDecl *captured, ->getGenericSignatureOfContext(); loweredInterfaceType = loweredInterfaceType->mapTypeOutOfContext() - ->getCanonicalType(homeSig); + ->getReducedType(homeSig); } auto boxType = getInterfaceBoxTypeForCapture(captured, diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 47ec7edf491b1..bdc1ae2aadfce 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -5945,8 +5945,8 @@ void SILProperty::verify(const SILModule &M) const { // TODO: base type for global/static descriptors auto sig = dc->getGenericSignatureOfContext(); auto baseTy = dc->getInnermostTypeContext()->getSelfInterfaceType() - ->getCanonicalType(sig); - auto leafTy = decl->getValueInterfaceType()->getCanonicalType(sig); + ->getReducedType(sig); + auto leafTy = decl->getValueInterfaceType()->getReducedType(sig); SubstitutionMap subs; if (sig) { auto env = dc->getGenericEnvironmentOfContext(); diff --git a/lib/SILGen/ResultPlan.cpp b/lib/SILGen/ResultPlan.cpp index 9621f035fe8be..11f8d50867b01 100644 --- a/lib/SILGen/ResultPlan.cpp +++ b/lib/SILGen/ResultPlan.cpp @@ -179,7 +179,7 @@ class IndirectOpenedSelfResultPlan final : public ResultPlan { layoutSubs.getGenericSignature().getCanonicalSignature(); auto boxLayout = SILLayout::get(SGF.getASTContext(), layoutSig, - SILField(layoutTy->getCanonicalType(layoutSig), true), + SILField(layoutTy->getReducedType(layoutSig), true), /*captures generics*/ false); resultBox = SGF.B.createAllocBox(loc, @@ -576,8 +576,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan { SILFunction *impl = SGF.SGM.getOrCreateForeignAsyncCompletionHandlerImplFunction( cast( - impFnTy->mapTypeOutOfContext()->getCanonicalType(sig)), - continuationTy->mapTypeOutOfContext()->getCanonicalType(sig), + impFnTy->mapTypeOutOfContext()->getReducedType(sig)), + continuationTy->mapTypeOutOfContext()->getReducedType(sig), origFormalType, sig, *calleeTypeInfo.foreign.async, calleeTypeInfo.foreign.error); auto impRef = SGF.B.createFunctionRef(loc, impl); @@ -660,7 +660,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan { auto sig = env ? env->getGenericSignature().getCanonicalSignature() : CanGenericSignature(); auto mappedContinuationTy = - continuationBGT->mapTypeOutOfContext()->getCanonicalType(sig); + continuationBGT->mapTypeOutOfContext()->getReducedType(sig); auto resumeType = cast(mappedContinuationTy).getGenericArgs()[0]; auto continuationTy = continuationBGT->getCanonicalType(); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 38a16aa4b872e..b5c3a8ec9c9ce 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -1902,8 +1902,8 @@ void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) { assert(!decl->isStatic()); baseTy = decl->getDeclContext()->getSelfInterfaceType() - ->getCanonicalType(decl->getInnermostDeclContext() - ->getGenericSignatureOfContext()); + ->getReducedType(decl->getInnermostDeclContext() + ->getGenericSignatureOfContext()); } else { // TODO: Global variables should eventually be referenceable as // key paths from (), viz. baseTy = TupleType::getEmpty(getASTContext()); diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 4c7817e52b285..63b60b98bd233 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -6164,7 +6164,7 @@ ManagedValue SILGenFunction::emitReadAsyncLetBinding(SILLocation loc, // Load and reabstract the value if needed. auto genericSig = F.getLoweredFunctionType()->getInvocationGenericSignature(); - auto substVarTy = var->getType()->getCanonicalType(genericSig); + auto substVarTy = var->getType()->getReducedType(genericSig); auto substAbstraction = AbstractionPattern(genericSig, substVarTy); return emitLoad(loc, visitor.varAddr, substAbstraction, substVarTy, getTypeLowering(substAbstraction, substVarTy), diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 6c21e8fa21701..6584ff2ad93f1 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3267,7 +3267,7 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, = GenericEnvironment::mapConformanceRefIntoContext(genericEnv, formalTy, hashable); - auto formalCanTy = formalTy->getCanonicalType(genericSig); + auto formalCanTy = formalTy->getReducedType(genericSig); // Get the Equatable conformance from the Hashable conformance. auto equatable = hashable.getAssociatedConformance( @@ -3693,8 +3693,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc, ->getTypeOfMember(SwiftModule, var) ->getReferenceStorageReferent() ->mapTypeOutOfContext() - ->getCanonicalType( - genericEnv ? genericEnv->getGenericSignature() : nullptr); + ->getCanonicalType(); // The component type for an @objc optional requirement needs to be // wrapped in an optional. diff --git a/lib/SILGen/SILGenLazyConformance.cpp b/lib/SILGen/SILGenLazyConformance.cpp index 31ead79fed57d..949bf54a75149 100644 --- a/lib/SILGen/SILGenLazyConformance.cpp +++ b/lib/SILGen/SILGenLazyConformance.cpp @@ -334,7 +334,7 @@ void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) { for (auto *EED : ED->getAllElements()) { if (EED->hasAssociatedValues()) { useConformancesFromType(EED->getArgumentInterfaceType() - ->getCanonicalType(genericSig)); + ->getReducedType(genericSig)); } } } @@ -342,13 +342,13 @@ void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) { if (isa(NTD) || isa(NTD)) { for (auto *VD : NTD->getStoredProperties()) { useConformancesFromType(VD->getValueInterfaceType() - ->getCanonicalType(genericSig)); + ->getReducedType(genericSig)); } } if (auto *CD = dyn_cast(NTD)) if (auto superclass = CD->getSuperclass()) - useConformancesFromType(superclass->getCanonicalType(genericSig)); + useConformancesFromType(superclass->getReducedType(genericSig)); if (auto *PD = dyn_cast(NTD)) { for (auto reqt : PD->getRequirementSignature().getRequirements()) { diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index 5cf19d7f1e321..3a5e75a963598 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -458,7 +458,7 @@ static void emitCaptureArguments(SILGenFunction &SGF, // Local function to get the captured variable type within the capturing // context. auto getVarTypeInCaptureContext = [&]() -> Type { - auto interfaceType = VD->getInterfaceType()->getCanonicalType( + auto interfaceType = VD->getInterfaceType()->getReducedType( origGenericSig); return SGF.F.mapTypeIntoContext(interfaceType); }; @@ -1014,7 +1014,7 @@ uint16_t SILGenFunction::emitBasicProlog(ParameterList *paramList, Optional origClosureType) { // Create the indirect result parameters. auto genericSig = DC->getGenericSignatureOfContext(); - resultType = resultType->getCanonicalType(genericSig); + resultType = resultType->getReducedType(genericSig); AbstractionPattern origResultType = origClosureType ? origClosureType->getFunctionResultType() diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 3d5955b751cce..21015cc8106f0 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -732,7 +732,7 @@ SILFunction *SILGenModule::emitProtocolWitness( // The type of the witness thunk. auto reqtSubstTy = cast( reqtOrigTy->substGenericArgs(reqtSubMap) - ->getCanonicalType(genericSig)); + ->getReducedType(genericSig)); // Generic signatures where all parameters are concrete are lowered away // at the SILFunctionType level. diff --git a/lib/SILOptimizer/Differentiation/JVPCloner.cpp b/lib/SILOptimizer/Differentiation/JVPCloner.cpp index 0ac7cbfa9edca..387e08018e8ee 100644 --- a/lib/SILOptimizer/Differentiation/JVPCloner.cpp +++ b/lib/SILOptimizer/Differentiation/JVPCloner.cpp @@ -145,7 +145,7 @@ class JVPCloner::Implementation final SILType getLoweredType(Type type) { auto jvpGenSig = jvp->getLoweredFunctionType()->getSubstGenericSignature(); Lowering::AbstractionPattern pattern(jvpGenSig, - type->getCanonicalType(jvpGenSig)); + type->getReducedType(jvpGenSig)); return jvp->getLoweredType(pattern, type); } @@ -352,7 +352,7 @@ class JVPCloner::Implementation final /// Find the tangent space of a given canonical type. Optional getTangentSpace(CanType type) { // Use witness generic signature to remap types. - type = witness->getDerivativeGenericSignature().getCanonicalTypeInContext( + type = witness->getDerivativeGenericSignature().getReducedType( type); return type->getAutoDiffTangentSpace( LookUpConformanceInModule(getModule().getSwiftModule())); @@ -1627,12 +1627,12 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { // Handle formal original result. auto origResult = origTy->getResults()[resultIndex]; origResult = origResult.getWithInterfaceType( - origResult.getInterfaceType()->getCanonicalType(witnessCanGenSig)); + origResult.getInterfaceType()->getReducedType(witnessCanGenSig)); dfResults.push_back( SILResultInfo(origResult.getInterfaceType() ->getAutoDiffTangentSpace(lookupConformance) ->getType() - ->getCanonicalType(witnessCanGenSig), + ->getReducedType(witnessCanGenSig), origResult.getConvention())); } else { // Handle original `inout` parameter. @@ -1659,12 +1659,12 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { for (auto i : config.parameterIndices->getIndices()) { auto origParam = origParams[i]; origParam = origParam.getWithInterfaceType( - origParam.getInterfaceType()->getCanonicalType(witnessCanGenSig)); + origParam.getInterfaceType()->getReducedType(witnessCanGenSig)); dfParams.push_back( SILParameterInfo(origParam.getInterfaceType() ->getAutoDiffTangentSpace(lookupConformance) ->getType() - ->getCanonicalType(witnessCanGenSig), + ->getReducedType(witnessCanGenSig), origParam.getConvention())); } @@ -1673,7 +1673,7 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { auto *origEntry = original->getEntryBlock(); auto *dfStruct = linearMapInfo->getLinearMapStruct(origEntry); auto dfStructType = - dfStruct->getDeclaredInterfaceType()->getCanonicalType(witnessCanGenSig); + dfStruct->getDeclaredInterfaceType()->getReducedType(witnessCanGenSig); dfParams.push_back({dfStructType, ParameterConvention::Direct_Owned}); Mangle::DifferentiationMangler mangler; diff --git a/lib/SILOptimizer/Differentiation/PullbackCloner.cpp b/lib/SILOptimizer/Differentiation/PullbackCloner.cpp index b97d2a85effa1..0f5d901321552 100644 --- a/lib/SILOptimizer/Differentiation/PullbackCloner.cpp +++ b/lib/SILOptimizer/Differentiation/PullbackCloner.cpp @@ -194,7 +194,7 @@ class PullbackCloner::Implementation final auto pbGenSig = getPullback().getLoweredFunctionType()->getSubstGenericSignature(); Lowering::AbstractionPattern pattern(pbGenSig, - type->getCanonicalType(pbGenSig)); + type->getReducedType(pbGenSig)); return getPullback().getTypeLowering(pattern, type); } @@ -202,7 +202,7 @@ class PullbackCloner::Implementation final SILType remapType(SILType ty) { if (ty.hasArchetype()) ty = ty.mapTypeOutOfContext(); - auto remappedType = ty.getASTType()->getCanonicalType( + auto remappedType = ty.getASTType()->getReducedType( getPullback().getLoweredFunctionType()->getSubstGenericSignature()); auto remappedSILType = SILType::getPrimitiveType(remappedType, ty.getCategory()); @@ -212,7 +212,7 @@ class PullbackCloner::Implementation final Optional getTangentSpace(CanType type) { // Use witness generic signature to remap types. type = - getWitness()->getDerivativeGenericSignature().getCanonicalTypeInContext( + getWitness()->getDerivativeGenericSignature().getReducedType( type); return type->getAutoDiffTangentSpace( LookUpConformanceInModule(getModule().getSwiftModule())); diff --git a/lib/SILOptimizer/Differentiation/VJPCloner.cpp b/lib/SILOptimizer/Differentiation/VJPCloner.cpp index fea64e520a8d7..b11b61ea47ff0 100644 --- a/lib/SILOptimizer/Differentiation/VJPCloner.cpp +++ b/lib/SILOptimizer/Differentiation/VJPCloner.cpp @@ -137,7 +137,7 @@ class VJPCloner::Implementation final SILType getLoweredType(Type type) { auto vjpGenSig = vjp->getLoweredFunctionType()->getSubstGenericSignature(); Lowering::AbstractionPattern pattern(vjpGenSig, - type->getCanonicalType(vjpGenSig)); + type->getReducedType(vjpGenSig)); return vjp->getLoweredType(pattern, type); } @@ -809,7 +809,7 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { // Given a type, returns its formal SIL parameter info. auto getTangentParameterInfoForOriginalResult = [&](CanType tanType, ResultConvention origResConv) -> SILParameterInfo { - tanType = tanType->getCanonicalType(witnessCanGenSig); + tanType = tanType->getReducedType(witnessCanGenSig); Lowering::AbstractionPattern pattern(witnessCanGenSig, tanType); auto &tl = context.getTypeConverter().getTypeLowering( pattern, tanType, TypeExpansionContext::minimal()); @@ -836,7 +836,7 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { // Given a type, returns its formal SIL result info. auto getTangentResultInfoForOriginalParameter = [&](CanType tanType, ParameterConvention origParamConv) -> SILResultInfo { - tanType = tanType->getCanonicalType(witnessCanGenSig); + tanType = tanType->getReducedType(witnessCanGenSig); Lowering::AbstractionPattern pattern(witnessCanGenSig, tanType); auto &tl = context.getTypeConverter().getTypeLowering( pattern, tanType, TypeExpansionContext::minimal()); @@ -886,12 +886,12 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { if (resultIndex < origTy->getNumResults()) { auto origResult = origTy->getResults()[resultIndex]; origResult = origResult.getWithInterfaceType( - origResult.getInterfaceType()->getCanonicalType(witnessCanGenSig)); + origResult.getInterfaceType()->getReducedType(witnessCanGenSig)); pbParams.push_back(getTangentParameterInfoForOriginalResult( origResult.getInterfaceType() ->getAutoDiffTangentSpace(lookupConformance) ->getType() - ->getCanonicalType(witnessCanGenSig), + ->getReducedType(witnessCanGenSig), origResult.getConvention())); continue; } @@ -911,7 +911,7 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { } auto inoutParam = origParams[paramIndex]; auto origResult = inoutParam.getWithInterfaceType( - inoutParam.getInterfaceType()->getCanonicalType(witnessCanGenSig)); + inoutParam.getInterfaceType()->getReducedType(witnessCanGenSig)); auto inoutParamTanConvention = config.isWrtParameter(paramIndex) ? inoutParam.getConvention() @@ -920,7 +920,7 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { origResult.getInterfaceType() ->getAutoDiffTangentSpace(lookupConformance) ->getType() - ->getCanonicalType(witnessCanGenSig), + ->getReducedType(witnessCanGenSig), inoutParamTanConvention); pbParams.push_back(inoutParamTanParam); } @@ -937,7 +937,7 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { auto *origExit = &*original->findReturnBB(); auto *pbStruct = pullbackInfo.getLinearMapStruct(origExit); auto pbStructType = - pbStruct->getDeclaredInterfaceType()->getCanonicalType(witnessCanGenSig); + pbStruct->getDeclaredInterfaceType()->getReducedType(witnessCanGenSig); pbParams.push_back({pbStructType, ParameterConvention::Direct_Owned}); } @@ -947,12 +947,12 @@ SILFunction *VJPCloner::Implementation::createEmptyPullback() { if (origParam.isIndirectMutating()) continue; origParam = origParam.getWithInterfaceType( - origParam.getInterfaceType()->getCanonicalType(witnessCanGenSig)); + origParam.getInterfaceType()->getReducedType(witnessCanGenSig)); adjResults.push_back(getTangentResultInfoForOriginalParameter( origParam.getInterfaceType() ->getAutoDiffTangentSpace(lookupConformance) ->getType() - ->getCanonicalType(witnessCanGenSig), + ->getReducedType(witnessCanGenSig), origParam.getConvention())); } diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index 54e013eee793f..04c5c9af7f988 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -345,11 +345,6 @@ ExistentialTransform::createExistentialSpecializedFunctionType() { std::move(GenericParams), std::move(Requirements)); - /// Create a lambda for GenericParams. - auto getCanonicalType = [&](Type t) -> CanType { - return t->getCanonicalType(NewGenericSig); - }; - /// Original list of parameters SmallVector params; params.append(FTy->getParameters().begin(), FTy->getParameters().end()); @@ -362,7 +357,7 @@ ExistentialTransform::createExistentialSpecializedFunctionType() { auto iter = ArgToGenericTypeMap.find(Idx); if (iter != ArgToGenericTypeMap.end()) { auto GenericParam = iter->second; - InterfaceParams.push_back(SILParameterInfo(getCanonicalType(GenericParam), + InterfaceParams.push_back(SILParameterInfo(GenericParam->getReducedType(NewGenericSig), param.getConvention())); } else { InterfaceParams.push_back(param); diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp index 0635c36a6836a..53760d54c8280 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp @@ -291,7 +291,8 @@ SILCombiner::optimizeAlignment(PointerToAddressInst *ptrAdrInst) { if (match(alignOper, m_ApplyInst(BuiltinValueKind::Alignof))) { CanType formalType = cast(alignOper)->getSubstitutions() - .getReplacementTypes()[0]->getCanonicalType(ptrAdrInst->getFunction()->getGenericSignature()); + .getReplacementTypes()[0]->getReducedType( + ptrAdrInst->getFunction()->getGenericSignature()); SILType instanceType = ptrAdrInst->getFunction()->getLoweredType( Lowering::AbstractionPattern::getOpaque(), formalType); diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index af88f3fb33f48..505cf3472ef21 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -812,7 +812,7 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF, // First substitute concrete types into the existing function type. CanSILFunctionType FnTy = - cast(CanSpecializedGenericSig.getCanonicalTypeInContext( + cast(CanSpecializedGenericSig.getReducedType( OrigF->getLoweredFunctionType() ->substGenericArgs(M, SubstMap, getResilienceExpansion()) ->getUnsubstitutedType(M))); @@ -1449,7 +1449,7 @@ void FunctionSignaturePartialSpecializer:: createGenericParamsForCalleeGenericParams() { for (auto GP : CalleeGenericSig.getGenericParams()) { auto CanTy = GP->getCanonicalType(); - auto CanTyInContext = CalleeGenericSig.getCanonicalTypeInContext(CanTy); + auto CanTyInContext = CalleeGenericSig.getReducedType(CanTy); auto Replacement = CanTyInContext.subst(CalleeInterfaceToCallerArchetypeMap); LLVM_DEBUG(llvm::dbgs() << "\n\nChecking callee generic parameter:\n"; CanTy->dump(llvm::dbgs())); diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 675c984757c06..1ef4e71877e20 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -919,8 +919,6 @@ class ResultBuilderTransform using UnsupportedElt = SkipUnhandledConstructInResultBuilder::UnhandledNode; - /// The constraint system this transform is associated with. - ConstraintSystem &CS; /// The result type of this result builder body. Type ResultType; @@ -930,8 +928,7 @@ class ResultBuilderTransform public: ResultBuilderTransform(ConstraintSystem &cs, DeclContext *dc, Type builderType, Type resultTy) - : BuilderTransformerBase(&cs, dc, builderType), CS(cs), - ResultType(resultTy) {} + : BuilderTransformerBase(&cs, dc, builderType), ResultType(resultTy) {} UnsupportedElt getUnsupportedElement() const { return FirstUnsupported; } @@ -1180,10 +1177,6 @@ class ResultBuilderTransform {buildBlockResult}, {Identifier()}); } - // Type erase return if the result type requires it. - buildBlockResult = CS.buildTypeErasedExpr(buildBlockResult, dc, - ResultType, CTP_ReturnStmt); - elements.push_back(new (ctx) ReturnStmt(resultLoc, buildBlockResult, /*Implicit=*/true)); } diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp index e689f1474a1e2..d299c02ac791b 100644 --- a/lib/Sema/CSClosure.cpp +++ b/lib/Sema/CSClosure.cpp @@ -1607,6 +1607,8 @@ class SyntacticElementSolutionApplication } ASTNode visitReturnStmt(ReturnStmt *returnStmt) { + auto &cs = solution.getConstraintSystem(); + if (!returnStmt->hasResult()) { // If contextual is not optional, there is nothing to do here. if (resultType->isVoid()) @@ -1621,8 +1623,6 @@ class SyntacticElementSolutionApplication assert(resultType->getOptionalObjectType() && resultType->lookThroughAllOptionalTypes()->isVoid()); - auto &cs = solution.getConstraintSystem(); - auto target = *cs.getSolutionApplicationTarget(returnStmt); returnStmt->setResult(target.getAsExpr()); } @@ -1652,13 +1652,24 @@ class SyntacticElementSolutionApplication mode = convertToResult; } - SolutionApplicationTarget resultTarget( - resultExpr, context.getAsDeclContext(), - mode == convertToResult ? CTP_ReturnStmt : CTP_Unused, - mode == convertToResult ? resultType : Type(), - /*isDiscarded=*/false); - if (auto newResultTarget = rewriteTarget(resultTarget)) + Optional resultTarget; + if (auto target = cs.getSolutionApplicationTarget(returnStmt)) { + resultTarget = *target; + } else { + // Single-expression closures have to handle returns in a special + // way so the target has to be created for them during solution + // application based on the resolved type. + assert(isSingleExpression); + resultTarget = SolutionApplicationTarget( + resultExpr, context.getAsDeclContext(), + mode == convertToResult ? CTP_ReturnStmt : CTP_Unused, + mode == convertToResult ? resultType : Type(), + /*isDiscarded=*/false); + } + + if (auto newResultTarget = rewriteTarget(*resultTarget)) { resultExpr = newResultTarget->getAsExpr(); + } switch (mode) { case convertToResult: diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 1ae4721808401..cdccf891d32d4 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1988,7 +1988,7 @@ typeEraseExistentialSelfReferences( // If the type parameter is beyond the domain of the existential generic // signature, ignore it. - if (!existentialSig->isValidTypeInContext(t)) { + if (!existentialSig->isValidTypeParameter(t)) { return Type(t); } @@ -6549,7 +6549,7 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase( return Action::SkipChildren; } - if (!Sig->isValidTypeInContext(ty)) { + if (!Sig->isValidTypeParameter(ty)) { return Action::SkipChildren; } diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 0f938861e4df1..bb2244bf8c566 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2517,7 +2517,7 @@ static void checkSpecializeAttrRequirements(SpecializeAttr *attr, for (auto *paramTy : specializedSig.getGenericParams()) { auto canTy = paramTy->getCanonicalType(); - if (specializedSig->isCanonicalTypeInContext(canTy) && + if (specializedSig->isReducedType(canTy) && (!specializedSig->getLayoutConstraint(canTy) || originalSig->getLayoutConstraint(canTy))) { unspecializedParams.push_back(paramTy); @@ -4547,7 +4547,7 @@ static bool checkFunctionSignature( auto xInstanceTy = x.getOldType()->getMetatypeInstanceType(); auto yInstanceTy = y.getOldType()->getMetatypeInstanceType(); return xInstanceTy->isEqual( - requiredGenSig.getCanonicalTypeInContext(yInstanceTy)); + requiredGenSig.getReducedType(yInstanceTy)); })) return false; @@ -4555,7 +4555,7 @@ static bool checkFunctionSignature( // match exactly. auto requiredResultFnTy = dyn_cast(required.getResult()); auto candidateResultTy = - requiredGenSig.getCanonicalTypeInContext(candidateFnTy.getResult()); + requiredGenSig.getReducedType(candidateFnTy.getResult()); if (!requiredResultFnTy) { auto requiredResultTupleTy = dyn_cast(required.getResult()); auto candidateResultTupleTy = dyn_cast(candidateResultTy); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index cc4e7d345830c..bc497b8abf133 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -151,7 +151,7 @@ bool swift::isOverrideBasedOnType(const ValueDecl *decl, Type declTy, auto genericSig = decl->getInnermostDeclContext()->getGenericSignatureOfContext(); - auto canDeclTy = declTy->getCanonicalType(genericSig); + auto canDeclTy = declTy->getReducedType(genericSig); auto declIUOAttr = decl->isImplicitlyUnwrappedOptional(); auto parentDeclIUOAttr = parentDecl->isImplicitlyUnwrappedOptional(); @@ -198,7 +198,7 @@ bool swift::isOverrideBasedOnType(const ValueDecl *decl, Type declTy, if (parentDeclTy->hasError()) return false; - auto canParentDeclTy = parentDeclTy->getCanonicalType(genericSig); + auto canParentDeclTy = parentDeclTy->getReducedType(genericSig); // If this is a constructor, let's compare only parameter types. if (isa(decl)) { @@ -1264,7 +1264,7 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, auto parentPropertyTy = getSuperMemberDeclType(baseDecl); CanType parentPropertyCanTy = - parentPropertyTy->getCanonicalType( + parentPropertyTy->getReducedType( decl->getInnermostDeclContext()->getGenericSignatureOfContext()); if (!propertyTy->matches(parentPropertyCanTy, TypeMatchFlags::AllowOverride)) { diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 3cb1762b649b0..2278a8f4171f7 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -834,7 +834,7 @@ Type AssociatedTypeInference::computeFixedTypeWitness( continue; auto structuralTy = DependentMemberType::get(selfTy, assocType->getName()); - const auto ty = sig.getCanonicalTypeInContext(structuralTy); + const auto ty = sig.getReducedType(structuralTy); // A dependent member type with an identical base and name indicates that // the protocol does not same-type constrain it in any way; move on to @@ -1286,7 +1286,7 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses( std::function substCurrentTypeWitnesses; substCurrentTypeWitnesses = [&](Type ty) -> Type { if (auto *gp = ty->getAs()) { - // FIXME: 'computeFixedTypeWitness' uses 'getCanonicalTypeInContext', + // FIXME: 'computeFixedTypeWitness' uses 'getReducedType', // so if a generic parameter is canonical here, it's 'Self'. if (gp->isCanonical() || isa(gp->getDecl()->getDeclContext()->getAsDecl())) { diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index b2e4efa990f60..fcc683e700ddb 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2682,13 +2682,6 @@ static VarDecl *synthesizePropertyWrapperProjectionVar( var->getAttrs().add( new (ctx) ProjectedValuePropertyAttr(name, SourceLoc(), SourceRange(), /*Implicit=*/true)); - - // If the wrapped property has a nonisolated attribute, propagate it to - // the synthesized projectedValue as well. - if (var->getAttrs().getAttribute()) { - property->getAttrs().add(new (ctx) NonisolatedAttr(/*Implicit=*/true)); - } - return property; } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 594109b7ffd5b..d0f63ee3a3c3e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -235,10 +235,10 @@ bool TypeResolution::areSameType(Type type1, Type type2) const { // If both are type parameters, we can use a cheaper check // that avoids transforming the type and computing anchors. if (type1->isTypeParameter() && type2->isTypeParameter()) { - return genericSig->areSameTypeParameterInContext(type1, type2); + return genericSig->areReducedTypeParametersEqual(type1, type2); } - return genericSig.getCanonicalTypeInContext(type1) == - genericSig.getCanonicalTypeInContext(type2); + return genericSig.getReducedType(type1) == + genericSig.getReducedType(type2); } } diff --git a/stdlib/CMakeLists.txt b/stdlib/CMakeLists.txt index b3590fdf6fc3b..7e0d2d27666a6 100644 --- a/stdlib/CMakeLists.txt +++ b/stdlib/CMakeLists.txt @@ -39,8 +39,6 @@ include(StdlibOptions) # End of user-configurable options. # -set(SWIFT_STDLIB_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - # Remove llvm-project/llvm/include directory from -I search part when building # the stdlib. We have our own fork of LLVM includes (Support, ADT) in # stdlib/include/llvm and we don't want to silently use headers from LLVM. diff --git a/stdlib/public/Distributed/DistributedActor.cpp b/stdlib/public/Distributed/DistributedActor.cpp index 17962d301a19b..36536e1cbb3ae 100644 --- a/stdlib/public/Distributed/DistributedActor.cpp +++ b/stdlib/public/Distributed/DistributedActor.cpp @@ -109,8 +109,7 @@ static void swift_distributed_execute_target_resume( return resumeInParent(parentCtx, error); } -SWIFT_CC(swift) -SWIFT_EXPORT_FROM(swiftDistributed) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL SwiftError* swift_distributed_makeDistributedTargetAccessorNotFoundError( const char *targetNameStart, size_t targetNameLength); diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 47092b332b876..1f632a2fb72e3 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -251,7 +251,8 @@ extension DistributedActorSystem { let subs = try invocationDecoder.decodeGenericSubstitutions() if subs.isEmpty { throw ExecuteDistributedTargetError( - message: "Cannot call generic method without generic argument substitutions") + message: "Cannot call generic method without generic argument substitutions", + errorCode: .missingGenericSubstitutions) } substitutionsBuffer = .allocate(capacity: subs.count) @@ -265,7 +266,8 @@ extension DistributedActorSystem { genericArguments: substitutionsBuffer!) if numWitnessTables < 0 { throw ExecuteDistributedTargetError( - message: "Generic substitutions \(subs) do not satisfy generic requirements of \(target) (\(targetName))") + message: "Generic substitutions \(subs) do not satisfy generic requirements of \(target) (\(targetName))", + errorCode: .invalidGenericSubstitutions) } } @@ -279,7 +281,8 @@ extension DistributedActorSystem { Failed to decode distributed invocation target expected parameter count, error code: \(paramCount) mangled name: \(targetName) - """) + """, + errorCode: .invalidParameterCount) } // Prepare buffer for the parameter types to be decoded into: @@ -304,7 +307,8 @@ extension DistributedActorSystem { Failed to decode the expected number of params of distributed invocation target, error code: \(decodedNum) (decoded: \(decodedNum), expected params: \(paramCount) mangled name: \(targetName) - """) + """, + errorCode: .invalidParameterCount) } // Copy the types from the buffer into a Swift Array @@ -325,12 +329,14 @@ extension DistributedActorSystem { genericEnv: genericEnv, genericArguments: substitutionsBuffer) else { throw ExecuteDistributedTargetError( - message: "Failed to decode distributed target return type") + message: "Failed to decode distributed target return type", + errorCode: .typeDeserializationFailure) } guard let resultBuffer = _openExistential(returnTypeFromTypeInfo, do: allocateReturnTypeBuffer) else { throw ExecuteDistributedTargetError( - message: "Failed to allocate buffer for distributed target return type") + message: "Failed to allocate buffer for distributed target return type", + errorCode: .typeDeserializationFailure) } func destroyReturnTypeBuffer(_: R.Type) { @@ -576,19 +582,38 @@ public protocol DistributedTargetInvocationResultHandler { @available(SwiftStdlib 5.7, *) public protocol DistributedActorSystemError: Error {} +/// Error thrown by ``DistributedActorSystem/executeDistributedTarget(on:target:invocationDecoder:handler:)``. +/// +/// Inspect the ``errorCode`` for details about the underlying reason this error was thrown. @available(SwiftStdlib 5.7, *) public struct ExecuteDistributedTargetError: DistributedActorSystemError { public let errorCode: ErrorCode public let message: String public enum ErrorCode { - /// Thrown when unable to resolve the target identifier to a function accessor. + /// Unable to resolve the target identifier to a function accessor. /// This can happen when the identifier is corrupt, illegal, or wrong in the /// sense that the caller and callee do not have the called function recorded /// using the same identifier. case targetAccessorNotFound - /// A general issue during the execution of the distributed call target ocurred. + /// Call target has different number of parameters than arguments + /// provided by the invocation decoder. + case invalidParameterCount + + /// Target expects generic environment information, but invocation decoder + /// provided no generic substitutions. + case missingGenericSubstitutions + + /// Generic substitutions provided by invocation decoder are incompatible + /// with target of the call. E.g. the generic requirements on the actual + /// target could not be fulfilled by the obtained generic substitutions. + case invalidGenericSubstitutions + + // Failed to deserialize type or obtain type information for call. + case typeDeserializationFailure + + /// A general issue during the execution of the distributed call target occurred. case other } diff --git a/stdlib/public/SwiftShims/_SwiftCxxInteroperability.h b/stdlib/public/SwiftShims/_SwiftCxxInteroperability.h index e731df27c369a..88549f9d4afe6 100644 --- a/stdlib/public/SwiftShims/_SwiftCxxInteroperability.h +++ b/stdlib/public/SwiftShims/_SwiftCxxInteroperability.h @@ -53,6 +53,42 @@ inline void opaqueFree(void *_Nonnull p) noexcept { #endif } +/// Base class for a container for an opaque Swift value, like resilient struct. +class OpaqueStorage { +public: + inline OpaqueStorage() noexcept : storage(nullptr) {} + inline OpaqueStorage(size_t size, size_t alignment) noexcept + : storage(reinterpret_cast(opaqueAlloc(size, alignment))) {} + inline OpaqueStorage(OpaqueStorage &&other) noexcept + : storage(other.storage) { + other.storage = nullptr; + } + inline OpaqueStorage(const OpaqueStorage &) noexcept = delete; + + inline ~OpaqueStorage() noexcept { + if (storage) { + opaqueFree(static_cast(storage)); + } + } + + void operator=(OpaqueStorage &&other) noexcept { + auto temp = storage; + storage = other.storage; + other.storage = temp; + } + void operator=(const OpaqueStorage &) noexcept = delete; + + inline char *_Nonnull getOpaquePointer() noexcept { + return static_cast(storage); + } + inline const char *_Nonnull getOpaquePointer() const noexcept { + return static_cast(storage); + } + +private: + char *_Nullable storage; +}; + /// Base class for a Swift reference counted class value. class RefCountedClass { public: @@ -104,8 +140,6 @@ using UInt = size_t; template static inline const constexpr bool isUsableInGenericContext = false; -#pragma clang diagnostic pop - /// Returns the type metadat for the given Swift type T. template inline void *_Nonnull getTypeMetadata(); @@ -117,8 +151,31 @@ template struct implClassFor { // using type = ...; }; +/// True if the given type is a Swift value type. +template static inline const constexpr bool isValueType = false; + +/// True if the given type is a Swift value type with opaque layout that can be +/// boxed. +template static inline const constexpr bool isOpaqueLayout = false; + +/// Returns the opaque pointer to the given value. +template +inline const void *_Nonnull getOpaquePointer(const T &value) { + if constexpr (isOpaqueLayout) + return reinterpret_cast(value).getOpaquePointer(); + return reinterpret_cast(&value); +} + +template inline void *_Nonnull getOpaquePointer(T &value) { + if constexpr (isOpaqueLayout) + return reinterpret_cast(value).getOpaquePointer(); + return reinterpret_cast(&value); +} + } // namespace _impl +#pragma clang diagnostic pop + } // namespace swift #endif diff --git a/stdlib/public/core/SmallString.swift b/stdlib/public/core/SmallString.swift index dafaef8a93d2e..49680b5163aa6 100644 --- a/stdlib/public/core/SmallString.swift +++ b/stdlib/public/core/SmallString.swift @@ -353,13 +353,22 @@ extension _SmallString { // @_effects(readonly) // @opaque @usableFromInline // testable - internal init(taggedCocoa cocoa: AnyObject) { + internal init?(taggedCocoa cocoa: AnyObject) { self.init() + var success = true self.withMutableCapacity { - let len = _bridgeTagged(cocoa, intoUTF8: $0) - _internalInvariant(len != nil && len! <= _SmallString.capacity, - "Internal invariant violated: large tagged NSStrings") - return len._unsafelyUnwrappedUnchecked + /* + For regular NSTaggedPointerStrings we will always succeed here, but + tagged NSLocalizedStrings may not fit in a SmallString + */ + if let len = _bridgeTagged(cocoa, intoUTF8: $0) { + return len + } + success = false + return 0 + } + if !success { + return nil } self._invariantCheck() } diff --git a/stdlib/public/core/StringBridge.swift b/stdlib/public/core/StringBridge.swift index a62dbeec5365a..e8d24b5115f24 100644 --- a/stdlib/public/core/StringBridge.swift +++ b/stdlib/public/core/StringBridge.swift @@ -335,8 +335,9 @@ internal enum _KnownCocoaString { #if !(arch(i386) || arch(arm) || arch(arm64_32)) // Resiliently write a tagged _CocoaString's contents into a buffer. -// TODO: move this to the Foundation overlay and reimplement it with -// _NSTaggedPointerStringGetBytes +// The Foundation overlay takes care of bridging tagged pointer strings before +// they reach us, but this may still be called by older code, or by strings +// entering our domain via the arguments to -isEqual:, etc... @_effects(releasenone) // @opaque internal func _bridgeTagged( _ cocoa: _CocoaString, @@ -370,8 +371,11 @@ private func _withCocoaASCIIPointer( if requireStableAddress { return nil // tagged pointer strings don't support _fastCStringContents } - let tmp = _StringGuts(_SmallString(taggedCocoa: str)) - return tmp.withFastUTF8 { work($0.baseAddress._unsafelyUnwrappedUnchecked) } + if let smol = _SmallString(taggedCocoa: str) { + return _StringGuts(smol).withFastUTF8 { + work($0.baseAddress._unsafelyUnwrappedUnchecked) + } + } } #endif defer { _fixLifetime(str) } @@ -503,7 +507,11 @@ internal func _bridgeCocoaString(_ cocoaString: _CocoaString) -> _StringGuts { cocoaString, to: __SharedStringStorage.self).asString._guts #if !(arch(i386) || arch(arm) || arch(arm64_32)) case .tagged: - return _StringGuts(_SmallString(taggedCocoa: cocoaString)) + // Foundation should be taking care of tagged pointer strings before they + // reach here, so the only ones reaching this point should be back deployed, + // which will never have tagged pointer strings that aren't small, hence + // the force unwrap here. + return _StringGuts(_SmallString(taggedCocoa: cocoaString)!) #if arch(arm64) case .constantTagged: let taggedContents = getConstantTaggedCocoaContents(cocoaString)! @@ -530,7 +538,11 @@ internal func _bridgeCocoaString(_ cocoaString: _CocoaString) -> _StringGuts { #if !(arch(i386) || arch(arm) || arch(arm64_32)) if _isObjCTaggedPointer(immutableCopy) { - return _StringGuts(_SmallString(taggedCocoa: immutableCopy)) + // Copying a tagged pointer can produce a tagged pointer, but only if it's + // small enough to definitely fit in a _SmallString + return _StringGuts( + _SmallString(taggedCocoa: immutableCopy).unsafelyUnwrapped + ) } #endif diff --git a/stdlib/toolchain/CMakeLists.txt b/stdlib/toolchain/CMakeLists.txt index 9016c376b07de..20a75bddaedaa 100644 --- a/stdlib/toolchain/CMakeLists.txt +++ b/stdlib/toolchain/CMakeLists.txt @@ -50,7 +50,6 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT) add_subdirectory(legacy_layouts) add_subdirectory(Compatibility50) add_subdirectory(Compatibility51) - add_subdirectory(Compatibility56) add_subdirectory(CompatibilityDynamicReplacements) add_subdirectory(CompatibilityConcurrency) endif() diff --git a/stdlib/toolchain/Compatibility56/CMakeLists.txt b/stdlib/toolchain/Compatibility56/CMakeLists.txt deleted file mode 100644 index dc5b736927c48..0000000000000 --- a/stdlib/toolchain/Compatibility56/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -set(library_name "swiftCompatibility56") - -include_directories("include/" "${SWIFT_STDLIB_SOURCE_DIR}") - -add_swift_target_library("${library_name}" STATIC - Overrides.cpp - Concurrency/Task.cpp - Concurrency/Error.cpp - Concurrency/Actor.cpp - Concurrency/AsyncLet.cpp - - TARGET_SDKS ${SWIFT_DARWIN_PLATFORMS} - - C_COMPILE_FLAGS ${CXX_COMPILE_FLAGS} - LINK_FLAGS ${CXX_LINK_FLAGS} - INCORPORATE_OBJECT_LIBRARIES swiftThreading - SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} - DEPLOYMENT_VERSION_OSX ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_OSX} - DEPLOYMENT_VERSION_IOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_IOS} - DEPLOYMENT_VERSION_TVOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_TVOS} - DEPLOYMENT_VERSION_WATCHOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_WATCHOS} - - INSTALL_IN_COMPONENT compiler - INSTALL_WITH_SHARED) - - -# FIXME: We need a more flexible mechanism to add lipo targets generated by -# add_swift_target_library to the ALL target. Until then this hack is necessary -# to ensure these libraries build. -foreach(sdk ${SWIFT_SDKS}) - set(target_name "${library_name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}") - if(NOT TARGET "${target_name}") - continue() - endif() - - set_target_properties("${target_name}" - PROPERTIES - EXCLUDE_FROM_ALL FALSE) -endforeach() diff --git a/stdlib/toolchain/Compatibility56/CompatibilityOverride.h b/stdlib/toolchain/Compatibility56/CompatibilityOverride.h deleted file mode 100644 index 842447fd0bbe4..0000000000000 --- a/stdlib/toolchain/Compatibility56/CompatibilityOverride.h +++ /dev/null @@ -1,137 +0,0 @@ -//===--- CompatibiltyOverride.h - Back-deploying compatibility fixes --*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2018 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Support back-deploying compatibility fixes for newer apps running on older runtimes. -// -//===----------------------------------------------------------------------===// - -#ifndef COMPATIBILITY_OVERRIDE_H -#define COMPATIBILITY_OVERRIDE_H - -#include "public/runtime/Private.h" - -#include "Runtime/Concurrency.h" -#include "swift/Runtime/Metadata.h" -#include "swift/Runtime/Once.h" -#include - -namespace swift { - -// Macro utilities. -#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__ -#define COMPATIBILITY_CONCAT2(x, y) x##y -#define COMPATIBILITY_CONCAT(x, y) COMPATIBILITY_CONCAT2(x, y) - -// This ridiculous construct will remove the parentheses from the argument and -// add a trailing comma, or will produce nothing when passed no argument. For -// example: -// COMPATIBILITY_UNPAREN_WITH_COMMA((1, 2, 3)) -> 1, 2, 3, -// COMPATIBILITY_UNPAREN_WITH_COMMA((4)) -> 4, -// COMPATIBILITY_UNPAREN_WITH_COMMA() -> -#define COMPATIBILITY_UNPAREN_WITH_COMMA(x) \ - COMPATIBILITY_CONCAT(COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_, \ - COMPATIBILITY_UNPAREN_WITH_COMMA2 x) -#define COMPATIBILITY_UNPAREN_WITH_COMMA2(...) PARAMS(__VA_ARGS__) -#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_PARAMS(...) __VA_ARGS__, -#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_COMPATIBILITY_UNPAREN_WITH_COMMA2 - -// This ridiculous construct will preserve the parentheses around the argument, -// or will produce an empty pair of parentheses when passed no argument. For -// example: -// COMPATIBILITY_PAREN((1, 2, 3)) -> (1, 2, 3) -// COMPATIBILITY_PAREN((4)) -> (4) -// COMPATIBILITY_PAREN() -> () -#define COMPATIBILITY_PAREN(x) \ - COMPATIBILITY_CONCAT(COMPATIBILITY_PAREN_, COMPATIBILITY_PAREN2 x) -#define COMPATIBILITY_PAREN2(...) PARAMS(__VA_ARGS__) -#define COMPATIBILITY_PAREN_PARAMS(...) (__VA_ARGS__) -#define COMPATIBILITY_PAREN_COMPATIBILITY_PAREN2 () - -// Include path computation. Code that includes this file can write -// `#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH` to include the appropriate -// .def file for the current library. -#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swiftRuntime \ - "CompatibilityOverrideRuntime.def" -#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swift_Concurrency \ - "CompatibilityOverrideConcurrency.def" - -#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH \ - COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_INCLUDE_PATH_, \ - SWIFT_TARGET_LIBRARY_NAME) - -// Compatibility overrides are only supported on Darwin. -#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES -#if !(defined(__APPLE__) && defined(__MACH__)) -#define SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES -#endif -#endif - -#ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES - -# error Back-deployment library must always be built with compatibilty overrides - -#else // #ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES - -// Override section name computation. `COMPATIBILITY_OVERRIDE_SECTION_NAME` will -// resolve to string literal containing the appropriate section name for the -// current library. -#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swift_Concurrency "__s_async_hook" - -#define COMPATIBILITY_OVERRIDE_SECTION_NAME \ - COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_SECTION_NAME_, \ - SWIFT_TARGET_LIBRARY_NAME) - -// Create typedefs for function pointers to call the original implementation. -#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ - ccAttrs typedef ret(*Original_##name) COMPATIBILITY_PAREN(typedArgs); -#include "CompatibilityOverrideRuntime.def" -#include "CompatibilityOverrideConcurrency.def" -#undef OVERRIDE - - -// Create typedefs for override function pointers. -#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ - ccAttrs typedef ret (*Override_##name)(COMPATIBILITY_UNPAREN_WITH_COMMA( \ - typedArgs) Original_##name originalImpl); -#include "CompatibilityOverrideRuntime.def" -#include "CompatibilityOverrideConcurrency.def" -#undef OVERRIDE - -// Create declarations for getOverride functions. -#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ - Override_ ## name getOverride_ ## name(); -#include "CompatibilityOverrideRuntime.def" -#include "CompatibilityOverrideConcurrency.def" -#undef OVERRIDE - -/// Used to define an override point. The override point #defines the appropriate -/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes -/// the file to generate the override points. The original implementation of the -/// functionality must be available as swift_funcNameHereImpl. -#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \ - typedArgs, namedArgs) \ - attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \ - static Override_##name Override; \ - static swift_once_t Predicate; \ - swift_once( \ - &Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \ - if (Override != nullptr) \ - return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \ - swift_##name##Impl); \ - return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \ - } - -#endif // #else SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES - -} /* end namespace swift */ - -#endif /* COMPATIBILITY_OVERRIDE_H */ diff --git a/stdlib/toolchain/Compatibility56/CompatibilityOverrideConcurrency.def b/stdlib/toolchain/Compatibility56/CompatibilityOverrideConcurrency.def deleted file mode 100644 index deedd1177a257..0000000000000 --- a/stdlib/toolchain/Compatibility56/CompatibilityOverrideConcurrency.def +++ /dev/null @@ -1,356 +0,0 @@ -//===--- CompatibilityOverridesConcurrency.def - Overrides Info -*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2018 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// This file defines x-macros used for metaprogramming with the set of -// compatibility override functions. -// -//===----------------------------------------------------------------------===// - -/// #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) -/// Provides information about an overridable function. -/// - name is the name of the function, without any leading swift_ or -/// namespace. -/// - ret is the return type of the function. -/// - attrs is the attributes, if any, applied to the function definition. -/// - ccAttrs is the calling convention attributes, if any, applied to the -/// function definition and corresponding typedefs -/// - namespace is the namespace, if any, the function is in, including a -/// trailing :: -/// - typedArgs is the argument list, including types, surrounded by -/// parentheses -/// - namedArgs is the list of argument names, with no types, surrounded by -/// parentheses -/// -/// The entries are organized by group. A user may define OVERRIDE to get all -/// entries, or define one or more of the more specific OVERRIDE_* variants to -/// get only those entries. - -// NOTE: this file is used to build the definition of OverrideSection in -// CompatibilityOverride.cpp, which is part of the ABI. Moving or removing -// entries in this file will break the ABI. Additional entries can be added to -// the end. ABI breaks or version-specific changes can be accommodated by -// changing the name of the override section in that file. - -#ifdef OVERRIDE -# define OVERRIDE_ACTOR OVERRIDE -# define OVERRIDE_TASK OVERRIDE -# define OVERRIDE_ASYNC_LET OVERRIDE -# define OVERRIDE_TASK_GROUP OVERRIDE -# define OVERRIDE_TASK_LOCAL OVERRIDE -# define OVERRIDE_TASK_STATUS OVERRIDE -#else -# ifndef OVERRIDE_ACTOR -# define OVERRIDE_ACTOR(...) -# endif -# ifndef OVERRIDE_TASK -# define OVERRIDE_TASK(...) -# endif -# ifndef OVERRIDE_ASYNC_LET -# define OVERRIDE_ASYNC_LET(...) -# endif -# ifndef OVERRIDE_TASK_GROUP -# define OVERRIDE_TASK_GROUP(...) -# endif -# ifndef OVERRIDE_TASK_LOCAL -# define OVERRIDE_TASK_LOCAL(...) -# endif -# ifndef OVERRIDE_TASK_STATUS -# define OVERRIDE_TASK_STATUS(...) -# endif -#endif - -OVERRIDE_ACTOR(task_enqueue, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (class Job *job, ExecutorRef executor), - (job, executor)) - -OVERRIDE_ACTOR(job_run, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (class Job *job, ExecutorRef executor), - (job, executor)) - -OVERRIDE_ACTOR(task_getCurrentExecutor, ExecutorRef, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, ,) - -OVERRIDE_ACTOR(task_isCurrentExecutor, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (ExecutorRef executor), (executor)) - -OVERRIDE_ACTOR(task_switch, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, (SWIFT_ASYNC_CONTEXT AsyncContext *resumeToContext, - TaskContinuationFunction *resumeFunction, ExecutorRef newExecutor), - (resumeToContext, resumeFunction, newExecutor)) - -OVERRIDE_TASK(task_create_common, AsyncTaskAndContext, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (size_t taskCreateFlags, - TaskOptionRecord *options, - const Metadata *futureResultType, - FutureAsyncSignature::FunctionType *function, - void *closureContext, - size_t initialContextSize), - (taskCreateFlags, options, futureResultType, function, - closureContext, initialContextSize)) - -OVERRIDE_TASK(task_future_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency), - SWIFT_CC(swiftasync), swift::, - (OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, AsyncTask *task, - TaskContinuationFunction *resumeFunction, - AsyncContext *callContext), - (result, callerContext, task, resumeFunction, callContext)) - -OVERRIDE_TASK(task_future_wait_throwing, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, AsyncTask *task, - ThrowingTaskFutureWaitContinuationFunction *resumeFunction, - AsyncContext *callContext), - (result, callerContext, task, resumeFunction, callContext)) - -OVERRIDE_TASK(continuation_resume, void, SWIFT_EXPORT_FROM(swift_Concurrency), - SWIFT_CC(swift), swift::, - (AsyncTask *continuation), - (continuation)) - -OVERRIDE_TASK(continuation_throwingResume, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (AsyncTask *continuation), - (continuation)) - -OVERRIDE_TASK(continuation_throwingResumeWithError, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (AsyncTask *continuation, SwiftError *error), - (continuation, error)) - -OVERRIDE_TASK(task_addCancellationHandler, - CancellationNotificationStatusRecord *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (CancellationNotificationStatusRecord::FunctionType handler, - void *context), - (handler, context)) - -OVERRIDE_TASK(task_removeCancellationHandler, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (CancellationNotificationStatusRecord *record), (record)) - -OVERRIDE_TASK(task_createNullaryContinuationJob, NullaryContinuationJob *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (size_t priority, - AsyncTask *continuation), (priority, continuation)) - -OVERRIDE_TASK(task_asyncMainDrainQueue, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - , ) - -OVERRIDE_TASK(task_suspend, AsyncTask *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, ,) - -OVERRIDE_TASK(continuation_init, AsyncTask *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (ContinuationAsyncContext *context, - AsyncContinuationFlags flags), - (context, flags)) - -OVERRIDE_TASK(continuation_await, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, (ContinuationAsyncContext *context), - (context)) - -OVERRIDE_ASYNC_LET(asyncLet_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency), - SWIFT_CC(swiftasync), swift::, - (OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, TaskContinuationFunction *resumeFn, - AsyncContext *callContext), - (result, callerContext, alet, resumeFn, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_wait_throwing, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, - ThrowingTaskFutureWaitContinuationFunction *resume, - AsyncContext *callContext), - (result, callerContext, alet, resume, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_end, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (AsyncLet *alet), (alet)) - -OVERRIDE_ASYNC_LET(asyncLet_get, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, void *resultBuffer, - TaskContinuationFunction *resumeFn, - AsyncContext *callContext), - (callerContext, alet, resultBuffer, resumeFn, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_get_throwing, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, void *resultBuffer, - ThrowingTaskFutureWaitContinuationFunction *resumeFn, - AsyncContext *callContext), - (callerContext, alet, resultBuffer, resumeFn, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_consume, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, void *resultBuffer, - TaskContinuationFunction *resumeFn, - AsyncContext *callContext), - (callerContext, alet, resultBuffer, resumeFn, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_consume_throwing, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, void *resultBuffer, - ThrowingTaskFutureWaitContinuationFunction *resumeFn, - AsyncContext *callContext), - (callerContext, alet, resultBuffer, resumeFn, callContext)) - -OVERRIDE_ASYNC_LET(asyncLet_finish, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncLet *alet, void *resultBuffer, - TaskContinuationFunction *resumeFn, - AsyncContext *callContext), - (callerContext, alet, resultBuffer, resumeFn, callContext)) - -OVERRIDE_TASK_GROUP(taskGroup_initialize, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group, const Metadata *T), (group, T)) - -OVERRIDE_TASK_STATUS(taskGroup_attachChild, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group, AsyncTask *child), - (group, child)) - -OVERRIDE_TASK_GROUP(taskGroup_destroy, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group), (group)) - -OVERRIDE_TASK_GROUP(taskGroup_wait_next_throwing, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync), - swift::, - (OpaqueValue *resultPointer, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - TaskGroup *_group, - ThrowingTaskFutureWaitContinuationFunction *resumeFn, - AsyncContext *callContext), - (resultPointer, callerContext, _group, resumeFn, - callContext)) - -OVERRIDE_TASK_GROUP(taskGroup_isEmpty, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group), (group)) - -OVERRIDE_TASK_GROUP(taskGroup_isCancelled, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group), (group)) - -OVERRIDE_TASK_GROUP(taskGroup_cancelAll, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group), (group)) - -OVERRIDE_TASK_GROUP(taskGroup_addPending, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group, bool unconditionally), - (group, unconditionally)) - - -OVERRIDE_TASK_LOCAL(task_reportIllegalTaskLocalBindingWithinWithTaskGroup, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, - (const unsigned char *file, uintptr_t fileLength, - bool fileIsASCII, uintptr_t line), - (file, fileLength, fileIsASCII, line)) - -OVERRIDE_TASK_LOCAL(task_localValuePush, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, - (const HeapObject *key, OpaqueValue *value, - const Metadata *valueType), - (key, value, valueType)) - -OVERRIDE_TASK_LOCAL(task_localValueGet, OpaqueValue *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, - (const HeapObject *key), - (key)) - -OVERRIDE_TASK_LOCAL(task_localValuePop, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, ,) - -OVERRIDE_TASK_LOCAL(task_localsCopyTo, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, - (AsyncTask *target), - (target)) - -OVERRIDE_TASK_STATUS(task_addStatusRecord, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskStatusRecord *newRecord), (newRecord)) - -OVERRIDE_TASK_STATUS(task_tryAddStatusRecord, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskStatusRecord *newRecord), (newRecord)) - -OVERRIDE_TASK_STATUS(task_removeStatusRecord, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskStatusRecord *record), (record)) - -OVERRIDE_TASK_STATUS(task_hasTaskGroupStatusRecord, bool, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, , ) - -OVERRIDE_TASK_STATUS(task_attachChild, ChildTaskStatusRecord *, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (AsyncTask *child), (child)) - -OVERRIDE_TASK_STATUS(task_detachChild, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (ChildTaskStatusRecord *record), (record)) - -OVERRIDE_TASK_STATUS(task_cancel, void, SWIFT_EXPORT_FROM(swift_Concurrency), - SWIFT_CC(swift), swift::, (AsyncTask *task), (task)) - -OVERRIDE_TASK_STATUS(task_cancel_group_child_tasks, void, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (TaskGroup *group), (group)) - -OVERRIDE_TASK_STATUS(task_escalate, JobPriority, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (AsyncTask *task, JobPriority newPriority), - (task, newPriority)) - -OVERRIDE_TASK_STATUS(task_getNearestDeadline, NearestTaskDeadline, - SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), - swift::, (AsyncTask *task), (task)) - -#undef OVERRIDE_ACTOR -#undef OVERRIDE_TASK -#undef OVERRIDE_ASYNC_LET -#undef OVERRIDE_TASK_GROUP -#undef OVERRIDE_TASK_LOCAL -#undef OVERRIDE_TASK_STATUS diff --git a/stdlib/toolchain/Compatibility56/CompatibilityOverrideRuntime.def b/stdlib/toolchain/Compatibility56/CompatibilityOverrideRuntime.def deleted file mode 100644 index 65ba46990b0f8..0000000000000 --- a/stdlib/toolchain/Compatibility56/CompatibilityOverrideRuntime.def +++ /dev/null @@ -1,227 +0,0 @@ -//===--- CompatibilityOverridesRuntime.def - Overrides Database -*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2018 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// This file defines x-macros used for metaprogramming with the set of -// compatibility override functions. -// -//===----------------------------------------------------------------------===// - -/// #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) -/// Provides information about an overridable function. -/// - name is the name of the function, without any leading swift_ or -/// namespace. -/// - ret is the return type of the function. -/// - attrs is the attributes, if any, applied to the function definition. -/// - ccAttrs is the calling convention attributes, if any, applied to the -/// function definition and corresponding typedefs -/// - namespace is the namespace, if any, the function is in, including a -/// trailing :: -/// - typedArgs is the argument list, including types, surrounded by -/// parentheses -/// - namedArgs is the list of argument names, with no types, surrounded by -/// parentheses -/// -/// The entries are organized by group. A user may define OVERRIDE to get all -/// entries, or define one or more of OVERRIDE_METADATALOOKUP, OVERRIDE_CASTING, -/// OVERRIDE_OBJC, OVERRIDE_FOREIGN, OVERRIDE_PROTOCOLCONFORMANCE, -/// and OVERRIDE_KEYPATH to get only those entries. - -// NOTE: this file is used to build the definition of OverrideSection in -// CompatibilityOverride.cpp, which is part of the ABI. Moving or removing -// entries in this file will break the ABI. Additional entries can be added to -// the end. ABI breaks or version-specific changes can be accommodated by -// changing the name of the override section in that file. - -#ifdef OVERRIDE -# define OVERRIDE_METADATALOOKUP OVERRIDE -# define OVERRIDE_CASTING OVERRIDE -# define OVERRIDE_DYNAMICCASTING OVERRIDE -# define OVERRIDE_OBJC OVERRIDE -# define OVERRIDE_FOREIGN OVERRIDE -# define OVERRIDE_PROTOCOLCONFORMANCE OVERRIDE -# define OVERRIDE_KEYPATH OVERRIDE -# define OVERRIDE_WITNESSTABLE OVERRIDE -#else -# ifndef OVERRIDE_METADATALOOKUP -# define OVERRIDE_METADATALOOKUP(...) -# endif -# ifndef OVERRIDE_CASTING -# define OVERRIDE_CASTING(...) -# endif -# ifndef OVERRIDE_DYNAMICCASTING -# define OVERRIDE_DYNAMICCASTING(...) -# endif -# ifndef OVERRIDE_OBJC -# define OVERRIDE_OBJC(...) -# endif -# ifndef OVERRIDE_FOREIGN -# define OVERRIDE_FOREIGN(...) -# endif -# ifndef OVERRIDE_PROTOCOLCONFORMANCE -# define OVERRIDE_PROTOCOLCONFORMANCE(...) -# endif -# ifndef OVERRIDE_KEYPATH -# define OVERRIDE_KEYPATH(...) -# endif -# ifndef OVERRIDE_WITNESSTABLE -# define OVERRIDE_WITNESSTABLE(...) -# endif -#endif - -OVERRIDE_DYNAMICCASTING(dynamicCast, bool, , , swift::, - (OpaqueValue *dest, OpaqueValue *src, - const Metadata *srcType, - const Metadata *targetType, - DynamicCastFlags flags), - (dest, src, srcType, targetType, flags)) - - -OVERRIDE_CASTING(dynamicCastClass, const void *, , , swift::, - (const void *object, - const ClassMetadata *targetType), - (object, targetType)) - - -OVERRIDE_CASTING(dynamicCastClassUnconditional, const void *, , , swift::, - (const void *object, - const ClassMetadata *targetType, - const char *file, unsigned line, unsigned column), - (object, targetType, file, line, column)) - - - -OVERRIDE_CASTING(dynamicCastUnknownClass, const void *, , , swift::, - (const void *object, const Metadata *targetType), - (object, targetType)) - - -OVERRIDE_CASTING(dynamicCastUnknownClassUnconditional, const void *, , , swift::, - (const void *object, const Metadata *targetType, - const char *file, unsigned line, unsigned column), - (object, targetType, file, line, column)) - - -OVERRIDE_CASTING(dynamicCastMetatype, const Metadata *, , , swift::, - (const Metadata *sourceType, - const Metadata *targetType), - (sourceType, targetType)) - - -OVERRIDE_CASTING(dynamicCastMetatypeUnconditional, const Metadata *, , , swift::, - (const Metadata *sourceType, - const Metadata *targetType, - const char *file, unsigned line, unsigned column), - (sourceType, targetType, file, line, column)) - - -OVERRIDE_FOREIGN(dynamicCastForeignClassMetatype, const ClassMetadata *, , , swift::, - (const ClassMetadata *sourceType, - const ClassMetadata *targetType), - (sourceType, targetType)) - - -OVERRIDE_FOREIGN(dynamicCastForeignClassMetatypeUnconditional, - const ClassMetadata *, , , swift::, - (const ClassMetadata *sourceType, - const ClassMetadata *targetType, - const char *file, unsigned line, unsigned column), - (sourceType, targetType, file, line, column)) - - -OVERRIDE_PROTOCOLCONFORMANCE(conformsToProtocol, const WitnessTable *, , , swift::, - (const Metadata * const type, - const ProtocolDescriptor *protocol), - (type, protocol)) - -OVERRIDE_KEYPATH(getKeyPath, const HeapObject *, , , swift::, - (const void *pattern, const void *arguments), - (pattern, arguments)) - -OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeLookupErrorOr, , SWIFT_CC(swift), swift::, - (MetadataRequest request, - Demangler &demangler, - Demangle::NodePointer node, - const void * const *arguments, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable), - (request, demangler, node, arguments, substGenericParam, substWitnessTable)) -OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeLookupErrorOr, , SWIFT_CC(swift), swift::, - (MetadataRequest request, - StringRef typeName, - const void * const *arguments, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable), - (request, typeName, arguments, substGenericParam, substWitnessTable)) - -OVERRIDE_WITNESSTABLE(getAssociatedTypeWitnessSlow, MetadataResponse, - SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, - (MetadataRequest request, WitnessTable *wtable, - const Metadata *conformingType, - const ProtocolRequirement *reqBase, - const ProtocolRequirement *assocType), - (request, wtable, conformingType, reqBase, assocType)) - -OVERRIDE_WITNESSTABLE(getAssociatedConformanceWitnessSlow, const WitnessTable *, - SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, - (WitnessTable *wtable, const Metadata *conformingType, - const Metadata *assocType, - const ProtocolRequirement *reqBase, - const ProtocolRequirement *assocConformance), - (wtable, conformingType, assocType, reqBase, - assocConformance)) -#if SWIFT_OBJC_INTEROP - -OVERRIDE_OBJC(dynamicCastObjCClass, const void *, , , swift::, - (const void *object, - const ClassMetadata *targetType), - (object, targetType)) - - -OVERRIDE_OBJC(dynamicCastObjCClassUnconditional, const void *, , , swift::, - (const void *object, - const ClassMetadata *targetType, - const char *file, unsigned line, unsigned column), - (object, targetType, file, line, column)) - -OVERRIDE_OBJC(dynamicCastObjCClassMetatype, const ClassMetadata *, , , swift::, - (const ClassMetadata *sourceType, - const ClassMetadata *targetType), - (sourceType, targetType)) - - -OVERRIDE_OBJC(dynamicCastObjCClassMetatypeUnconditional, const ClassMetadata *, , , swift::, - (const ClassMetadata *sourceType, const ClassMetadata *targetType, - const char *file, unsigned line, unsigned column), - (sourceType, targetType, file, line, column)) - - -OVERRIDE_FOREIGN(dynamicCastForeignClass, const void *, , , swift::, - (const void *object, - const ForeignClassMetadata *targetType), - (object, targetType)) - - -OVERRIDE_FOREIGN(dynamicCastForeignClassUnconditional, const void *, , , swift::, - (const void *object, const ForeignClassMetadata *targetType, - const char *file, unsigned line, unsigned column), - (object, targetType, file, line, column)) - -#endif - -#undef OVERRIDE_METADATALOOKUP -#undef OVERRIDE_CASTING -#undef OVERRIDE_DYNAMICCASTING -#undef OVERRIDE_OBJC -#undef OVERRIDE_FOREIGN -#undef OVERRIDE_PROTOCOLCONFORMANCE -#undef OVERRIDE_KEYPATH -#undef OVERRIDE_WITNESSTABLE diff --git a/stdlib/toolchain/Compatibility56/Concurrency/Actor.cpp b/stdlib/toolchain/Compatibility56/Concurrency/Actor.cpp deleted file mode 100644 index 58922a8edd00b..0000000000000 --- a/stdlib/toolchain/Compatibility56/Concurrency/Actor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "Runtime/Concurrency.h" -#include "Concurrency/Actor.h" -#include "Concurrency/Task.h" - -#include "swift/Runtime/Atomic.h" -#include "swift/Runtime/Casting.h" -#include "Runtime/Threading/Mutex.h" -#include "Runtime/Threading/Once.h" -#include "Runtime/Threading/ThreadLocal.h" -#include "Runtime/Threading/ThreadLocalStorage.h" - -#include -#include - -using namespace swift; - -namespace { - -/// An extremely silly class which exists to make pointer -/// default-initialization constexpr. -template struct Pointer { - T *Value; - constexpr Pointer() : Value(nullptr) {} - constexpr Pointer(T *value) : Value(value) {} - operator T *() const { return Value; } - T *operator->() const { return Value; } -}; - - -class ActiveTask { - /// A thread-local variable pointing to the active tracking - /// information about the current thread, if any. - static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer, Value, - SWIFT_CONCURRENCY_TASK_KEY); - -public: - static void set(AsyncTask *task) { Value.set(task); } - static AsyncTask *get() { return Value.get(); } -}; - -/// Define the thread-locals. -SWIFT_RUNTIME_DECLARE_THREAD_LOCAL( - Pointer, - ActiveTask::Value, - SWIFT_CONCURRENCY_TASK_KEY); - - -} // namespace diff --git a/stdlib/toolchain/Compatibility56/Concurrency/AsyncLet.cpp b/stdlib/toolchain/Compatibility56/Concurrency/AsyncLet.cpp deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/stdlib/toolchain/Compatibility56/Concurrency/Error.cpp b/stdlib/toolchain/Compatibility56/Concurrency/Error.cpp deleted file mode 100644 index 78d0331550c01..0000000000000 --- a/stdlib/toolchain/Compatibility56/Concurrency/Error.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===--- Error.cpp - Error handling support code --------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "Concurrency/Error.h" - -// swift::fatalError is not exported from libswiftCore and not shared, so define another -// internal function instead. -SWIFT_NORETURN void swift::swift_Concurrency_fatalError(uint32_t flags, const char *format, ...) { - abort(); -} diff --git a/stdlib/toolchain/Compatibility56/Concurrency/Task.cpp b/stdlib/toolchain/Compatibility56/Concurrency/Task.cpp deleted file mode 100644 index c5d5edea3a559..0000000000000 --- a/stdlib/toolchain/Compatibility56/Concurrency/Task.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "Concurrency/Task.h" - -#include "Concurrency/TaskPrivate.h" -#include "Concurrency/Error.h" -#include "Overrides.h" - -using namespace swift; -using FutureFragment = AsyncTask::FutureFragment; -using TaskGroup = swift::TaskGroup; - -//===--- swift_task_future_wait -------------------------------------------===// - -void SWIFT_CC(swiftasync) swift::swift56override_swift_task_future_wait( - OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncTask *task, - TaskContinuationFunction *resumeFn, - AsyncContext *callContext, - TaskFutureWait_t *original) { - original(result, callerContext, task, resumeFn, callContext); -} - -//===--- swift_task_future_wait_throwing ----------------------------------===// - -void SWIFT_CC(swiftasync) swift::swift56override_swift_task_future_wait_throwing( - OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncTask *task, - ThrowingTaskFutureWaitContinuationFunction *resumeFunction, - AsyncContext *callContext, - TaskFutureWaitThrowing_t *original) { - original(result, callerContext, task, resumeFunction, callContext); -} diff --git a/stdlib/toolchain/Compatibility56/Overrides.cpp b/stdlib/toolchain/Compatibility56/Overrides.cpp deleted file mode 100644 index 440b499dccd03..0000000000000 --- a/stdlib/toolchain/Compatibility56/Overrides.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===--- Overrides.cpp - Compat override table for Swift 5.6 runtime ------===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// This file provides compatibility override hooks for Swift 5.6 runtimes. -// -//===----------------------------------------------------------------------===// - -#include "Overrides.h" - -#include -#include -#include - -using namespace swift; - -#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ - Override_ ## name name; - -struct RuntimeOverrideSection { - uintptr_t version; -#include "CompatibilityOverrideRuntime.def" -}; - -struct ConcurrencyOverrideSection { - uintptr_t version; -#include "CompatibilityOverrideConcurrency.def" -}; - -#undef OVERRIDE - -ConcurrencyOverrideSection Swift56ConcurrencyOverrides -__attribute__((used, section("__DATA,__s_async_hook"))) = { - .version = 0, - .task_future_wait = swift56override_swift_task_future_wait, - .task_future_wait_throwing = swift56override_swift_task_future_wait_throwing, -}; - -RuntimeOverrideSection Swift56RuntimeOverrides -__attribute__((used, section("__DATA,__swift56_hooks"))) = { - .version = 0, -}; - -// Allow this library to get force-loaded by autolinking -__attribute__((weak, visibility("hidden"))) -extern "C" -char _swift_FORCE_LOAD_$_swiftCompatibility56 = 0; diff --git a/stdlib/toolchain/Compatibility56/Overrides.h b/stdlib/toolchain/Compatibility56/Overrides.h deleted file mode 100644 index e722cb2c22974..0000000000000 --- a/stdlib/toolchain/Compatibility56/Overrides.h +++ /dev/null @@ -1,61 +0,0 @@ -//===--- Overrides.h - Compat overrides for Swift 5.6 runtime ------s------===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// This file provides compatibility override hooks for Swift 5.6 runtimes. -// -//===----------------------------------------------------------------------===// - -#include "swift/Runtime/Metadata.h" -#include "llvm/ADT/StringRef.h" -#include "CompatibilityOverride.h" - -namespace swift { -struct OpaqueValue; -class AsyncContext; -class AsyncTask; - -using TaskFutureWait_t = SWIFT_CC(swiftasync) void( - OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncTask *task, - TaskContinuationFunction *resumeFn, - AsyncContext *callContext); - -using TaskFutureWaitThrowing_t = SWIFT_CC(swiftasync) void( - OpaqueValue *result, - SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, - AsyncTask *task, - ThrowingTaskFutureWaitContinuationFunction *resumeFn, - AsyncContext *callContext); - -void SWIFT_CC(swiftasync) swift56override_swift_task_future_wait( - OpaqueValue *, - SWIFT_ASYNC_CONTEXT AsyncContext *, - AsyncTask *, - TaskContinuationFunction *, - AsyncContext *, - TaskFutureWait_t *original); - -void SWIFT_CC(swiftasync) swift56override_swift_task_future_wait_throwing( - OpaqueValue *, - SWIFT_ASYNC_CONTEXT AsyncContext *, - AsyncTask *, - ThrowingTaskFutureWaitContinuationFunction *, - AsyncContext *, - TaskFutureWaitThrowing_t *original); - - -using AsyncMainDrainQueue_t = SWIFT_CC(swift) void(); - -void SWIFT_CC(swift) swift56override_swift_asyncMainDrainQueue(AsyncMainDrainQueue_t *); - -} // namespace swift diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/Actor.h b/stdlib/toolchain/Compatibility56/include/Concurrency/Actor.h deleted file mode 100644 index 31867e3f9f920..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/Actor.h +++ /dev/null @@ -1,45 +0,0 @@ -//===--- Actor.h - ABI structures for actors --------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift ABI describing actors. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_ABI_ACTOR_BACKDEPLOY56_H -#define SWIFT_ABI_ACTOR_BACKDEPLOY56_H - -#include "swift/ABI/HeapObject.h" -#include "swift/ABI/MetadataValues.h" - -namespace swift { - -/// The default actor implementation. This is the layout of both -/// the DefaultActor and NSDefaultActor classes. -class alignas(Alignment_DefaultActor) DefaultActor : public HeapObject { -public: - // These constructors do not initialize the actor instance, and the - // destructor does not destroy the actor instance; you must call - // swift_defaultActor_{initialize,destroy} yourself. - constexpr DefaultActor(const HeapMetadata *metadata) - : HeapObject(metadata), PrivateData{} {} - - constexpr DefaultActor(const HeapMetadata *metadata, - InlineRefCounts::Immortal_t immortal) - : HeapObject(metadata, immortal), PrivateData{} {} - - void *PrivateData[NumWords_DefaultActor]; -}; - -} // end namespace swift - -#endif // SWIFT_ABI_ACTOR_BACKDEPLOY56_H - diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/AsyncLet.h b/stdlib/toolchain/Compatibility56/include/Concurrency/AsyncLet.h deleted file mode 100644 index 8415f1260dbc6..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/AsyncLet.h +++ /dev/null @@ -1,65 +0,0 @@ -//===--- AsyncLet.h - ABI structures for async let -00-----------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift ABI describing task groups. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H -#define SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H - -#include "Task.h" -#include "swift/ABI/HeapObject.h" -#include "swift/Runtime/Config.h" -#include "swift/Basic/RelativePointer.h" -#include "swift/Basic/STLExtras.h" - -namespace swift { - -/// Represents an in-flight `async let`, i.e. the Task that is computing the -/// result of the async let, along with the awaited status and other metadata. -class alignas(Alignment_AsyncLet) AsyncLet { -public: - // These constructors do not initialize the AsyncLet instance, and the - // destructor does not destroy the AsyncLet instance; you must call - // swift_asyncLet_{start,end} yourself. - constexpr AsyncLet() - : PrivateData{} {} - - void *PrivateData[NumWords_AsyncLet]; - - // TODO: we could offer a "was awaited on" check here - - /// Returns the child task that is associated with this async let. - /// The tasks completion is used to fulfil the value represented by this async let. - AsyncTask *getTask() const; - - // The compiler preallocates a large fixed space for the `async let`, with the - // intent that most of it be used for the child task context. The next two - // methods return the address and size of that space. - - /// Return a pointer to the unused space within the async let block. - void *getPreallocatedSpace(); - - /// Return the size of the unused space within the async let block. - static size_t getSizeOfPreallocatedSpace(); - - /// Was the task allocated out of the parent's allocator? - bool didAllocateFromParentTask(); - - /// Flag that the task was allocated from the parent's allocator. - void setDidAllocateFromParentTask(bool value = true); -}; - -} // end namespace swift - -#endif // SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/Error.h b/stdlib/toolchain/Compatibility56/include/Concurrency/Error.h deleted file mode 100644 index cfb89b4685648..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/Error.h +++ /dev/null @@ -1,30 +0,0 @@ -//===--- Error.h - Swift Concurrency error helpers --------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Error handling support. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H -#define SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H - -#include "public/SwiftShims/Visibility.h" -#include -#include - -namespace swift { - -SWIFT_NORETURN void swift_Concurrency_fatalError(uint32_t flags, const char *format, ...); - -} // namespace swift - -#endif // SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/Executor.h b/stdlib/toolchain/Compatibility56/include/Concurrency/Executor.h deleted file mode 100644 index 013f013c82251..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/Executor.h +++ /dev/null @@ -1,221 +0,0 @@ -//===--- Executor.h - ABI structures for executors --------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift ABI describing executors. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H -#define SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H - -#include - -#include "Actor.h" -#include "swift/ABI/HeapObject.h" -#include "swift/Runtime/Casting.h" - -namespace swift { -class AsyncContext; -class AsyncTask; -class DefaultActor; -class Job; -class SerialExecutorWitnessTable; - -/// An unmanaged reference to an executor. -/// -/// This type corresponds to the type Optional in -/// Swift. The representation of nil in Optional -/// aligns with what this type calls the generic executor, so the -/// notional subtype of this type which is never generic corresponds -/// to the type Builtin.Executor. -/// -/// An executor reference is divided into two pieces: -/// -/// - The identity, which is just a (potentially ObjC) object -/// reference; when this is null, the reference is generic. -/// Equality of executor references is based solely on equality -/// of identity. -/// -/// - The implementation, which is an optional reference to a -/// witness table for the SerialExecutor protocol. When this -/// is null, but the identity is non-null, the reference is to -/// a default actor. The low bits of the implementation pointer -/// are reserved for the use of marking interesting properties -/// about the executor's implementation. The runtime masks these -/// bits off before accessing the witness table, so setting them -/// in the future should back-deploy as long as the witness table -/// reference is still present. -class ExecutorRef { - HeapObject *Identity; // Not necessarily Swift reference-countable - uintptr_t Implementation; - - // We future-proof the ABI here by masking the low bits off the - // implementation pointer before using it as a witness table. - enum: uintptr_t { - WitnessTableMask = ~uintptr_t(alignof(void*) - 1) - }; - - constexpr ExecutorRef(HeapObject *identity, uintptr_t implementation) - : Identity(identity), Implementation(implementation) {} - -public: - /// A generic execution environment. When running in a generic - /// environment, it's presumed to be okay to switch synchronously - /// to an actor. As an executor request, this represents a request - /// to drop whatever the current actor is. - constexpr static ExecutorRef generic() { - return ExecutorRef(nullptr, 0); - } - - /// Given a pointer to a default actor, return an executor reference - /// for it. - static ExecutorRef forDefaultActor(DefaultActor *actor) { - assert(actor); - return ExecutorRef(actor, 0); - } - - /// Given a pointer to a serial executor and its SerialExecutor - /// conformance, return an executor reference for it. - static ExecutorRef forOrdinary(HeapObject *identity, - const SerialExecutorWitnessTable *witnessTable) { - assert(identity); - assert(witnessTable); - return ExecutorRef(identity, reinterpret_cast(witnessTable)); - } - - HeapObject *getIdentity() const { - return Identity; - } - - /// Is this the generic executor reference? - bool isGeneric() const { - return Identity == 0; - } - - /// Is this a default-actor executor reference? - bool isDefaultActor() const { - return !isGeneric() && Implementation == 0; - } - DefaultActor *getDefaultActor() const { - assert(isDefaultActor()); - return reinterpret_cast(Identity); - } - - const SerialExecutorWitnessTable *getSerialExecutorWitnessTable() const { - assert(!isGeneric() && !isDefaultActor()); - auto table = Implementation & WitnessTableMask; - return reinterpret_cast(table); - } - - /// Do we have to do any work to start running as the requested - /// executor? - bool mustSwitchToRun(ExecutorRef newExecutor) const { - return Identity != newExecutor.Identity; - } - - /// Is this executor the main executor? - bool isMainExecutor() const; - - bool operator==(ExecutorRef other) const { - return Identity == other.Identity; - } - bool operator!=(ExecutorRef other) const { - return !(*this == other); - } -}; - -using JobInvokeFunction = - SWIFT_CC(swiftasync) - void (Job *); - -using TaskContinuationFunction = - SWIFT_CC(swiftasync) - void (SWIFT_ASYNC_CONTEXT AsyncContext *); - -using ThrowingTaskFutureWaitContinuationFunction = - SWIFT_CC(swiftasync) - void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *); - - -template -class AsyncFunctionPointer; -template -struct AsyncFunctionTypeImpl; - -/// The abstract signature for an asynchronous function. -template -struct AsyncSignature; - -template -struct AsyncSignature { - bool hasDirectResult = !std::is_same::value; - using DirectResultType = DirectResultTy; - - bool hasErrorResult = HasErrorResult; - - using FunctionPointer = AsyncFunctionPointer; - using FunctionType = typename AsyncFunctionTypeImpl::type; -}; - -/// A signature for a thin async function that takes no arguments -/// and returns no results. -using ThinNullaryAsyncSignature = - AsyncSignature; - -/// A signature for a thick async function that takes no formal -/// arguments and returns no results. -using ThickNullaryAsyncSignature = - AsyncSignature; - -/// A class which can be used to statically query whether a type -/// is a specialization of AsyncSignature. -template -struct IsAsyncSignature { - static const bool value = false; -}; -template -struct IsAsyncSignature> { - static const bool value = true; -}; - -template -struct AsyncFunctionTypeImpl { - static_assert(IsAsyncSignature::value, - "template argument is not an AsyncSignature"); - - // TODO: expand and include the arguments in the parameters. - using type = TaskContinuationFunction; -}; - -template -using AsyncFunctionType = typename AsyncFunctionTypeImpl::type; - -/// A "function pointer" for an async function. -/// -/// Eventually, this will always be signed with the data key -/// using a type-specific discriminator. -template -class AsyncFunctionPointer { -public: - /// The function to run. - RelativeDirectPointer, - /*nullable*/ false, - int32_t> Function; - - /// The expected size of the context. - uint32_t ExpectedContextSize; -}; - -} - -#endif // SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/Task.h b/stdlib/toolchain/Compatibility56/include/Concurrency/Task.h deleted file mode 100644 index 47b9076d85e7a..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/Task.h +++ /dev/null @@ -1,776 +0,0 @@ -//===--- Task.h - ABI structures for asynchronous tasks ---------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift ABI describing tasks. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_ABI_TASK_BACKDEPLOY56_H -#define SWIFT_ABI_TASK_BACKDEPLOY56_H - -#include "Executor.h" -#include "swift/ABI/HeapObject.h" -#include "swift/ABI/Metadata.h" -#include "swift/ABI/MetadataValues.h" // Maybe replace? - -#include "swift/Runtime/Config.h" -#include "VoucherShims.h" -#include "swift/Basic/STLExtras.h" -#include -#include - -namespace swift { -class AsyncTask; -class AsyncContext; -class Job; -struct OpaqueValue; -struct SwiftError; -class TaskStatusRecord; -class TaskOptionRecord; -class TaskGroup; - -extern FullMetadata jobHeapMetadata; - -/// A schedulable job. -class alignas(2 * alignof(void*)) Job : - // For async-let tasks, the refcount bits are initialized as "immortal" - // because such a task is allocated with the parent's stack allocator. - public HeapObject { -public: - // Indices into SchedulerPrivate, for use by the runtime. - enum { - /// The next waiting task link, an AsyncTask that is waiting on a future. - NextWaitingTaskIndex = 0, - - // The Dispatch object header is one pointer and two ints, which is - // equivalent to three pointers on 32-bit and two pointers 64-bit. Set the - // indexes accordingly so that DispatchLinkageIndex points to where Dispatch - // expects. - DispatchHasLongObjectHeader = sizeof(void *) == sizeof(int), - - /// An opaque field used by Dispatch when enqueueing Jobs directly. - DispatchLinkageIndex = DispatchHasLongObjectHeader ? 1 : 0, - - /// The dispatch queue being used when enqueueing a Job directly with - /// Dispatch. - DispatchQueueIndex = DispatchHasLongObjectHeader ? 0 : 1, - }; - - // Reserved for the use of the scheduler. - void *SchedulerPrivate[2]; - - JobFlags Flags; - - // Derived classes can use this to store a Job Id. - uint32_t Id = 0; - - /// The voucher associated with the job. Note: this is currently unused on - /// non-Darwin platforms, with stub implementations of the functions for - /// consistency. - voucher_t Voucher = nullptr; - - /// Reserved for future use. - void *Reserved = nullptr; - - // We use this union to avoid having to do a second indirect branch - // when resuming an asynchronous task, which we expect will be the - // common case. - union { - // A function to run a job that isn't an AsyncTask. - JobInvokeFunction * __ptrauth_swift_job_invoke_function RunJob; - - // A function to resume an AsyncTask. - TaskContinuationFunction * __ptrauth_swift_task_resume_function ResumeTask; - }; - - Job(JobFlags flags, JobInvokeFunction *invoke, - const HeapMetadata *metadata = &jobHeapMetadata) - : HeapObject(metadata), Flags(flags), RunJob(invoke) { - Voucher = voucher_copy(); - assert(!isAsyncTask() && "wrong constructor for a task"); - } - - Job(JobFlags flags, TaskContinuationFunction *invoke, - const HeapMetadata *metadata = &jobHeapMetadata, - bool captureCurrentVoucher = true) - : HeapObject(metadata), Flags(flags), ResumeTask(invoke) { - if (captureCurrentVoucher) - Voucher = voucher_copy(); - assert(isAsyncTask() && "wrong constructor for a non-task job"); - } - - /// Create a job with "immortal" reference counts. - /// Used for async let tasks. - Job(JobFlags flags, TaskContinuationFunction *invoke, - const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal, - bool captureCurrentVoucher = true) - : HeapObject(metadata, immortal), Flags(flags), ResumeTask(invoke) { - if (captureCurrentVoucher) - Voucher = voucher_copy(); - assert(isAsyncTask() && "wrong constructor for a non-task job"); - } - - ~Job() { swift_voucher_release(Voucher); } - - bool isAsyncTask() const { - return Flags.isAsyncTask(); - } - - JobPriority getPriority() const { - return Flags.getPriority(); - } - - /// Given that we've fully established the job context in the current - /// thread, actually start running this job. To establish the context - /// correctly, call swift_job_run or runJobInExecutorContext. - SWIFT_CC(swiftasync) - void runInFullyEstablishedContext(); - - /// Given that we've fully established the job context in the - /// current thread, and that the job is a simple (non-task) job, - /// actually start running this job. - SWIFT_CC(swiftasync) - void runSimpleInFullyEstablishedContext() { - return RunJob(this); // 'return' forces tail call - } -}; - -// The compiler will eventually assume these. -#if SWIFT_POINTER_IS_8_BYTES -static_assert(sizeof(Job) == 8 * sizeof(void*), - "Job size is wrong"); -#else -static_assert(sizeof(Job) == 10 * sizeof(void*), - "Job size is wrong"); -#endif -static_assert(alignof(Job) == 2 * alignof(void*), - "Job alignment is wrong"); - -class NullaryContinuationJob : public Job { - -private: - AsyncTask* Task; - AsyncTask* Continuation; - -public: - NullaryContinuationJob(AsyncTask *task, JobPriority priority, AsyncTask *continuation) - : Job({JobKind::NullaryContinuation, priority}, &process), - Task(task), Continuation(continuation) {} - - SWIFT_CC(swiftasync) - static void process(Job *job); - - static bool classof(const Job *job) { - return job->Flags.getKind() == JobKind::NullaryContinuation; - } -}; - -/// An asynchronous task. Tasks are the analogue of threads for -/// asynchronous functions: that is, they are a persistent identity -/// for the overall async computation. -/// -/// ### Fragments -/// An AsyncTask may have the following fragments: -/// -/// +--------------------------+ -/// | childFragment? | -/// | groupChildFragment? | -/// | futureFragment? |* -/// +--------------------------+ -/// -/// * The future fragment is dynamic in size, based on the future result type -/// it can hold, and thus must be the *last* fragment. -class AsyncTask : public Job { -public: - // On 32-bit targets, there is a word of tail padding remaining - // in Job, and ResumeContext will fit into that, at offset 28. - // Private then has offset 32. - // On 64-bit targets, there is no tail padding in Job, and so - // ResumeContext has offset 48. There is therefore another word - // of reserved storage prior to Private (which needs to have - // double-word alignment), which has offset 64. - // We therefore converge and end up with 16 words of storage on - // all platforms. - - /// The context for resuming the job. When a task is scheduled - /// as a job, the next continuation should be installed as the - /// ResumeTask pointer in the job header, with this serving as - /// the context pointer. - /// - /// We can't protect the data in the context from being overwritten - /// by attackers, but we can at least sign the context pointer to - /// prevent it from being corrupted in flight. - AsyncContext * __ptrauth_swift_task_resume_context ResumeContext; - -#if SWIFT_POINTER_IS_8_BYTES - void *Reserved64; -#endif - - struct PrivateStorage; - - /// Private storage for the use of the runtime. - struct alignas(2 * alignof(void*)) OpaquePrivateStorage { - void *Storage[14]; - - /// Initialize this storage during the creation of a task. - void initialize(JobPriority basePri); - void initializeWithSlab(JobPriority basePri, void *slab, - size_t slabCapacity); - - /// React to the completion of the enclosing task's execution. - void complete(AsyncTask *task); - - /// React to the final destruction of the enclosing task. - void destroy(); - - PrivateStorage &get(); - const PrivateStorage &get() const; - }; - PrivateStorage &_private(); - const PrivateStorage &_private() const; - - OpaquePrivateStorage Private; - - /// Create a task. - /// This does not initialize Private; callers must call - /// Private.initialize separately. - AsyncTask(const HeapMetadata *metadata, JobFlags flags, - TaskContinuationFunction *run, - AsyncContext *initialContext, - bool captureCurrentVoucher) - : Job(flags, run, metadata, captureCurrentVoucher), - ResumeContext(initialContext) { - assert(flags.isAsyncTask()); - setTaskId(); - } - - /// Create a task with "immortal" reference counts. - /// Used for async let tasks. - /// This does not initialize Private; callers must call - /// Private.initialize separately. - AsyncTask(const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal, - JobFlags flags, - TaskContinuationFunction *run, - AsyncContext *initialContext, - bool captureCurrentVoucher) - : Job(flags, run, metadata, immortal, captureCurrentVoucher), - ResumeContext(initialContext) { - assert(flags.isAsyncTask()); - setTaskId(); - } - - ~AsyncTask(); - - /// Set the task's ID field to the next task ID. - void setTaskId(); - uint64_t getTaskId(); - - /// Get the task's resume function, for logging purposes only. This will - /// attempt to see through the various adapters that are sometimes used, and - /// failing that will return ResumeTask. The returned function pointer may - /// have a different signature than ResumeTask, and it's only for identifying - /// code associated with the task. - const void *getResumeFunctionForLogging(); - - /// Given that we've already fully established the job context - /// in the current thread, start running this task. To establish - /// the job context correctly, call swift_job_run or - /// runInExecutorContext. - SWIFT_CC(swiftasync) - void runInFullyEstablishedContext() { - return ResumeTask(ResumeContext); // 'return' forces tail call - } - - /// A task can have the following states: - /// * suspended: In this state, a task is considered not runnable - /// * enqueued: In this state, a task is considered runnable - /// * running on a thread - /// * completed - /// - /// The following state transitions are possible: - /// suspended -> enqueued - /// suspended -> running - /// enqueued -> running - /// running -> suspended - /// running -> completed - /// running -> enqueued - /// - /// The 4 methods below are how a task switches from one state to another. - - /// Flag that this task is now running. This can update - /// the priority stored in the job flags if the priority has been - /// escalated. - /// - /// Generally this should be done immediately after updating - /// ActiveTask. - void flagAsRunning(); - - /// Flag that this task is now suspended. - void flagAsSuspended(); - - /// Flag that the task is to be enqueued on the provided executor and actually - /// enqueue it - void flagAsAndEnqueueOnExecutor(ExecutorRef newExecutor); - - /// Flag that this task is now completed. This normally does not do anything - /// but can be used to locally insert logging. - void flagAsCompleted(); - - /// Check whether this task has been cancelled. - /// Checking this is, of course, inherently race-prone on its own. - bool isCancelled() const; - - // ==== Task Local Values ---------------------------------------------------- - - void localValuePush(const HeapObject *key, - /* +1 */ OpaqueValue *value, - const Metadata *valueType); - - OpaqueValue *localValueGet(const HeapObject *key); - - /// Returns true if storage has still more bindings. - bool localValuePop(); - - // ==== Child Fragment ------------------------------------------------------- - - /// A fragment of an async task structure that happens to be a child task. - class ChildFragment { - /// The parent task of this task. - AsyncTask *Parent; - - // TODO: Document more how this is used from the `TaskGroupTaskStatusRecord` - - /// The next task in the singly-linked list of child tasks. - /// The list must start in a `ChildTaskStatusRecord` registered - /// with the parent task. - /// - /// Note that the parent task may have multiple such records. - /// - /// WARNING: Access can only be performed by the `Parent` of this task. - AsyncTask *NextChild = nullptr; - - public: - ChildFragment(AsyncTask *parent) : Parent(parent) {} - - AsyncTask *getParent() const { - return Parent; - } - - AsyncTask *getNextChild() const { - return NextChild; - } - - /// Set the `NextChild` to to the passed task. - /// - /// WARNING: This must ONLY be invoked from the parent of both - /// (this and the passed-in) tasks for thread-safety reasons. - void setNextChild(AsyncTask *task) { - NextChild = task; - } - }; - - bool hasChildFragment() const { - return Flags.task_isChildTask(); - } - - ChildFragment *childFragment() { - assert(hasChildFragment()); - - auto offset = reinterpret_cast(this); - offset += sizeof(AsyncTask); - - return reinterpret_cast(offset); - } - - // ==== TaskGroup Child ------------------------------------------------------ - - /// A child task created by `group.add` is called a "task group child." - /// Upon completion, in addition to the usual future notifying all its waiters, - /// it must also `group->offer` itself to the group. - /// - /// This signalling is necessary to correctly implement the group's `next()`. - class GroupChildFragment { - private: - TaskGroup* Group; - - friend class AsyncTask; - friend class TaskGroup; - - public: - explicit GroupChildFragment(TaskGroup *group) - : Group(group) {} - - /// Return the group this task should offer into when it completes. - TaskGroup* getGroup() { - return Group; - } - }; - - // Checks if task is a child of a TaskGroup task. - // - // A child task that is a group child knows that it's parent is a group - // and therefore may `groupOffer` to it upon completion. - bool hasGroupChildFragment() const { return Flags.task_isGroupChildTask(); } - - GroupChildFragment *groupChildFragment() { - assert(hasGroupChildFragment()); - - auto offset = reinterpret_cast(this); - offset += sizeof(AsyncTask); - if (hasChildFragment()) - offset += sizeof(ChildFragment); - - return reinterpret_cast(offset); - } - - // ==== Future --------------------------------------------------------------- - - class FutureFragment { - public: - /// Describes the status of the future. - /// - /// Futures always begin in the "Executing" state, and will always - /// make a single state change to either Success or Error. - enum class Status : uintptr_t { - /// The future is executing or ready to execute. The storage - /// is not accessible. - Executing = 0, - - /// The future has completed with result (of type \c resultType). - Success, - - /// The future has completed by throwing an error (an \c Error - /// existential). - Error, - }; - - /// An item within the wait queue, which includes the status and the - /// head of the list of tasks. - struct WaitQueueItem { - /// Mask used for the low status bits in a wait queue item. - static const uintptr_t statusMask = 0x03; - - uintptr_t storage; - - Status getStatus() const { - return static_cast(storage & statusMask); - } - - AsyncTask *getTask() const { - return reinterpret_cast(storage & ~statusMask); - } - - static WaitQueueItem get(Status status, AsyncTask *task) { - return WaitQueueItem{ - reinterpret_cast(task) | static_cast(status)}; - } - }; - - private: - /// Queue containing all of the tasks that are waiting in `get()`. - /// - /// The low bits contain the status, the rest of the pointer is the - /// AsyncTask. - std::atomic waitQueue; - - /// The type of the result that will be produced by the future. - const Metadata *resultType; - - SwiftError *error = nullptr; - - // Trailing storage for the result itself. The storage will be - // uninitialized, contain an instance of \c resultType. - - friend class AsyncTask; - - public: - explicit FutureFragment(const Metadata *resultType) - : waitQueue(WaitQueueItem::get(Status::Executing, nullptr)), - resultType(resultType) { } - - /// Destroy the storage associated with the future. - void destroy(); - - const Metadata *getResultType() const { - return resultType; - } - - /// Retrieve a pointer to the storage of the result. - OpaqueValue *getStoragePtr() { - // The result storage starts at the first aligned offset following - // the fragment header. This offset will agree with the abstract - // calculation for `resultOffset` in the fragmentSize function below - // because the entire task is aligned to at least the target - // alignment (because it's aligned to MaxAlignment), which means - // `this` must have the same value modulo that alignment as - // `fragmentOffset` has in that function. - char *fragmentAddr = reinterpret_cast(this); - uintptr_t alignment = resultType->vw_alignment(); - char *resultAddr = fragmentAddr + sizeof(FutureFragment); - uintptr_t unalignedResultAddrInt = - reinterpret_cast(resultAddr); - uintptr_t alignedResultAddrInt = - (unalignedResultAddrInt + alignment - 1) & ~(alignment - 1); - // We could just cast alignedResultAddrInt back to a pointer, but - // doing pointer arithmetic is more strictly conformant and less - // likely to annoy the optimizer. - resultAddr += (alignedResultAddrInt - unalignedResultAddrInt); - return reinterpret_cast(resultAddr); - } - - /// Retrieve the error. - SwiftError *&getError() { return error; } - - /// Determine the size of the future fragment given the result type - /// of the future. - static size_t fragmentSize(size_t fragmentOffset, - const Metadata *resultType) { - assert((fragmentOffset & (alignof(FutureFragment) - 1)) == 0); - size_t alignment = resultType->vw_alignment(); - size_t resultOffset = fragmentOffset + sizeof(FutureFragment); - resultOffset = (resultOffset + alignment - 1) & ~(alignment - 1); - size_t endOffset = resultOffset + resultType->vw_size(); - return (endOffset - fragmentOffset); - } - }; - - bool isFuture() const { return Flags.task_isFuture(); } - - FutureFragment *futureFragment() { - assert(isFuture()); - auto offset = reinterpret_cast(this); - offset += sizeof(AsyncTask); - if (hasChildFragment()) - offset += sizeof(ChildFragment); - if (hasGroupChildFragment()) - offset += sizeof(GroupChildFragment); - - return reinterpret_cast(offset); - } - - /// Wait for this future to complete. - /// - /// \returns the status of the future. If this result is - /// \c Executing, then \c waitingTask has been added to the - /// wait queue and will be scheduled when the future completes. Otherwise, - /// the future has completed and can be queried. - /// The waiting task's async context will be initialized with the parameters if - /// the current's task state is executing. - FutureFragment::Status waitFuture(AsyncTask *waitingTask, - AsyncContext *waitingTaskContext, - TaskContinuationFunction *resumeFn, - AsyncContext *callerContext, - OpaqueValue *result); - - /// Complete this future. - /// - /// Upon completion, any waiting tasks will be scheduled on the given - /// executor. - void completeFuture(AsyncContext *context); - - // ==== ---------------------------------------------------------------------- - - static bool classof(const Job *job) { - return job->isAsyncTask(); - } - -private: - /// Access the next waiting task, which establishes a singly linked list of - /// tasks that are waiting on a future. - AsyncTask *&getNextWaitingTask() { - return reinterpret_cast( - SchedulerPrivate[NextWaitingTaskIndex]); - } -}; - -// The compiler will eventually assume these. -static_assert(sizeof(AsyncTask) == NumWords_AsyncTask * sizeof(void*), - "AsyncTask size is wrong"); -static_assert(alignof(AsyncTask) == 2 * alignof(void*), - "AsyncTask alignment is wrong"); -// Libc hardcodes this offset to extract the TaskID -static_assert(offsetof(AsyncTask, Id) == 4 * sizeof(void *) + 4, - "AsyncTask::Id offset is wrong"); - -SWIFT_CC(swiftasync) -inline void Job::runInFullyEstablishedContext() { - if (auto task = dyn_cast(this)) - return task->runInFullyEstablishedContext(); // 'return' forces tail call - else - return runSimpleInFullyEstablishedContext(); // 'return' forces tail call -} - -// ==== ------------------------------------------------------------------------ - -/// An asynchronous context within a task. Generally contexts are -/// allocated using the task-local stack alloc/dealloc operations, but -/// there's no guarantee of that, and the ABI is designed to permit -/// contexts to be allocated within their caller's frame. -class alignas(MaximumAlignment) AsyncContext { -public: - /// The parent context. - AsyncContext * __ptrauth_swift_async_context_parent Parent; - - /// The function to call to resume running in the parent context. - /// Generally this means a semantic return, but for some temporary - /// translation contexts it might mean initiating a call. - /// - /// Eventually, the actual type here will depend on the types - /// which need to be passed to the parent. For now, arguments - /// are always written into the context, and so the type is - /// always the same. - TaskContinuationFunction * __ptrauth_swift_async_context_resume - ResumeParent; - - AsyncContext(TaskContinuationFunction *resumeParent, - AsyncContext *parent) - : Parent(parent), ResumeParent(resumeParent) {} - - AsyncContext(const AsyncContext &) = delete; - AsyncContext &operator=(const AsyncContext &) = delete; - - /// Perform a return from this context. - /// - /// Generally this should be tail-called. - SWIFT_CC(swiftasync) - void resumeParent() { - // TODO: destroy context before returning? - // FIXME: force tail call - return ResumeParent(Parent); - } -}; - -/// An async context that supports yielding. -class YieldingAsyncContext : public AsyncContext { -public: - /// The function to call to temporarily resume running in the - /// parent context. Generally this means a semantic yield. - TaskContinuationFunction * __ptrauth_swift_async_context_yield - YieldToParent; - - YieldingAsyncContext(TaskContinuationFunction *resumeParent, - TaskContinuationFunction *yieldToParent, - AsyncContext *parent) - : AsyncContext(resumeParent, parent), - YieldToParent(yieldToParent) {} -}; - -/// An async context that can be resumed as a continuation. -class ContinuationAsyncContext : public AsyncContext { -public: - class FlagsType : public FlagSet { - public: - enum { - CanThrow = 0, - IsExecutorSwitchForced = 1, - }; - - explicit FlagsType(size_t bits) : FlagSet(bits) {} - constexpr FlagsType() {} - - /// Whether this is a throwing continuation. - FLAGSET_DEFINE_FLAG_ACCESSORS(CanThrow, - canThrow, - setCanThrow) - - /// See AsyncContinuationFlags::isExecutorSwitchForced(). - FLAGSET_DEFINE_FLAG_ACCESSORS(IsExecutorSwitchForced, - isExecutorSwitchForced, - setIsExecutorSwitchForced) - }; - - /// Flags for the continuation. Not public ABI. - FlagsType Flags; - - /// An atomic object used to ensure that a continuation is not - /// scheduled immediately during a resume if it hasn't yet been - /// awaited by the function which set it up. Not public ABI. - std::atomic AwaitSynchronization; - - /// The error result value of the continuation. - /// This should be null-initialized when setting up the continuation. - /// Throwing resumers must overwrite this with a non-null value. - /// Public ABI. - SwiftError *ErrorResult; - - /// A pointer to the normal result value of the continuation. - /// Normal resumers must initialize this before resuming. - /// Public ABI. - OpaqueValue *NormalResult; - - /// The executor that should be resumed to. - /// Public ABI. - ExecutorRef ResumeToExecutor; - - void setErrorResult(SwiftError *error) { - ErrorResult = error; - } - - bool isExecutorSwitchForced() const { - return Flags.isExecutorSwitchForced(); - } -}; - -/// An asynchronous context within a task that describes a general "Future". -/// task. -/// -/// This type matches the ABI of a function ` () async throws -> T`, which -/// is the type used by `detach` and `Task.group.add` to create -/// futures. -class FutureAsyncContext : public AsyncContext { -public: - using AsyncContext::AsyncContext; -}; - -/// This matches the ABI of a closure `() async throws -> ()` -using AsyncVoidClosureEntryPoint = - SWIFT_CC(swiftasync) - void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *); - -/// This matches the ABI of a closure `() async throws -> T` -using AsyncGenericClosureEntryPoint = - SWIFT_CC(swiftasync) - void(OpaqueValue *, - SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *); - -/// This matches the ABI of the resume function of a closure -/// `() async throws -> ()`. -using AsyncVoidClosureResumeEntryPoint = - SWIFT_CC(swiftasync) - void(SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT SwiftError *); - -class AsyncContextPrefix { -public: - // Async closure entry point adhering to compiler calling conv (e.g directly - // passing the closure context instead of via the async context) - AsyncVoidClosureEntryPoint *__ptrauth_swift_task_resume_function - asyncEntryPoint; - void *closureContext; - SwiftError *errorResult; -}; - -/// Storage that is allocated before the AsyncContext to be used by an adapter -/// of Swift's async convention and the ResumeTask interface. -class FutureAsyncContextPrefix { -public: - OpaqueValue *indirectResult; - // Async closure entry point adhering to compiler calling conv (e.g directly - // passing the closure context instead of via the async context) - AsyncGenericClosureEntryPoint *__ptrauth_swift_task_resume_function - asyncEntryPoint; - void *closureContext; - SwiftError *errorResult; -}; - -} // end namespace swift - -#endif // SWIFT_ABI_TASK_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/TaskPrivate.h b/stdlib/toolchain/Compatibility56/include/Concurrency/TaskPrivate.h deleted file mode 100644 index b51f3b437ce2e..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/TaskPrivate.h +++ /dev/null @@ -1,71 +0,0 @@ -//===--- TaskPrivate.h - Concurrency library internal interface -*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Internal functions for the concurrency library. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H -#define SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H - -#include "Concurrency/Error.h" -#include "Concurrency/Task.h" -#include "swift/Runtime/Error.h" - -namespace swift { -namespace { - -/// The layout of a context to call one of the following functions: -/// -/// @_silgen_name("swift_task_future_wait") -/// func _taskFutureGet(_ task: Builtin.NativeObject) async -> T -/// -/// @_silgen_name("swift_task_future_wait_throwing") -/// func _taskFutureGetThrowing(_ task: Builtin.NativeObject) async throws -> T -/// -/// @_silgen_name("swift_asyncLet_wait") -/// func _asyncLetGet(_ task: Builtin.RawPointer) async -> T -/// -/// @_silgen_name("swift_asyncLet_waitThrowing") -/// func _asyncLetGetThrowing(_ task: Builtin.RawPointer) async throws -> T -/// -/// @_silgen_name("swift_taskGroup_wait_next_throwing") -/// func _taskGroupWaitNext(group: Builtin.RawPointer) async throws -> T? -/// -class TaskFutureWaitAsyncContext : public AsyncContext { -public: - SwiftError *errorResult; - - OpaqueValue *successResultPointer; - - void fillWithSuccess(AsyncTask::FutureFragment *future) { - fillWithSuccess(future->getStoragePtr(), future->getResultType(), - successResultPointer); - } - void fillWithSuccess(OpaqueValue *src, const Metadata *successType, - OpaqueValue *result) { - successType->vw_initializeWithCopy(result, src); - } - - void fillWithError(AsyncTask::FutureFragment *future) { - fillWithError(future->getError()); - } - void fillWithError(SwiftError *error) { - errorResult = error; - swift_errorRetain(error); - } -}; - -} -} // namespace swift - -#endif // SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/TaskStatus.h b/stdlib/toolchain/Compatibility56/include/Concurrency/TaskStatus.h deleted file mode 100644 index 665f94048b2ed..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/TaskStatus.h +++ /dev/null @@ -1,166 +0,0 @@ -//===--- TaskStatusRecord.h - Structures to track task status --*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift ABI describing "status records", the mechanism by which -// tasks track dynamic information about their child tasks, custom -// cancellation hooks, and other information which may need to be exposed -// asynchronously outside of the task. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H -#define SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H - -#include "swift/ABI/MetadataValues.h" -#include "Task.h" - -namespace swift { - -/// The abstract base class for all status records. -/// -/// TaskStatusRecords are typically allocated on the stack (possibly -/// in the task context), partially initialized, and then atomically -/// added to the task with `swift_task_addTaskStatusRecord`. While -/// registered with the task, a status record should only be -/// modified in ways that respect the possibility of asynchronous -/// access by a cancelling thread. In particular, the chain of -/// status records must not be disturbed. When the task leaves -/// the scope that requires the status record, the record can -/// be unregistered from the task with `removeStatusRecord`, -/// at which point the memory can be returned to the system. -class TaskStatusRecord { -public: - TaskStatusRecordFlags Flags; - TaskStatusRecord *Parent; - - TaskStatusRecord(TaskStatusRecordKind kind, - TaskStatusRecord *parent = nullptr) - : Flags(kind) { - resetParent(parent); - } - - TaskStatusRecord(const TaskStatusRecord &) = delete; - TaskStatusRecord &operator=(const TaskStatusRecord &) = delete; - - TaskStatusRecordKind getKind() const { return Flags.getKind(); } - - TaskStatusRecord *getParent() const { return Parent; } - - /// Change the parent of this unregistered status record to the - /// given record. - /// - /// This should be used when the record has been previously initialized - /// without knowing what the true parent is. If we decide to cache - /// important information (e.g. the earliest timeout) in the innermost - /// status record, this is the method that should fill that in - /// from the parent. - void resetParent(TaskStatusRecord *newParent) { - Parent = newParent; - // TODO: cache - } - - /// Splice a record out of the status-record chain. - /// - /// Unlike resetParent, this assumes that it's just removing one or - /// more records from the chain and that there's no need to do any - /// extra cache manipulation. - void spliceParent(TaskStatusRecord *newParent) { Parent = newParent; } -}; - -/// A deadline for the task. If this is reached, the task will be -/// automatically cancelled. The deadline can also be queried and used -/// in other ways. -struct TaskDeadline { - // FIXME: I don't really know what this should look like right now. - // It's probably target-specific. - uint64_t Value; - - bool operator==(const TaskDeadline &other) const { - return Value == other.Value; - } - bool operator<(const TaskDeadline &other) const { - return Value < other.Value; - } -}; - -/// A status record which states that a task has one or -/// more active child tasks. -class ChildTaskStatusRecord : public TaskStatusRecord { - AsyncTask *FirstChild; - -public: - ChildTaskStatusRecord(AsyncTask *child) - : TaskStatusRecord(TaskStatusRecordKind::ChildTask), FirstChild(child) {} - - ChildTaskStatusRecord(AsyncTask *child, TaskStatusRecordKind kind) - : TaskStatusRecord(kind), FirstChild(child) { - assert(kind == TaskStatusRecordKind::ChildTask); - assert(!child->hasGroupChildFragment() && - "Group child tasks must be tracked in their respective " - "TaskGroupTaskStatusRecord, and not as independent " - "ChildTaskStatusRecord " - "records."); - } - - /// Return the first child linked by this record. This may be null; - /// if not, it (and all of its successors) are guaranteed to satisfy - /// `isChildTask()`. - AsyncTask *getFirstChild() const { return FirstChild; } - - static AsyncTask *getNextChildTask(AsyncTask *task) { - return task->childFragment()->getNextChild(); - } - - using child_iterator = LinkedListIterator; - llvm::iterator_range children() const { - return child_iterator::rangeBeginning(getFirstChild()); - } - - static bool classof(const TaskStatusRecord *record) { - return record->getKind() == TaskStatusRecordKind::ChildTask; - } -}; - -/// A cancellation record which states that a task has an arbitrary -/// function that needs to be called if the task is cancelled. -/// -/// The end of any call to the function will be ordered before the -/// end of a call to unregister this record from the task. That is, -/// code may call `removeStatusRecord` and freely -/// assume after it returns that this function will not be -/// subsequently used. -class CancellationNotificationStatusRecord : public TaskStatusRecord { -public: - using FunctionType = SWIFT_CC(swift) void(SWIFT_CONTEXT void *); - -private: - FunctionType *__ptrauth_swift_cancellation_notification_function Function; - void *Argument; - -public: - CancellationNotificationStatusRecord(FunctionType *fn, void *arg) - : TaskStatusRecord(TaskStatusRecordKind::CancellationNotification), - Function(fn), Argument(arg) {} - - void run() { Function(Argument); } - - static bool classof(const TaskStatusRecord *record) { - return record->getKind() == TaskStatusRecordKind::CancellationNotification; - } -}; - -/// Return the current thread's active task reference. -SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift) -AsyncTask *swift_task_getCurrent(void); -} // namespace swift - -#endif // SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Concurrency/VoucherShims.h b/stdlib/toolchain/Compatibility56/include/Concurrency/VoucherShims.h deleted file mode 100644 index 50927c2a614b7..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Concurrency/VoucherShims.h +++ /dev/null @@ -1,103 +0,0 @@ -//===--- VoucherShims.h - Shims for OS vouchers --------------------*- C++ -*-// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2021 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Shims for interfacing with OS voucher calls. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H -#define SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H - -#include -#include "swift/Runtime/Config.h" - -// swift-corelibs-libdispatch has os/voucher_private.h but it doesn't work for -// us yet, so only look for it on Apple platforms. -#if __APPLE__ && __has_include() -#define SWIFT_HAS_VOUCHER_HEADER 1 -#include -#endif - -// A "dead" voucher pointer, indicating that a voucher has been removed from -// a Job, distinct from a NULL voucher that could just mean no voucher was -// present. This allows us to catch problems like adopting a voucher from the -// same Job twice without restoring it. -#define SWIFT_DEAD_VOUCHER ((voucher_t)-1) - -// The OS has voucher support if it has the header or if it has ObjC interop. -#if SWIFT_HAS_VOUCHER_HEADER || SWIFT_OBJC_INTEROP -#define SWIFT_HAS_VOUCHERS 1 -#endif - -#if SWIFT_HAS_VOUCHERS - -#if SWIFT_HAS_VOUCHER_HEADER - -#else - -// If the header isn't available, declare the necessary calls here. - -#include - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -OS_OBJECT_DECL_CLASS(voucher); -#pragma clang diagnostic pop - -extern "C" voucher_t _Nullable voucher_copy(void); - -// Consumes argument, returns retained value. -extern "C" voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher); - -#endif // __has_include() - -static inline void swift_voucher_release(voucher_t _Nullable voucher) { - // This NULL check isn't necessary, but NULL vouchers will be common, so - // optimize for that. - if (!voucher) - return; - if (voucher == SWIFT_DEAD_VOUCHER) - return; - os_release(voucher); -} - -#else // __APPLE__ - -// Declare some do-nothing stubs for OSes without voucher support. -typedef void *voucher_t; -static inline voucher_t _Nullable voucher_copy(void) { return nullptr; } -static inline voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher) { - return nullptr; -} -static inline void swift_voucher_release(voucher_t _Nullable voucher) {} -#endif // __APPLE__ - -// Declare our own voucher_needs_adopt for when we don't get it from the SDK. -// This declaration deliberately takes `void *` instead of `voucher_t`. When the -// SDK provides one that takes `voucher_t`, then C++ overload resolution will -// favor that one. When the SDK does not provide a declaration, then the call -// site will invoke this stub instead. -static inline bool voucher_needs_adopt(void * _Nullable voucher) { - return true; -} - -static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) { -#if __APPLE__ - if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)) - return voucher_needs_adopt(voucher); - return true; -#else - return voucher_needs_adopt(voucher); -#endif -} - -#endif // SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Concurrency.h b/stdlib/toolchain/Compatibility56/include/Runtime/Concurrency.h deleted file mode 100644 index f74d614cb507f..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Concurrency.h +++ /dev/null @@ -1,82 +0,0 @@ -//===--- Concurrency.h - Runtime interface for concurrency ------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// The runtime interface for concurrency. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H -#define SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H - -#include "Concurrency/Task.h" -#include "Concurrency/TaskStatus.h" -#include "Concurrency/AsyncLet.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" - -// Does the runtime use a cooperative global executor? -#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) -#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 1 -#else -#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 0 -#endif - -// Does the runtime integrate with libdispatch? -#ifndef SWIFT_CONCURRENCY_ENABLE_DISPATCH -#if SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR -#define SWIFT_CONCURRENCY_ENABLE_DISPATCH 0 -#else -#define SWIFT_CONCURRENCY_ENABLE_DISPATCH 1 -#endif -#endif - -namespace swift { -class DefaultActor; -class TaskOptionRecord; - -struct SwiftError; - -struct AsyncTaskAndContext { - AsyncTask *Task; - AsyncContext *InitialContext; -}; - -/// This should have the same representation as an enum like this: -/// enum NearestTaskDeadline { -/// case none -/// case alreadyCancelled -/// case active(TaskDeadline) -/// } -/// TODO: decide what this interface should really be. -struct NearestTaskDeadline { - enum Kind : uint8_t { - None, - AlreadyCancelled, - Active - }; - - TaskDeadline Value; - Kind ValueKind; -}; - - -/// Caution: not all future-initializing functions actually throw, so -/// this signature may be incorrect. -using FutureAsyncSignature = - AsyncSignature; - -} // namespace swift - -#pragma clang diagnostic pop - -#endif // SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Mutex.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Mutex.h deleted file mode 100644 index e485b68cfcd32..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Mutex.h +++ /dev/null @@ -1,1011 +0,0 @@ -//===--- Mutex.h - Mutex, ConditionVariable, & ReadWriteLock ----*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Mutex, ConditionVariable, Read/Write lock, and Scoped lock abstractions -// for use in Swift runtime. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_MUTEX_BACKDEPLOY56_H -#define SWIFT_RUNTIME_MUTEX_BACKDEPLOY56_H - -#include -#include - -#if __has_include() -#include -#endif - -#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) || defined(__wasi__) -#include "MutexSingleThreaded.h" -#elif defined(_POSIX_THREADS) -#include "MutexPThread.h" -#elif defined(_WIN32) -#include "MutexWin32.h" -#else -#error "Implement equivalent of MutexPThread.h/cpp for your platform." -#endif - -namespace swift { - -/// A stack based object that notifies one thread waiting on a condition -/// variable on destruction. -template -class ScopedNotifyOneT { - ScopedNotifyOneT() = delete; - ScopedNotifyOneT(const ScopedNotifyOneT &) = delete; - ScopedNotifyOneT &operator=(const ScopedNotifyOneT &) = delete; - - ConditionVariable &Condition; -public: - explicit ScopedNotifyOneT(ConditionVariable &c) : Condition(c) {} - - ~ScopedNotifyOneT() { - Condition.notifyOne(); - } -}; - -/// A stack based object that notifies all threads waiting on a condition -/// variable on destruction. -template -class ScopedNotifyAllT { - ScopedNotifyAllT() = delete; - ScopedNotifyAllT(const ScopedNotifyAllT &) = delete; - ScopedNotifyAllT &operator=(const ScopedNotifyAllT &) = delete; - - ConditionVariable &Condition; -public: - explicit ScopedNotifyAllT(ConditionVariable &c) : Condition(c) {} - - ~ScopedNotifyAllT() { - Condition.notifyAll(); - } -}; - -/// Compile time adjusted stack based object that locks/unlocks the supplied -/// Mutex type. Use the provided typedefs instead of this directly. -template class ScopedLockT { - ScopedLockT() = delete; - ScopedLockT(const ScopedLockT &) = delete; - ScopedLockT &operator=(const ScopedLockT &) = delete; - ScopedLockT(ScopedLockT &&) = delete; - ScopedLockT &operator=(ScopedLockT &&) = delete; - -public: - explicit ScopedLockT(T &l) : Lock(l) { - if (Inverted) { - Lock.unlock(); - } else { - Lock.lock(); - } - } - - ~ScopedLockT() { - if (Inverted) { - Lock.lock(); - } else { - Lock.unlock(); - } - } - -private: - T &Lock; -}; - -/// A ConditionVariable that works with Mutex to allow -- as an example -- -/// multi-threaded producers and consumers to signal each other in a safe way. -class ConditionVariable { - friend class ConditionMutex; - friend class StaticConditionVariable; - - ConditionVariable(const ConditionVariable &) = delete; - ConditionVariable &operator=(const ConditionVariable &) = delete; - ConditionVariable(ConditionVariable &&) = delete; - ConditionVariable &operator=(ConditionVariable &&) = delete; - -public: - ConditionVariable() { ConditionPlatformHelper::init(Handle); } - ~ConditionVariable() { ConditionPlatformHelper::destroy(Handle); } - - /// Notifies one waiter (if any exists) that the condition has been met. - /// - /// Note: To avoid missed notification it is best hold the related mutex - // lock when calling notifyOne. - void notifyOne() { ConditionPlatformHelper::notifyOne(Handle); } - - /// Notifies all waiters (if any exists) that the condition has been met. - /// - /// Note: To avoid missed notification it is best hold the related mutex - // lock when calling notifyAll. - void notifyAll() { ConditionPlatformHelper::notifyAll(Handle); } - -private: - ConditionHandle Handle; - -public: - /// A Mutex object that also supports ConditionVariables. - /// - /// This is NOT a recursive mutex. - class Mutex { - - Mutex(const Mutex &) = delete; - Mutex &operator=(const Mutex &) = delete; - Mutex(Mutex &&) = delete; - Mutex &operator=(Mutex &&) = delete; - - public: - /// Constructs a non-recursive mutex. - /// - /// If `checked` is true the mutex will attempt to check for misuse and - /// fatalError when detected. If `checked` is false (the default) the - /// mutex will make little to no effort to check for misuse (more - /// efficient). - explicit Mutex(bool checked = false) { - MutexPlatformHelper::init(Handle, checked); - } - ~Mutex() { MutexPlatformHelper::destroy(Handle); } - - /// The lock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Blocks the calling thread until exclusive ownership of the mutex - /// can be obtained. - /// - Prior m.unlock() operations on the same mutex synchronize-with - /// this lock operation. - /// - The behavior is undefined if the calling thread already owns - /// the mutex (likely a deadlock). - /// - Does not throw exceptions but will halt on error (fatalError). - void lock() { MutexPlatformHelper::lock(Handle); } - - /// The unlock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Releases the calling thread's ownership of the mutex and - /// synchronizes-with the subsequent successful lock operations on - /// the same object. - /// - The behavior is undefined if the calling thread does not own - /// the mutex. - /// - Does not throw exceptions but will halt on error (fatalError). - void unlock() { MutexPlatformHelper::unlock(Handle); } - - /// The try_lock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Attempts to obtain exclusive ownership of the mutex for the calling - /// thread without blocking. If ownership is not obtained, returns - /// immediately. The function is allowed to spuriously fail and return - /// even if the mutex is not currently owned by another thread. - /// - If try_lock() succeeds, prior unlock() operations on the same object - /// synchronize-with this operation. lock() does not synchronize with a - /// failed try_lock() - /// - The behavior is undefined if the calling thread already owns - /// the mutex (likely a deadlock)? - /// - Does not throw exceptions but will halt on error (fatalError). - bool try_lock() { return MutexPlatformHelper::try_lock(Handle); } - - /// Releases lock, waits on supplied condition, and relocks before - /// returning. - /// - /// Precondition: Mutex held by this thread, undefined otherwise. - void wait(ConditionVariable &condition) { - ConditionPlatformHelper::wait(condition.Handle, Handle); - } - - /// Acquires lock before calling the supplied critical section and releases - /// lock on return from critical section. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following mutates value while holding the mutex lock. - /// - /// ``` - /// mutex.lock([&value] { value++; }); - /// ``` - /// - /// Precondition: Mutex not held by this thread, undefined otherwise. - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedLock guard(*this); - return std::forward(criticalSection)(); - } - - /// Acquires lock before calling the supplied critical section. If critical - /// section returns `false` then it will wait on the supplied condition and - /// call the critical section again when wait returns (after acquiring - /// lock). If critical section returns `true` (done) it will no longer wait, - /// it will release the lock and return (lockOrWait returns to caller). - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following will loop waiting on the condition until - /// `value > 0`. It will then "consume" that value and stop looping. - /// ...all while being correctly protected by mutex. - /// - /// ``` - /// mutex.withLockOrWait(condition, [&value] { - /// if (value > 0) { - /// value--; - /// return true; - /// } - /// return false; - /// }); - /// ``` - /// - /// Precondition: Mutex not held by this thread, undefined otherwise. - template - void withLockOrWait(ConditionVariable &condition, - CriticalSection &&criticalSection) { - withLock([&] { - while (!criticalSection()) { - wait(condition); - } - }); - } - - /// Acquires lock before calling the supplied critical section and on return - /// from critical section it notifies one waiter of supplied condition and - /// then releases the lock. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following mutates value while holding the mutex lock and - /// then notifies one condition waiter about this change. - /// - /// ``` - /// mutex.withLockThenNotifyOne(condition, [&value] { value++; }); - /// ``` - /// - /// Precondition: Mutex not held by this thread, undefined otherwise. - template - auto withLockThenNotifyOne(ConditionVariable &condition, - CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - return withLock([&] { - ScopedNotifyOne guard(condition); - return std::forward(criticalSection)(); - }); - } - - /// Acquires lock before calling the supplied critical section and on return - /// from critical section it notifies all waiters of supplied condition and - /// then releases the lock. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following mutates value while holding the mutex lock and - /// then notifies all condition waiters about this change. - /// - /// ``` - /// mutex.withLockThenNotifyAll(condition, [&value] { value++; }); - /// ``` - /// - /// Precondition: Mutex not held by this thread, undefined otherwise. - template - auto withLockThenNotifyAll(ConditionVariable &condition, - CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - return withLock([&] { - ScopedNotifyAll guard(condition); - return std::forward(criticalSection)(); - }); - } - - /// A stack based object that locks the supplied mutex on construction - /// and unlocks it on destruction. - /// - /// Precondition: Mutex unlocked by this thread, undefined otherwise. - typedef ScopedLockT ScopedLock; - - /// A stack based object that unlocks the supplied mutex on construction - /// and relocks it on destruction. - /// - /// Precondition: Mutex locked by this thread, undefined otherwise. - typedef ScopedLockT ScopedUnlock; - - private: - ConditionMutexHandle Handle; - }; - - using ScopedNotifyOne = ScopedNotifyOneT; - using ScopedNotifyAll = ScopedNotifyAllT; -}; - -/// A Mutex object that supports `BasicLockable` and `Lockable` C++ concepts. -/// See http://en.cppreference.com/w/cpp/concept/BasicLockable -/// See http://en.cppreference.com/w/cpp/concept/Lockable -/// -/// This is NOT a recursive mutex. -class Mutex { - - Mutex(const Mutex &) = delete; - Mutex &operator=(const Mutex &) = delete; - Mutex(Mutex &&) = delete; - Mutex &operator=(Mutex &&) = delete; - -public: - /// Constructs a non-recursive mutex. - /// - /// If `checked` is true the mutex will attempt to check for misuse and - /// fatalError when detected. If `checked` is false (the default) the - /// mutex will make little to no effort to check for misuse (more efficient). - explicit Mutex(bool checked = false) { - MutexPlatformHelper::init(Handle, checked); - } - ~Mutex() { MutexPlatformHelper::destroy(Handle); } - - /// The lock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Blocks the calling thread until exclusive ownership of the mutex - /// can be obtained. - /// - Prior m.unlock() operations on the same mutex synchronize-with - /// this lock operation. - /// - The behavior is undefined if the calling thread already owns - /// the mutex (likely a deadlock). - /// - Does not throw exceptions but will halt on error (fatalError). - void lock() { MutexPlatformHelper::lock(Handle); } - - /// The unlock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Releases the calling thread's ownership of the mutex and - /// synchronizes-with the subsequent successful lock operations on - /// the same object. - /// - The behavior is undefined if the calling thread does not own - /// the mutex. - /// - Does not throw exceptions but will halt on error (fatalError). - void unlock() { MutexPlatformHelper::unlock(Handle); } - - /// The try_lock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Attempts to obtain exclusive ownership of the mutex for the calling - /// thread without blocking. If ownership is not obtained, returns - /// immediately. The function is allowed to spuriously fail and return - /// even if the mutex is not currently owned by another thread. - /// - If try_lock() succeeds, prior unlock() operations on the same object - /// synchronize-with this operation. lock() does not synchronize with a - /// failed try_lock() - /// - The behavior is undefined if the calling thread already owns - /// the mutex (likely a deadlock)? - /// - Does not throw exceptions but will halt on error (fatalError). - bool try_lock() { return MutexPlatformHelper::try_lock(Handle); } - - /// Acquires lock before calling the supplied critical section and releases - /// lock on return from critical section. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following mutates value while holding the mutex lock. - /// - /// ``` - /// mutex.lock([&value] { value++; }); - /// ``` - /// - /// Precondition: Mutex not held by this thread, undefined otherwise. - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedLock guard(*this); - return std::forward(criticalSection)(); - } - - /// A stack based object that locks the supplied mutex on construction - /// and unlocks it on destruction. - /// - /// Precondition: Mutex unlocked by this thread, undefined otherwise. - typedef ScopedLockT ScopedLock; - - /// A stack based object that unlocks the supplied mutex on construction - /// and relocks it on destruction. - /// - /// Precondition: Mutex locked by this thread, undefined otherwise. - typedef ScopedLockT ScopedUnlock; - -private: - MutexHandle Handle; -}; - -/// Compile time adjusted stack based object that locks/unlocks the supplied -/// ReadWriteLock type. Use the provided typedefs instead of this directly. -template class ScopedRWLockT { - - ScopedRWLockT() = delete; - ScopedRWLockT(const ScopedRWLockT &) = delete; - ScopedRWLockT &operator=(const ScopedRWLockT &) = delete; - ScopedRWLockT(ScopedRWLockT &&) = delete; - ScopedRWLockT &operator=(ScopedRWLockT &&) = delete; - -public: - explicit ScopedRWLockT(T &l) : Lock(l) { - if (Inverted) { - if (Read) { - Lock.readUnlock(); - } else { - Lock.writeUnlock(); - } - } else { - if (Read) { - Lock.readLock(); - } else { - Lock.writeLock(); - } - } - } - - ~ScopedRWLockT() { - if (Inverted) { - if (Read) { - Lock.readLock(); - } else { - Lock.writeLock(); - } - } else { - if (Read) { - Lock.readUnlock(); - } else { - Lock.writeUnlock(); - } - } - } - -private: - T &Lock; -}; - -class ReadWriteLock; -class StaticReadWriteLock; - -/// A stack based object that unlocks the supplied ReadWriteLock on -/// construction and locks it for reading on destruction. -/// -/// Precondition: ReadWriteLock unlocked by this thread, undefined otherwise. -typedef ScopedRWLockT ScopedReadLock; -typedef ScopedRWLockT StaticScopedReadLock; - -/// A stack based object that unlocks the supplied ReadWriteLock on -/// construction and locks it for reading on destruction. -/// -/// Precondition: ReadWriteLock unlocked by this thread, undefined -/// otherwise. -typedef ScopedRWLockT ScopedReadUnlock; -typedef ScopedRWLockT StaticScopedReadUnlock; - -/// A stack based object that unlocks the supplied ReadWriteLock on -/// construction and locks it for reading on destruction. -/// -/// Precondition: ReadWriteLock unlocked by this thread, undefined otherwise. -typedef ScopedRWLockT ScopedWriteLock; -typedef ScopedRWLockT StaticScopedWriteLock; - -/// A stack based object that unlocks the supplied ReadWriteLock on -/// construction and locks it for writing on destruction. -/// -/// Precondition: ReadWriteLock unlocked by this thread, undefined otherwise. -typedef ScopedRWLockT ScopedWriteUnlock; -typedef ScopedRWLockT StaticScopedWriteUnlock; - -/// A Read / Write lock object that has semantics similar to `BasicLockable` -/// and `Lockable` C++ concepts however it supports multiple concurrent -/// threads holding the reader lock as long as the write lock isn't held and -/// only one thread can hold the write local at the same time. -/// -/// If you need static allocated ReadWriteLock use StaticReadWriteLock. -/// -/// See http://en.cppreference.com/w/cpp/concept/BasicLockable -/// See http://en.cppreference.com/w/cpp/concept/Lockable -/// -/// This is NOT a recursive mutex. -class ReadWriteLock { - - ReadWriteLock(const ReadWriteLock &) = delete; - ReadWriteLock &operator=(const ReadWriteLock &) = delete; - ReadWriteLock(ReadWriteLock &&) = delete; - ReadWriteLock &operator=(ReadWriteLock &&) = delete; - -public: - ReadWriteLock() { ReadWriteLockPlatformHelper::init(Handle); } - ~ReadWriteLock() { ReadWriteLockPlatformHelper::destroy(Handle); } - - /// The readLock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Blocks the calling thread while the write lock is held by another - /// thread and once the read lock is acquired by the calling thread - /// other threads are prevented from acquiring the write lock. - /// - Multiple threads can hold the read lock at the same time. - /// - Prior unlock() operations on the same lock synchronize-with - /// this lock operation. - /// - The behavior is undefined if the calling thread already owns - /// the read or write lock (likely a deadlock). - /// - Does not throw exceptions but will halt on error (fatalError). - /// - /// Callers must not mutate the data protected by the ReadWriteLock while - /// holding the read lock, the write lock must be used. - void readLock() { ReadWriteLockPlatformHelper::readLock(Handle); } - - /// The try_readLock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Attempts to obtain the read lock without blocking the calling thread. - /// If ownership is not obtained, returns immediately. The function is - /// allowed to spuriously fail and return even if the lock is not - /// currently owned by another thread. - /// - If try_readLock() succeeds, prior unlock() operations on the same - /// object synchronize-with this operation. unlock() does not synchronize - /// with a failed try_readLock(). - /// - The behavior is undefined if the calling thread already owns - /// the read or write lock (likely a deadlock)? - /// - Does not throw exceptions but will halt on error (fatalError). - /// - /// Callers must not mutate the data protected by the ReadWriteLock while - /// holding the read lock, the write lock must be used. - bool try_readLock() { - return ReadWriteLockPlatformHelper::try_readLock(Handle); - } - - /// The readUnlock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Releases the calling thread's ownership of the read lock - /// and synchronizes-with the subsequent successful lock operations on - /// the same object. - /// - The behavior is undefined if the calling thread does not own - /// the read lock. - /// - Does not throw exceptions but will halt on error (fatalError). - void readUnlock() { ReadWriteLockPlatformHelper::readUnlock(Handle); } - - /// The writeLock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Blocks the calling thread while the write lock or a read lock is held - /// by another thread and once the write lock is acquired by the calling - /// thread other threads are prevented from acquiring the write lock or a - /// read lock. - /// - Only one thread can hold the write lock at the same time. - /// - Prior unlock() operations on the same lock synchronize-with - /// this lock operation. - /// - The behavior is undefined if the calling thread already owns - /// the read or write lock (likely a deadlock). - /// - Does not throw exceptions but will halt on error (fatalError). - void writeLock() { ReadWriteLockPlatformHelper::writeLock(Handle); } - - /// The try_writeLock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Attempts to obtain the write lock without blocking the calling thread. - /// If ownership is not obtained, returns immediately. The function is - /// allowed to spuriously fail and return even if the lock is not - /// currently owned by another thread. - /// - If try_writeLock() succeeds, prior unlock() operations on the same - /// object synchronize-with this operation. unlock() does not synchronize - /// with a failed try_writeLock(). - /// - The behavior is undefined if the calling thread already owns - /// the read or write lock (likely a deadlock)? - /// - Does not throw exceptions but will halt on error (fatalError). - bool try_writeLock() { - return ReadWriteLockPlatformHelper::try_writeLock(Handle); - } - - /// The writeUnlock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Releases the calling thread's ownership of the write lock - /// and synchronizes-with the subsequent successful lock operations on - /// the same object. - /// - The behavior is undefined if the calling thread does not own - /// the write lock. - /// - Does not throw exceptions but will halt on error (fatalError). - void writeUnlock() { ReadWriteLockPlatformHelper::writeUnlock(Handle); } - - /// Acquires read lock before calling the supplied critical section and - /// releases lock on return from critical section. Callers must not mutate - /// the data protected by the ReadWriteLock while holding the read lock, the - /// write lock must be used. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following reads the cached value while holding - /// the read lock. - /// - /// ``` - /// rw.withReadLock([&value] { value = cachedValue; }); - /// ``` - /// - /// Precondition: ReadWriteLock not held by this thread, undefined otherwise. - template - auto withReadLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedReadLock guard(*this); - return std::forward(criticalSection)(); - } - - /// Acquires write lock before calling the supplied critical section and - /// releases lock on return from critical section. - /// - /// This call can block while waiting for the lock to become available. - /// - /// For example the following updates the cached value while holding - /// the write lock. - /// - /// ``` - /// rw.withWriteLock([&newValue] { cachedValue = newValue }); - /// ``` - /// - /// Precondition: ReadWriteLock not held by this thread, undefined otherwise. - template - auto withWriteLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedWriteLock guard(*this); - return std::forward(criticalSection)(); - } - -private: - ReadWriteLockHandle Handle; -}; - -/// A static allocation variant of ConditionVariable. -/// -/// Use ConditionVariable instead unless you need static allocation. -class StaticConditionVariable { - StaticConditionVariable(const StaticConditionVariable &) = delete; - StaticConditionVariable &operator=(const StaticConditionVariable &) = delete; - StaticConditionVariable(StaticConditionVariable &&) = delete; - StaticConditionVariable &operator=(StaticConditionVariable &&) = delete; - -public: -#if SWIFT_CONDITION_SUPPORTS_CONSTEXPR - constexpr -#endif - StaticConditionVariable() - : Handle(ConditionPlatformHelper::staticInit()) { - } - - /// See ConditionVariable::notifyOne - void notifyOne() { ConditionPlatformHelper::notifyOne(Handle); } - - /// See ConditionVariable::notifyAll - void notifyAll() { ConditionPlatformHelper::notifyAll(Handle); } - - using ScopedNotifyOne = ScopedNotifyOneT; - using ScopedNotifyAll = ScopedNotifyAllT; - - /// A static allocation variant of ConditionVariable::Mutex. - /// - /// Use ConditionVariable::Mutex instead unless you need static allocation. - class StaticMutex { - - StaticMutex(const StaticMutex &) = delete; - StaticMutex &operator=(const StaticMutex &) = delete; - StaticMutex(StaticMutex &&) = delete; - StaticMutex &operator=(StaticMutex &&) = delete; - - public: -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR - constexpr -#endif - StaticMutex() - : Handle(MutexPlatformHelper::conditionStaticInit()) { - } - - /// See Mutex::lock - void lock() { MutexPlatformHelper::lock(Handle); } - - /// See Mutex::unlock - void unlock() { MutexPlatformHelper::unlock(Handle); } - - /// See Mutex::try_lock - bool try_lock() { return MutexPlatformHelper::try_lock(Handle); } - - /// See Mutex::wait - void wait(StaticConditionVariable &condition) { - ConditionPlatformHelper::wait(condition.Handle, Handle); - } - void wait(ConditionVariable &condition) { - ConditionPlatformHelper::wait(condition.Handle, Handle); - } - - /// See Mutex::lock - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedLock guard(*this); - return std::forward(criticalSection)(); - } - - /// See Mutex::withLockOrWait - template - void withLockOrWait(StaticConditionVariable &condition, - CriticalSection &&criticalSection) { - withLock([&] { - while (!criticalSection()) { - wait(condition); - } - }); - } - - /// See Mutex::withLockThenNotifyOne - template - auto withLockThenNotifyOne(StaticConditionVariable &condition, - CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - return withLock([&] { - StaticConditionVariable::ScopedNotifyOne guard(condition); - return std::forward(criticalSection)(); - }); - } - - /// See Mutex::withLockThenNotifyAll - template - auto withLockThenNotifyAll(StaticConditionVariable &condition, - CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - return withLock([&] { - StaticConditionVariable::ScopedNotifyAll guard(condition); - return std::forward(criticalSection)(); - }); - } - - /// A stack based object that locks the supplied mutex on construction - /// and unlocks it on destruction. - /// - /// Precondition: Mutex unlocked by this thread, undefined otherwise. - typedef ScopedLockT ScopedLock; - - /// A stack based object that unlocks the supplied mutex on construction - /// and relocks it on destruction. - /// - /// Precondition: Mutex locked by this thread, undefined otherwise. - typedef ScopedLockT ScopedUnlock; - - private: - ConditionMutexHandle Handle; - }; - -private: - ConditionHandle Handle; -}; - -/// A static allocation variant of Mutex. -/// -/// Use Mutex instead unless you need static allocation. -class StaticMutex { - - StaticMutex(const StaticMutex &) = delete; - StaticMutex &operator=(const StaticMutex &) = delete; - StaticMutex(StaticMutex &&) = delete; - StaticMutex &operator=(StaticMutex &&) = delete; - -public: -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR - constexpr -#endif - StaticMutex() - : Handle(MutexPlatformHelper::staticInit()) { - } - - /// See Mutex::lock - void lock() { MutexPlatformHelper::lock(Handle); } - - /// See Mutex::unlock - void unlock() { MutexPlatformHelper::unlock(Handle); } - - /// See Mutex::try_lock - bool try_lock() { return MutexPlatformHelper::try_lock(Handle); } - - /// See Mutex::lock - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedLock guard(*this); - return std::forward(criticalSection)(); - } - - /// A stack based object that locks the supplied mutex on construction - /// and unlocks it on destruction. - /// - /// Precondition: Mutex unlocked by this thread, undefined otherwise. - typedef ScopedLockT ScopedLock; - - /// A stack based object that unlocks the supplied mutex on construction - /// and relocks it on destruction. - /// - /// Precondition: Mutex locked by this thread, undefined otherwise. - typedef ScopedLockT ScopedUnlock; - -private: - MutexHandle Handle; -}; - -/// A static allocation variant of ReadWriteLock. -/// -/// Use ReadWriteLock instead unless you need static allocation. -class StaticReadWriteLock { - - StaticReadWriteLock(const StaticReadWriteLock &) = delete; - StaticReadWriteLock &operator=(const StaticReadWriteLock &) = delete; - StaticReadWriteLock(StaticReadWriteLock &&) = delete; - StaticReadWriteLock &operator=(StaticReadWriteLock &&) = delete; - -public: -#if SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR - constexpr -#endif - StaticReadWriteLock() - : Handle(ReadWriteLockPlatformHelper::staticInit()) { - } - - /// See ReadWriteLock::readLock - void readLock() { ReadWriteLockPlatformHelper::readLock(Handle); } - - /// See ReadWriteLock::try_readLock - bool try_readLock() { - return ReadWriteLockPlatformHelper::try_readLock(Handle); - } - - /// See ReadWriteLock::readUnlock - void readUnlock() { ReadWriteLockPlatformHelper::readUnlock(Handle); } - - /// See ReadWriteLock::writeLock - void writeLock() { ReadWriteLockPlatformHelper::writeLock(Handle); } - - /// See ReadWriteLock::try_writeLock - bool try_writeLock() { - return ReadWriteLockPlatformHelper::try_writeLock(Handle); - } - - /// See ReadWriteLock::writeUnlock - void writeUnlock() { ReadWriteLockPlatformHelper::writeUnlock(Handle); } - - /// See ReadWriteLock::withReadLock - template - auto withReadLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - StaticScopedReadLock guard(*this); - return std::forward(criticalSection)(); - } - - /// See ReadWriteLock::withWriteLock - template - auto withWriteLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - StaticScopedWriteLock guard(*this); - return std::forward(criticalSection)(); - } - -private: - ReadWriteLockHandle Handle; -}; - -/// A Mutex object that supports `BasicLockable` C++ concepts. It is -/// considered -/// unsafe to use because it doesn't do any error checking. It is only for -/// use in pathways that deal with reporting fatalErrors to avoid the -/// potential -/// for recursive fatalErrors that could happen if you used Mutex. -/// -/// Always use Mutex, unless in the above mentioned error pathway situation. -class StaticUnsafeMutex { - - StaticUnsafeMutex(const StaticUnsafeMutex &) = delete; - StaticUnsafeMutex &operator=(const StaticUnsafeMutex &) = delete; - StaticUnsafeMutex(StaticUnsafeMutex &&) = delete; - StaticUnsafeMutex &operator=(StaticUnsafeMutex &&) = delete; - -public: -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR - constexpr -#endif - StaticUnsafeMutex() - : Handle(MutexPlatformHelper::staticInit()) { - } - - /// The lock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Blocks the calling thread until exclusive ownership of the mutex - /// can be obtained. - /// - Prior m.unlock() operations on the same mutex synchronize-with - /// this lock operation. - /// - The behavior is undefined if the calling thread already owns - /// the mutex (likely a deadlock). - /// - Ignores errors that may happen, undefined when an error happens. - void lock() { MutexPlatformHelper::unsafeLock(Handle); } - - /// The unlock() method has the following properties: - /// - Behaves as an atomic operation. - /// - Releases the calling thread's ownership of the mutex and - /// synchronizes-with the subsequent successful lock operations on - /// the same object. - /// - The behavior is undefined if the calling thread does not own - /// the mutex. - /// - Ignores errors that may happen, undefined when an error happens. - void unlock() { MutexPlatformHelper::unsafeUnlock(Handle); } - - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(std::forward(criticalSection)()) { - ScopedLock guard(*this); - return std::forward(criticalSection)(); - } - - typedef ScopedLockT ScopedLock; - typedef ScopedLockT ScopedUnlock; - -private: - MutexHandle Handle; -}; - -/// An indirect variant of a Mutex. This allocates the mutex on the heap, for -/// places where having the mutex inline takes up too much space. Used for -/// SmallMutex on platforms where Mutex is large. -class IndirectMutex { - IndirectMutex(const IndirectMutex &) = delete; - IndirectMutex &operator=(const IndirectMutex &) = delete; - IndirectMutex(IndirectMutex &&) = delete; - IndirectMutex &operator=(IndirectMutex &&) = delete; - -public: - explicit IndirectMutex(bool checked = false) { Ptr = new Mutex(checked); } - ~IndirectMutex() { delete Ptr; } - - void lock() { Ptr->lock(); } - - void unlock() { Ptr->unlock(); } - - bool try_lock() { return Ptr->try_lock(); } - - template - auto withLock(CriticalSection &&criticalSection) - -> decltype(criticalSection()) { - return Ptr->withLock(std::forward(criticalSection)); - } - - /// A stack based object that locks the supplied mutex on construction - /// and unlocks it on destruction. - /// - /// Precondition: Mutex unlocked by this thread, undefined otherwise. - typedef ScopedLockT ScopedLock; - - /// A stack based object that unlocks the supplied mutex on construction - /// and relocks it on destruction. - /// - /// Precondition: Mutex locked by this thread, undefined otherwise. - typedef ScopedLockT ScopedUnlock; - -private: - Mutex *Ptr; -}; - -/// A "small" mutex, which is pointer sized or smaller, for places where the -/// mutex is stored inline with limited storage space. This uses a normal Mutex -/// when that is small, and otherwise uses IndirectMutex. -using SmallMutex = - std::conditional_t; - -// Enforce literal requirements for static variants. -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR -static_assert(std::is_literal_type::value, - "StaticMutex must be literal type"); -static_assert(std::is_literal_type::value, - "StaticUnsafeMutex must be literal type"); -#else -// Your platform doesn't currently support statically allocated Mutex -// you will possibly see global-constructors warnings -#endif - -#if SWIFT_CONDITION_SUPPORTS_CONSTEXPR -static_assert(std::is_literal_type::value, - "StaticConditionVariable must be literal type"); -#else -// Your platform doesn't currently support statically allocated ConditionVar -// you will possibly see global-constructors warnings -#endif - -#if SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR -static_assert(std::is_literal_type::value, - "StaticReadWriteLock must be literal type"); -#else -// Your platform doesn't currently support statically allocated ReadWriteLocks -// you will possibly see global-constructors warnings -#endif -} - -#endif // SWIFT_RUNTIME_MUTEX_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexPThread.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexPThread.h deleted file mode 100644 index d4f3c97c5f751..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexPThread.h +++ /dev/null @@ -1,157 +0,0 @@ -//===--- MutexPThread.h - Supports Mutex.h using PThreads -------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Mutex, ConditionVariable, Read/Write lock, and Scoped lock implementations -// using PThreads. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H -#define SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H - -#include - -#if defined(__APPLE__) && defined(__MACH__) -#include -#define HAS_OS_UNFAIR_LOCK 1 -#endif - -namespace swift { - -typedef pthread_cond_t ConditionHandle; -typedef pthread_mutex_t ConditionMutexHandle; -typedef pthread_rwlock_t ReadWriteLockHandle; - -#if HAS_OS_UNFAIR_LOCK -typedef os_unfair_lock MutexHandle; -#else -typedef pthread_mutex_t MutexHandle; -#endif - -#if defined(__CYGWIN__) || defined(__HAIKU__) || defined(__wasi__) -// At the moment CYGWIN pthreads implementation doesn't support the use of -// constexpr for static allocation versions. The way they define things -// results in a reinterpret_cast which violates constexpr. -// WASI currently doesn't support threading/locking at all. -#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 0 -#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 0 -#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 0 -#else -#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1 -#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1 -#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1 -#endif - -/// PThread low-level implementation that supports ConditionVariable -/// found in Mutex.h -/// -/// See ConditionVariable -struct ConditionPlatformHelper { -#if SWIFT_CONDITION_SUPPORTS_CONSTEXPR - static constexpr -#else - static -#endif - ConditionHandle - staticInit() { - return PTHREAD_COND_INITIALIZER; - }; - static void init(ConditionHandle &condition); - static void destroy(ConditionHandle &condition); - static void notifyOne(ConditionHandle &condition); - static void notifyAll(ConditionHandle &condition); - static void wait(ConditionHandle &condition, ConditionMutexHandle &mutex); -}; - -/// PThread low-level implementation that supports Mutex -/// found in Mutex.h -/// -/// See Mutex -struct MutexPlatformHelper { -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR - static constexpr -#else - static -#endif - ConditionMutexHandle - conditionStaticInit() { - return PTHREAD_MUTEX_INITIALIZER; - }; -#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR - static constexpr -#else - static -#endif - MutexHandle - staticInit() { -#if HAS_OS_UNFAIR_LOCK - return OS_UNFAIR_LOCK_INIT; -#else - return PTHREAD_MUTEX_INITIALIZER; -#endif - } - static void init(ConditionMutexHandle &mutex, bool checked = false); - static void destroy(ConditionMutexHandle &mutex); - static void lock(ConditionMutexHandle &mutex); - static void unlock(ConditionMutexHandle &mutex); - static bool try_lock(ConditionMutexHandle &mutex); - - // The ConditionMutexHandle versions handle everything on-Apple platforms. -#if HAS_OS_UNFAIR_LOCK - - static void init(MutexHandle &mutex, bool checked = false); - static void destroy(MutexHandle &mutex); - static void lock(MutexHandle &mutex); - static void unlock(MutexHandle &mutex); - static bool try_lock(MutexHandle &mutex); - - // os_unfair_lock always checks for errors, so just call through. - static void unsafeLock(MutexHandle &mutex) { lock(mutex); } - static void unsafeUnlock(MutexHandle &mutex) { unlock(mutex); } -#endif - - // The unsafe versions don't do error checking. - static void unsafeLock(ConditionMutexHandle &mutex) { - (void)pthread_mutex_lock(&mutex); - } - static void unsafeUnlock(ConditionMutexHandle &mutex) { - (void)pthread_mutex_unlock(&mutex); - } -}; - -/// PThread low-level implementation that supports ReadWriteLock -/// found in Mutex.h -/// -/// See ReadWriteLock -struct ReadWriteLockPlatformHelper { -#if SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR - static constexpr -#else - static -#endif - ReadWriteLockHandle - staticInit() { - return PTHREAD_RWLOCK_INITIALIZER; - }; - - static void init(ReadWriteLockHandle &rwlock); - static void destroy(ReadWriteLockHandle &rwlock); - static void readLock(ReadWriteLockHandle &rwlock); - static bool try_readLock(ReadWriteLockHandle &rwlock); - static void readUnlock(ReadWriteLockHandle &rwlock); - static void writeLock(ReadWriteLockHandle &rwlock); - static bool try_writeLock(ReadWriteLockHandle &rwlock); - static void writeUnlock(ReadWriteLockHandle &rwlock); -}; -} - -#endif // SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexSingleThreaded.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexSingleThreaded.h deleted file mode 100644 index 44c53beee8f8c..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexSingleThreaded.h +++ /dev/null @@ -1,74 +0,0 @@ -//===--- MutexSingleThreaded.h - --------------------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// No-op implementation of locks for single-threaded environments. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H -#define SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H - -#include -#include "swift/Runtime/Debug.h" - -namespace swift { - -typedef void* ConditionHandle; -typedef void* ConditionMutexHandle; -typedef void* MutexHandle; -typedef void* ReadWriteLockHandle; - -#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1 -#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1 -#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1 - -struct ConditionPlatformHelper { - static constexpr ConditionHandle staticInit() { - return nullptr; - }; - static void init(ConditionHandle &condition) {} - static void destroy(ConditionHandle &condition) {} - static void notifyOne(ConditionHandle &condition) {} - static void notifyAll(ConditionHandle &condition) {} - static void wait(ConditionHandle &condition, MutexHandle &mutex) { - fatalError(0, "single-threaded runtime cannot wait for condition"); - } -}; - -struct MutexPlatformHelper { - static constexpr MutexHandle staticInit() { return nullptr; } - static constexpr ConditionMutexHandle conditionStaticInit() { - return nullptr; - } - static void init(MutexHandle &mutex, bool checked = false) {} - static void destroy(MutexHandle &mutex) {} - static void lock(MutexHandle &mutex) {} - static void unlock(MutexHandle &mutex) {} - static bool try_lock(MutexHandle &mutex) { return true; } - static void unsafeLock(MutexHandle &mutex) {} - static void unsafeUnlock(MutexHandle &mutex) {} -}; - -struct ReadWriteLockPlatformHelper { - static constexpr ReadWriteLockHandle staticInit() { return nullptr; } - static void init(ReadWriteLockHandle &rwlock) {} - static void destroy(ReadWriteLockHandle &rwlock) {} - static void readLock(ReadWriteLockHandle &rwlock) {} - static bool try_readLock(ReadWriteLockHandle &rwlock) { return true; } - static void readUnlock(ReadWriteLockHandle &rwlock) {} - static void writeLock(ReadWriteLockHandle &rwlock) {} - static bool try_writeLock(ReadWriteLockHandle &rwlock) { return true; } - static void writeUnlock(ReadWriteLockHandle &rwlock) {} -}; -} - -#endif // SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexWin32.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexWin32.h deleted file mode 100644 index e41cbef7d5f96..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/MutexWin32.h +++ /dev/null @@ -1,101 +0,0 @@ -//===--- MutexWin32.h - -----------------------------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Mutex, ConditionVariable, Read/Write lock, and Scoped lock implementations -// using Windows Slim Reader/Writer Locks and Conditional Variables. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H -#define SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include - -namespace swift { - -typedef CONDITION_VARIABLE ConditionHandle; -typedef SRWLOCK ConditionMutexHandle; -typedef SRWLOCK MutexHandle; -typedef SRWLOCK ReadWriteLockHandle; - -#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1 -#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1 -#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1 - -struct ConditionPlatformHelper { - static constexpr ConditionHandle staticInit() { - return CONDITION_VARIABLE_INIT; - }; - static void init(ConditionHandle &condition) { - InitializeConditionVariable(&condition); - } - static void destroy(ConditionHandle &condition) {} - static void notifyOne(ConditionHandle &condition) { - WakeConditionVariable(&condition); - } - static void notifyAll(ConditionHandle &condition) { - WakeAllConditionVariable(&condition); - } - static void wait(ConditionHandle &condition, MutexHandle &mutex); -}; - -struct MutexPlatformHelper { - static constexpr MutexHandle staticInit() { return SRWLOCK_INIT; } - static constexpr ConditionMutexHandle conditionStaticInit() { - return SRWLOCK_INIT; - } - static void init(MutexHandle &mutex, bool checked = false) { - InitializeSRWLock(&mutex); - } - static void destroy(MutexHandle &mutex) {} - static void lock(MutexHandle &mutex) { AcquireSRWLockExclusive(&mutex); } - static void unlock(MutexHandle &mutex) { ReleaseSRWLockExclusive(&mutex); } - static bool try_lock(MutexHandle &mutex) { - return TryAcquireSRWLockExclusive(&mutex) != 0; - } - // The unsafe versions don't do error checking. - static void unsafeLock(MutexHandle &mutex) { - AcquireSRWLockExclusive(&mutex); - } - static void unsafeUnlock(MutexHandle &mutex) { - ReleaseSRWLockExclusive(&mutex); - } -}; - -struct ReadWriteLockPlatformHelper { - static constexpr ReadWriteLockHandle staticInit() { return SRWLOCK_INIT; } - static void init(ReadWriteLockHandle &rwlock) { InitializeSRWLock(&rwlock); } - static void destroy(ReadWriteLockHandle &rwlock) {} - static void readLock(ReadWriteLockHandle &rwlock) { - AcquireSRWLockShared(&rwlock); - } - static bool try_readLock(ReadWriteLockHandle &rwlock) { - return TryAcquireSRWLockShared(&rwlock) != 0; - } - static void readUnlock(ReadWriteLockHandle &rwlock) { - ReleaseSRWLockShared(&rwlock); - } - static void writeLock(ReadWriteLockHandle &rwlock) { - AcquireSRWLockExclusive(&rwlock); - } - static bool try_writeLock(ReadWriteLockHandle &rwlock) { - return TryAcquireSRWLockExclusive(&rwlock) != 0; - } - static void writeUnlock(ReadWriteLockHandle &rwlock) { - ReleaseSRWLockExclusive(&rwlock); - } -}; -} - -#endif // SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Once.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Once.h deleted file mode 100644 index 336eae735eade..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/Once.h +++ /dev/null @@ -1,54 +0,0 @@ -//===--- Once.h - Runtime support for lazy initialization -------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Swift runtime functions in support of lazy initialization. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H -#define SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H - -#include "swift/Runtime/HeapObject.h" -#include - -namespace swift { - -#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME - -typedef bool swift_once_t; - -#elif defined(__APPLE__) - -// On OS X and iOS, swift_once_t matches dispatch_once_t. -typedef long swift_once_t; - -#elif defined(__CYGWIN__) - -// On Cygwin, std::once_flag can not be used because it is larger than the -// platform word. -typedef uintptr_t swift_once_t; -#else - -// On other platforms swift_once_t is std::once_flag -typedef std::once_flag swift_once_t; - -#endif - -/// Runs the given function with the given context argument exactly once. -/// The predicate argument must point to a global or static variable of static -/// extent of type swift_once_t. -SWIFT_RUNTIME_EXPORT -void swift_once(swift_once_t *predicate, void (*fn)(void *), void *context); - -} - -#endif // SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocal.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocal.h deleted file mode 100644 index f1f10927b8cda..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocal.h +++ /dev/null @@ -1,176 +0,0 @@ -//===--- ThreadLocal.h - Thread-local storage -------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// Declarations and macros for working with thread-local storage in the -// Swift runtime. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H -#define SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H - -#include -#include "ThreadLocalStorage.h" - -/// SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL - Does the current configuration -/// allow the use of SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL? -#if defined(__APPLE__) -// The pthread TLS APIs work better than C++ TLS on Apple platforms. -#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0 -#elif defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) -// We define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL to nothing in this -// configuration and just use a global variable, so this is okay. -#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1 -#elif __has_feature(tls) -// If __has_feature reports that TLS is available, use it. -#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1 -#elif !defined(__clang__) -// If we're not using Clang, assume that __has_feature is unreliable -// and that we can safely use TLS. -#else -// Otherwise we can't use TLS and have to fall back on something else. -#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0 -#endif - -/// SWIFT_RUNTIME_THREAD_LOCAL - Declare that something is a -/// thread-local variable in the runtime. -#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) -// In a single-threaded runtime, thread-locals are global. -#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL -#elif defined(__GNUC__) -// In GCC-compatible compilers, we prefer __thread because it's understood -// to guarantee a constant initializer, which permits more efficient access -// patterns. -#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL __thread -#else -// Otherwise, just fall back on the standard C++ feature. -#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL thread_local -#endif - -// Implementation of SWIFT_RUNTIME_DECLARE_THREAD_LOCAL -#if !SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL -#include -#include -#endif - -namespace swift { -// Validate a type stored in thread-local storage, using static asserts. Such -// types must fit in a pointer and be trivially copyable/destructible. -#define VALIDATE_THREAD_LOCAL_TYPE(T) \ - static_assert(sizeof(T) <= sizeof(void *), \ - "cannot store more than a pointer"); \ - static_assert(std::is_trivially_copyable::value, \ - "ThreadLocal values must be trivially copyable"); \ - static_assert(std::is_trivially_destructible::value, \ - "ThreadLocal cleanup is not supported, stored types must be " \ - "trivially destructible"); - -// A wrapper class for thread-local storage. -// -// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL -// above, an object of this type is declared with -// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL. This makes the object -// itself thread-local, and no internal support is required. -// -// Note that this includes platforms that set -// SWIFT_STDLIB_SINGLE_THREADED_RUNTIME, for which -// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL is empty; -// thread-local declarations then create an ordinary global. -// -// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL, -// we have to simulate thread-local storage. Fortunately, all of -// these platforms (at least for now) support pthread_getspecific. -#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL -template -class ThreadLocal { - VALIDATE_THREAD_LOCAL_TYPE(T) - - T value; - -public: - constexpr ThreadLocal() {} - - T get() { return value; } - - void set(T newValue) { value = newValue; } -}; -#else -// A wrapper around a pthread_key_t that is lazily initialized using -// dispatch_once. -class ThreadLocalKey { - // We rely on the zero-initialization of objects with static storage - // duration. - dispatch_once_t once; - pthread_key_t key; - -public: - pthread_key_t getKey() { - dispatch_once_f(&once, &key, [](void *ctx) { - pthread_key_create(reinterpret_cast(ctx), nullptr); - }); - return key; - } -}; - -// A type representing a constant pthread_key_t, for use on platforms that -// provide reserved keys. -template -class ConstantThreadLocalKey { -public: - pthread_key_t getKey() { return constantKey; } -}; - -template -class ThreadLocal { - VALIDATE_THREAD_LOCAL_TYPE(T) - - Key key; - -public: - constexpr ThreadLocal() {} - - T get() { - void *storedValue = SWIFT_THREAD_GETSPECIFIC(key.getKey()); - T value; - memcpy(&value, &storedValue, sizeof(T)); - return value; - } - - void set(T newValue) { - void *storedValue; - memcpy(&storedValue, &newValue, sizeof(T)); - SWIFT_THREAD_SETSPECIFIC(key.getKey(), storedValue); - } -}; -#endif - -} // end namespace swift - -/// SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) - Declare a variable -/// to be a thread-local variable. The declaration must have static -/// storage duration; it may be prefixed with "static". -/// -/// Because of the fallback path, the default-initialization of the -/// type must be equivalent to a bitwise zero-initialization, and the -/// type must be small and trivially copyable and destructible. -#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL -#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \ - SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL swift::ThreadLocal NAME -#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC -#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \ - swift::ThreadLocal> NAME -#else -#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \ - swift::ThreadLocal NAME -#endif - -#endif // SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H diff --git a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocalStorage.h b/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocalStorage.h deleted file mode 100644 index 88c8b90e01bd3..0000000000000 --- a/stdlib/toolchain/Compatibility56/include/Runtime/Threading/ThreadLocalStorage.h +++ /dev/null @@ -1,128 +0,0 @@ -//===--- ThreadLocalStorage.h - Thread-local storage interface. --*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2018 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 -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H -#define SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H - -#include "swift/Runtime/Config.h" - -// Depending on the target, we may be able to use dedicated TSD keys or -// thread_local variables. When dedicated TSD keys aren't available, -// wrap the target's API for thread-local data for things that don't want -// to use thread_local. - -// On Apple platforms, we have dedicated TSD keys. -#if defined(__APPLE__) -# define SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC 1 -#endif - -#if SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC -// Use reserved TSD keys. -# if __has_include() -# include -# else -// We still need to use the SPI for setting the destructor, so declare it here. -extern "C" int pthread_key_init_np(int key, void (*destructor)(void *)); -# endif - -// If the keys are not available from the header, define them ourselves. The values match -// what tsd_private.h provides. -# ifndef __PTK_FRAMEWORK_SWIFT_KEY0 -# define __PTK_FRAMEWORK_SWIFT_KEY0 100 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY1 -# define __PTK_FRAMEWORK_SWIFT_KEY1 101 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY2 -# define __PTK_FRAMEWORK_SWIFT_KEY2 102 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY3 -# define __PTK_FRAMEWORK_SWIFT_KEY3 103 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY4 -# define __PTK_FRAMEWORK_SWIFT_KEY4 104 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY5 -# define __PTK_FRAMEWORK_SWIFT_KEY5 105 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY6 -# define __PTK_FRAMEWORK_SWIFT_KEY6 106 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY7 -# define __PTK_FRAMEWORK_SWIFT_KEY7 107 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY8 -# define __PTK_FRAMEWORK_SWIFT_KEY8 108 -# endif -# ifndef __PTK_FRAMEWORK_SWIFT_KEY9 -# define __PTK_FRAMEWORK_SWIFT_KEY9 109 -# endif - - -# define SWIFT_RUNTIME_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY0 -# define SWIFT_STDLIB_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY1 -# define SWIFT_COMPATIBILITY_50_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY2 -# define SWIFT_CONCURRENCY_TASK_KEY __PTK_FRAMEWORK_SWIFT_KEY3 -# define SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY __PTK_FRAMEWORK_SWIFT_KEY4 -# define SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY \ - __PTK_FRAMEWORK_SWIFT_KEY5 - -#endif - -// If the reserved key path didn't already provide get/setspecific macros, -// wrap the platform's APIs. -#ifndef SWIFT_THREAD_GETSPECIFIC - -// Pick the right typedef for the key. -# if defined(__linux__) -# if defined(__ANDROID__) -typedef int __swift_thread_key_t; -# else -typedef unsigned int __swift_thread_key_t; -# endif -# elif defined(__FreeBSD__) -typedef int __swift_thread_key_t; -# elif defined(__OpenBSD__) -typedef int __swift_thread_key_t; -# elif defined(_WIN32) -typedef unsigned long __swift_thread_key_t; -# elif defined(__HAIKU__) -typedef int __swift_thread_key_t; -# else -typedef unsigned long __swift_thread_key_t; -# endif - -# if defined(_WIN32) && !defined(__CYGWIN__) -// Windows has its own flavor of API. -# include -# define WIN32_LEAN_AND_MEAN -# include - -#include - -static_assert(std::is_same<__swift_thread_key_t, DWORD>::value, - "__swift_thread_key_t is not a DWORD"); - -# define SWIFT_THREAD_KEY_CREATE _stdlib_thread_key_create -# define SWIFT_THREAD_GETSPECIFIC FlsGetValue -# define SWIFT_THREAD_SETSPECIFIC(key, value) (FlsSetValue(key, value) == FALSE) - -# elif !defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) -// Otherwise use the pthread API. -# include -# define SWIFT_THREAD_KEY_CREATE pthread_key_create -# define SWIFT_THREAD_GETSPECIFIC pthread_getspecific -# define SWIFT_THREAD_SETSPECIFIC pthread_setspecific -# endif -#endif - -#endif // SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H diff --git a/test/Concurrency/Backdeploy/weak_linking.swift b/test/Concurrency/Backdeploy/weak_linking.swift index 886668036bd8c..ae074486eb793 100644 --- a/test/Concurrency/Backdeploy/weak_linking.swift +++ b/test/Concurrency/Backdeploy/weak_linking.swift @@ -1,14 +1,8 @@ // RUN: %empty-directory(%t) - -// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx13.0 -module-name main -emit-ir -o %t/new.ir +// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx12.0 -module-name main -emit-ir -o %t/new.ir // RUN: %FileCheck %s --check-prefix=NEW < %t/new.ir - -// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx12.0 -module-name main -emit-ir -o %t/backdeploy_56.ir -// RUN: %FileCheck %s --check-prefix=BACKDEPLOY56 < %t/backdeploy_56.ir - -// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -module-name main -emit-ir -o %t/backdeployed_concurrency.ir -disable-availability-checking -// RUN: %FileCheck %s --check-prefixes=BACKDEPLOY_CONCURRENCY,BACKDEPLOY56 < %t/backdeployed_concurrency.ir - +// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -module-name main -emit-ir -o %t/old.ir -disable-availability-checking +// RUN: %FileCheck %s --check-prefix=OLD < %t/old.ir // RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -O -module-name main -emit-ir -o %t/optimized.ir -disable-availability-checking // RUN: %FileCheck %s --check-prefix=OPTIMIZED < %t/optimized.ir @@ -16,15 +10,10 @@ // REQUIRES: OS=macosx // NEW-NOT: extern_weak - -// BACKDEPLOY_CONCURRENCY: @"$sScPMn" = extern_weak global -// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc i8* @swift_task_alloc -// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc %swift.metadata_response @"$sScPMa" - -// BACKDEPLOY_CONCURRENCY: declare extern_weak void @"_swift_FORCE_LOAD_$_swiftCompatibilityConcurrency"() -// BACKDEPLOY56: declare extern_weak void @"_swift_FORCE_LOAD_$_swiftCompatibility56"() - -// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc i8 @"$sScP8rawValues5UInt8Vvg" +// OLD: @"$sScPMn" = extern_weak global +// OLD: declare extern_weak swiftcc i8* @swift_task_alloc +// OLD: declare extern_weak swiftcc %swift.metadata_response @"$sScPMa" +// OLD: declare extern_weak swiftcc i8 @"$sScP8rawValues5UInt8Vvg" // OPTIMIZED: @swift_async_extendedFramePointerFlags = extern_weak global i8* // OPTIMIZED: @_swift_async_extendedFramePointerFlagsUser = linkonce_odr hidden global i8** @swift_async_extendedFramePointerFlags diff --git a/test/Concurrency/global_actor_inference.swift b/test/Concurrency/global_actor_inference.swift index b2e4058345208..9fbe0dc0dfc11 100644 --- a/test/Concurrency/global_actor_inference.swift +++ b/test/Concurrency/global_actor_inference.swift @@ -457,51 +457,7 @@ func testInferredFromWrapper(x: InferredFromPropertyWrapper) { // expected-note{ _ = x.test() // expected-error{{call to global actor 'SomeGlobalActor'-isolated instance method 'test()' in a synchronous nonisolated context}} } -// https://github.com/apple/swift/issues/59380 -// https://github.com/apple/swift/issues/59494 -// Make sure the nonisolated attribute propagates to the synthesized projectedValue -// variable as well. - -@propertyWrapper -struct SimplePropertyWrapper { - var wrappedValue: Int { .zero } - var projectedValue: Int { .max } -} - -@MainActor -class HasNonIsolatedProperty { - @SimplePropertyWrapper nonisolated var value - - deinit { - _ = value - _ = $value // Ok - } -} - -@propertyWrapper -struct SimplePropertyWrapper2 { - var wrappedValue: Int - var projectedValue: SimplePropertyWrapper2 { self } -} - -@MainActor -class HasNonIsolatedProperty2 { - @SimplePropertyWrapper2 nonisolated var value = 0 - nonisolated init() {} -} - -let hasNonIsolatedProperty2 = HasNonIsolatedProperty2() - -Task { @MainActor in - hasNonIsolatedProperty2.value = 10 - _ = hasNonIsolatedProperty2.$value.wrappedValue -} - -Task.detached { - hasNonIsolatedProperty2.value = 10 - _ = hasNonIsolatedProperty2.$value.wrappedValue // Ok -} // ---------------------------------------------------------------------- // Unsafe global actors diff --git a/test/Generics/member_type_of_superclass_bound.swift b/test/Generics/member_type_of_superclass_bound.swift index 3d482dd5a8d4d..1310c522c8a10 100644 --- a/test/Generics/member_type_of_superclass_bound.swift +++ b/test/Generics/member_type_of_superclass_bound.swift @@ -6,7 +6,7 @@ // // The latter generic signature does not have a conformance requirement T : P, // but the superclass bound C of T conforms to P concretely; make sure that -// the requirement machine's getCanonicalTypeInContext() can handle this. +// the requirement machine's getReducedType() can handle this. public protocol P { associatedtype T } diff --git a/test/IRGen/ptrauth-global.swift b/test/IRGen/ptrauth-global.swift new file mode 100644 index 0000000000000..bf7e3ce05645f --- /dev/null +++ b/test/IRGen/ptrauth-global.swift @@ -0,0 +1,43 @@ +// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 -primary-file %s -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK +// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 %s -primary-file %S/Inputs/ptrauth-global-2.swift -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK2 + +// REQUIRES: CPU=arm64e +// REQUIRES: OS=ios + +// Make sure that the key at the definition of the global matches call sites. + +// CHECK-DAG: @"$s1A9ContainerV3AllAA1GVySiGycAA1VVySiGcycvpZ" = global %swift.function { {{.*}} @"$s1A9ContainerV3AllAA1GVySiGycAA1VVySiGcycvpZfiAGycAJcycfU_.ptrauth" +// CHECK-DAG: @"$s1A9ContainerV3AllAA1GVySiGycAA1VVySiGcycvpZfiAGycAJcycfU_.ptrauth" = {{.*}} @"$s1A9ContainerV3AllAA1GVySiGycAA1VVySiGcycvpZfiAGycAJcycfU_" {{.*}} i64 58141 }, section "llvm.ptrauth" + + + +// CHECK2: define {{.*}}swiftcc void @"$s1A4testyyF"() +// CHECK2: [[T:%.*]] = call swiftcc i8* @"$s1A9ContainerV3AllAA1GVySiGycAA1VVySiGcycvau"() +// CHECK2: [[T2:%.*]] = bitcast i8* [[T]] to %swift.function* +// CHECK2: [[T3:%.*]] = getelementptr inbounds %swift.function, %swift.function* [[T2]], i32 0, i32 0 +// CHECK2: [[T4:%.*]] = load i8*, i8** [[T3]] +// CHECK2: [[T5:%.*]] = bitcast i8* [[T4]] to { i8*, %swift.refcounted* } (%swift.refcounted*)* +// CHECK2: call swiftcc { i8*, %swift.refcounted* } [[T5]]({{.*}}) [ "ptrauth"(i32 0, i64 58141) ] + +public struct G { + init(_ t: T) {} +} + +public struct V { + var str: String = "" + var str1: String = "" + var str2: String = "" + var str3: String = "" + var str4: String = "" + var str5: String = "" + var str6: String = "" + var str7: String = "" + var str8: String = "" + init(_ t: T) {} +} + +// Because of the large parameter type the signature gets transformed by the +// large loadable pass. The types in the global initializer need to follow. +public struct Container { + public static let All = { return { (_ v: V) in { return G(5) } } } +} diff --git a/test/Interop/SwiftToCxx/class/swift-class-execution.cpp b/test/Interop/SwiftToCxx/class/swift-class-execution.cpp index 70279a8ab6a12..f027688ab5644 100644 --- a/test/Interop/SwiftToCxx/class/swift-class-execution.cpp +++ b/test/Interop/SwiftToCxx/class/swift-class-execution.cpp @@ -8,6 +8,16 @@ // RUN: %target-codesign %t/swift-class-execution // RUN: %target-run %t/swift-class-execution | %FileCheck %s +// RUN: %empty-directory(%t-evo) + +// RUN: %target-swift-frontend %S/swift-class-in-cxx.swift -typecheck -module-name Class -clang-header-expose-public-decls -enable-library-evolution -emit-clang-header-path %t-evo/class.h + +// RUN: %target-interop-build-clangxx -c %s -I %t-evo -o %t-evo/swift-class-execution.o +// RUN: %target-interop-build-swift %S/swift-class-in-cxx.swift -o %t-evo/swift-class-execution-evo -Xlinker %t-evo/swift-class-execution.o -module-name Class -enable-library-evolution -Xfrontend -entry-point-function-name -Xfrontend swiftMain + +// RUN: %target-codesign %t-evo/swift-class-execution-evo +// RUN: %target-run %t-evo/swift-class-execution-evo | %FileCheck %s + // REQUIRES: executable_test #include diff --git a/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift b/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift index 20ab96a478a00..a0295fa25df9b 100644 --- a/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift +++ b/test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift @@ -4,6 +4,11 @@ // RUN: %check-interop-cxx-header-in-clang(%t/class.h) +// RUN: %target-swift-frontend %s -typecheck -module-name Class -enable-library-evolution -clang-header-expose-public-decls -emit-clang-header-path %t/class-evo.h +// RUN: %FileCheck %s < %t/class-evo.h + +// RUN: %check-interop-cxx-header-in-clang(%t/class-evo.h) + public final class ClassWithIntField { var field: Int64 @@ -60,7 +65,6 @@ public final class ClassWithIntField { // CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions" // CHECK-NEXT: template<> // CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext = true; -// CHECK-NEXT: #pragma clang diagnostic pop // CHECK-NEXT: template<> // CHECK-NEXT: inline void * _Nonnull getTypeMetadata() { // CHECK-NEXT: return Class::_impl::$s5Class0A12WithIntFieldCMa(0)._0; @@ -69,6 +73,7 @@ public final class ClassWithIntField { // CHECK-NEXT: template<> // CHECK-NEXT: struct implClassFor { using type = Class::_impl::_impl_ClassWithIntField; }; // CHECK-NEXT: } // namespace +// CHECK-NEXT: #pragma clang diagnostic pop // CHECK-NEXT: } // namespace swift // CHECK-EMPTY: // CHECK-NEXT: namespace Class { diff --git a/test/Interop/SwiftToCxx/class/swift-class-inheritance-execution.cpp b/test/Interop/SwiftToCxx/class/swift-class-inheritance-execution.cpp index 02f5f8b60df1c..040932a577f21 100644 --- a/test/Interop/SwiftToCxx/class/swift-class-inheritance-execution.cpp +++ b/test/Interop/SwiftToCxx/class/swift-class-inheritance-execution.cpp @@ -11,6 +11,16 @@ // RUN: not %target-interop-build-clangxx -c %s -I %t -o %t/swift-class-execution.o -DERROR1 // RUN: not %target-interop-build-clangxx -c %s -I %t -o %t/swift-class-execution.o -DERROR2 +// RUN: %empty-directory(%t-evo) + +// RUN: %target-swift-frontend %S/swift-class-inheritance-in-cxx.swift -typecheck -module-name Class -enable-library-evolution -clang-header-expose-public-decls -emit-clang-header-path %t-evo/class.h + +// RUN: %target-interop-build-clangxx -c %s -I %t-evo -o %t-evo/swift-class-execution.o +// RUN: %target-interop-build-swift %S/swift-class-inheritance-in-cxx.swift -o %t-evo/swift-class-execution-evo -Xlinker %t-evo/swift-class-execution.o -module-name Class -enable-library-evolution -Xfrontend -entry-point-function-name -Xfrontend swiftMain + +// RUN: %target-codesign %t-evo/swift-class-execution-evo +// RUN: %target-run %t-evo/swift-class-execution-evo | %FileCheck %s + // REQUIRES: executable_test #include diff --git a/test/Interop/SwiftToCxx/class/swift-class-inheritance-in-cxx.swift b/test/Interop/SwiftToCxx/class/swift-class-inheritance-in-cxx.swift index 749621cd4d664..1d207d2f49dc9 100644 --- a/test/Interop/SwiftToCxx/class/swift-class-inheritance-in-cxx.swift +++ b/test/Interop/SwiftToCxx/class/swift-class-inheritance-in-cxx.swift @@ -4,6 +4,11 @@ // RUN: %check-interop-cxx-header-in-clang(%t/class.h) +// RUN: %target-swift-frontend %s -typecheck -module-name Class -enable-library-evolution -clang-header-expose-public-decls -emit-clang-header-path %t/class-evo.h +// RUN: %FileCheck %s < %t/class-evo.h + +// RUN: %check-interop-cxx-header-in-clang(%t/class-evo.h) + public class BaseClass { var field: Int64 diff --git a/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift b/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift index d28fc27daa443..dce6eb74dbf46 100644 --- a/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift +++ b/test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift @@ -51,6 +51,8 @@ // CHECK-NEXT: size_t stride; // CHECK-NEXT: unsigned flags; // CHECK-NEXT: unsigned extraInhabitantCount; +// CHECK-EMPTY: +// CHECK-NEXT: constexpr size_t getAlignment() const { return (flags & 255) + 1; } // CHECK-NEXT: }; // CHECK-EMPTY: // CHECK-NEXT: using EnumValueWitnessGetEnumTagTy = int(* __ptrauth_swift_value_witness_function_pointer(41909))(const void * _Nonnull, void * _Nonnull) SWIFT_NOEXCEPT_FUNCTION_PTR; @@ -96,22 +98,6 @@ // CHECK-NEXT: } // CHECK-NEXT: #endif // CHECK-EMPTY: -// CHECK-NEXT: /// Container for an opaque Swift value, like resilient struct. -// CHECK-NEXT: class OpaqueStorage { -// CHECK-NEXT: public: -// CHECK-NEXT: inline OpaqueStorage() noexcept : storage(nullptr) { } -// CHECK-NEXT: inline OpaqueStorage(ValueWitnessTable * _Nonnull vwTable) noexcept : storage(reinterpret_cast(opaqueAlloc(vwTable->size, (vwTable->flags &255) + 1))) { } -// CHECK-NEXT: inline OpaqueStorage(OpaqueStorage&& other) noexcept : storage(other.storage) { other.storage = nullptr; } -// CHECK-NEXT: inline OpaqueStorage(const OpaqueStorage&) noexcept = delete; -// CHECK-NEXT: inline ~OpaqueStorage() noexcept { if (storage) { opaqueFree(static_cast(storage)); } } -// CHECK-NEXT: void operator =(OpaqueStorage&& other) noexcept { auto temp = storage; storage = other.storage; other.storage = temp; } -// CHECK-NEXT: void operator =(const OpaqueStorage&) noexcept = delete; -// CHECK-NEXT: inline char * _Nonnull getOpaquePointer() noexcept { return static_cast(storage); } -// CHECK-NEXT: inline const char * _Nonnull getOpaquePointer() const noexcept { return static_cast(storage); } -// CHECK-NEXT: private: -// CHECK-NEXT: char * _Nullable storage; -// CHECK-NEXT: }; -// CHECK-EMPTY: // CHECK-NEXT: /// Naive exception class that should be thrown // CHECK-NEXT: class NaiveException { // CHECK-NEXT: public: diff --git a/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp b/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp index 330396aa84e95..716b9957357de 100644 --- a/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp +++ b/test/Interop/SwiftToCxx/generics/generic-function-execution.cpp @@ -156,5 +156,55 @@ int main() { } // CHECK-NEXT: deinit TestClass // CHECK-NEXT: deinit TestClass + + { + auto x = createTestLargeStruct(0); + genericPrintFunction(x); + } +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: 0, x2: 1, x3: -1, x4: 0, x5: 2, x6: -2) + + { + auto x = createTestLargeStruct(11); + auto y = createTestLargeStruct(-9); + genericPrintFunction(x); + genericPrintFunction(y); + genericSwap(x, y); + genericPrintFunction(x); + genericPrintFunction(y); + auto xy = genericRet(x); + genericPrintFunction(xy); + xy.mut(); + genericPrintFunction(xy); + genericPrintFunction(x); + } +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: 11, x2: 12, x3: 10, x4: 11, x5: 13, x6: 9) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: -9, x2: -8, x3: -10, x4: -9, x5: -7, x6: -11) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: -9, x2: -8, x3: -10, x4: -9, x5: -7, x6: -11) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: 11, x2: 12, x3: 10, x4: 11, x5: 13, x6: 9) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: -9, x2: -8, x3: -10, x4: -9, x5: -7, x6: -11) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: 9, x2: -8, x3: -10, x4: -9, x5: -7, x6: -7) +// CHECK-NEXT: TestLargeStruct value=TestLargeStruct(x1: -9, x2: -8, x3: -10, x4: -9, x5: -7, x6: -11) + + { + auto x = createTestSmallStruct(45); + auto y = createTestSmallStruct(0xFed1); + genericPrintFunction(x); + genericPrintFunction(y); + genericSwap(y, x); + genericPrintFunction(x); + genericPrintFunction(y); + auto xy = genericRet(x); + genericPrintFunction(xy); + xy.mut(); + genericPrintFunction(xy); + genericPrintFunction(x); + } +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 45) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 45) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 4294902062) +// CHECK-NEXT: TestSmallStruct value=TestSmallStruct(x1: 65233) return 0; } diff --git a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift index 0d5e2451af4cb..71a16b49e158f 100644 --- a/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift +++ b/test/Interop/SwiftToCxx/generics/generic-function-in-cxx.swift @@ -2,8 +2,12 @@ // RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h // RUN: %FileCheck %s < %t/functions.h -// RUN: %check-generic-interop-cxx-header-in-clang(%t/functions.h) +// RUN: %check-generic-interop-cxx-header-in-clang(%t/functions.h -Wno-unused-function) +// RUN: %target-swift-frontend %s -typecheck -module-name Functions -enable-library-evolution -clang-header-expose-public-decls -emit-clang-header-path %t/functions-evo.h +// RUN: %FileCheck %s < %t/functions-evo.h + +// RUN: %check-generic-interop-cxx-header-in-clang(%t/functions-evo.h -Wno-unused-function) public func genericPrintFunctionTwoArg(_ x: T, _ y: Int) { print("X:", x) @@ -40,30 +44,68 @@ public class TestClass { public func createTestClass() -> TestClass { return TestClass() } +public struct TestLargeStruct { + var x1, x2, x3, x4, x5, x6: Int + + init(_ x: Int) { + x1 = x + x2 = x+1 + x3 = x-1 + x4 = x + x5 = x+2 + x6 = x-2 + } + + public mutating func mut() { + x1 = -x1 + x6 = x5 + } +} + +public func createTestLargeStruct(_ x: Int) -> TestLargeStruct { + return TestLargeStruct(x) +} + +public struct TestSmallStruct { + var x1: UInt32 + + public mutating func mut() { + x1 = ~x1 + } +} + +public func createTestSmallStruct(_ x: UInt32) -> TestSmallStruct { + return TestSmallStruct(x1: x) +} + // CHECK: SWIFT_EXTERN void $s9Functions20genericPrintFunctionyyxlF(const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunction(_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(ptrdiff_t x, const void * _Nonnull t1, const void * _Nonnull t1p, ptrdiff_t y, const void * _Nonnull t2, void * _Nonnull , void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionMultiGeneric(_:_:_:_:_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions26genericPrintFunctionTwoArgyyx_SitlF(const void * _Nonnull x, ptrdiff_t y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericPrintFunctionTwoArg(_:_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions10genericRetyxxlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericRet(_:) // CHECK-NEXT: SWIFT_EXTERN void $s9Functions11genericSwapyyxz_xztlF(void * _Nonnull x, void * _Nonnull y, void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // genericSwap(_:_:) +// Skip templates in impl classes. +// CHECK: _impl_TestSmallStruct +// CHECK: template + // CHECK: template // CHECK-NEXT: requires swift::isUsableInGenericContext // CHECK-NEXT: inline void genericPrintFunction(const T & x) noexcept { -// CHECK-NEXT: return _impl::$s9Functions20genericPrintFunctionyyxlF(reinterpret_cast(&x), swift::getTypeMetadata()); +// CHECK-NEXT: return _impl::$s9Functions20genericPrintFunctionyyxlF(swift::_impl::getOpaquePointer(x), swift::getTypeMetadata()); // CHECK-NEXT: } // CHECK: template // CHECK-NEXT: requires swift::isUsableInGenericContext && swift::isUsableInGenericContext // CHECK-NEXT: inline void genericPrintFunctionMultiGeneric(swift::Int x, const T1 & t1, const T1 & t1p, swift::Int y, const T2 & t2) noexcept { -// CHECK-NEXT: return _impl::$s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(x, reinterpret_cast(&t1), reinterpret_cast(&t1p), y, reinterpret_cast(&t2), swift::getTypeMetadata(), swift::getTypeMetadata()); +// CHECK-NEXT: return _impl::$s9Functions32genericPrintFunctionMultiGenericyySi_xxSiq_tr0_lF(x, swift::_impl::getOpaquePointer(t1), swift::_impl::getOpaquePointer(t1p), y, swift::_impl::getOpaquePointer(t2), swift::getTypeMetadata(), swift::getTypeMetadata()); // CHECK-NEXT: } // CHECK: template // CHECK-NEXT: requires swift::isUsableInGenericContext // CHECK-NEXT: inline void genericPrintFunctionTwoArg(const T & x, swift::Int y) noexcept { -// CHECK-NEXT: return _impl::$s9Functions26genericPrintFunctionTwoArgyyx_SitlF(reinterpret_cast(&x), y, swift::getTypeMetadata()); +// CHECK-NEXT: return _impl::$s9Functions26genericPrintFunctionTwoArgyyx_SitlF(swift::_impl::getOpaquePointer(x), y, swift::getTypeMetadata()); // CHECK-NEXT: } // CHECK: template @@ -71,11 +113,15 @@ public func createTestClass() -> TestClass { return TestClass() } // CHECK-NEXT: inline T genericRet(const T & x) noexcept SWIFT_WARN_UNUSED_RESULT { // CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T>::value) { // CHECK-NEXT: void *returnValue; -// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast(&returnValue), reinterpret_cast(&x), swift::getTypeMetadata()); +// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast(&returnValue), swift::_impl::getOpaquePointer(x), swift::getTypeMetadata()); // CHECK-NEXT: return ::swift::_impl::implClassFor::type::makeRetained(returnValue); +// CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType) { +// CHECK-NEXT: return ::swift::_impl::implClassFor::type::returnNewValue([&](void * _Nonnull returnValue) { +// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(returnValue, swift::_impl::getOpaquePointer(x), swift::getTypeMetadata()); +// CHECK-NEXT: }); // CHECK-NEXT: } else { // CHECK-NEXT: T returnValue; -// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast(&returnValue), reinterpret_cast(&x), swift::getTypeMetadata()); +// CHECK-NEXT: _impl::$s9Functions10genericRetyxxlF(reinterpret_cast(&returnValue), swift::_impl::getOpaquePointer(x), swift::getTypeMetadata()); // CHECK-NEXT: return returnValue; // CHECK-NEXT: } // CHECK-NEXT: } @@ -83,5 +129,5 @@ public func createTestClass() -> TestClass { return TestClass() } // CHECK: template // CHECK-NEXT: requires swift::isUsableInGenericContext // CHECK-NEXT: inline void genericSwap(T & x, T & y) noexcept { -// CHECK-NEXT: return _impl::$s9Functions11genericSwapyyxz_xztlF(reinterpret_cast(&x), reinterpret_cast(&y), swift::getTypeMetadata()); +// CHECK-NEXT: return _impl::$s9Functions11genericSwapyyxz_xztlF(swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::getTypeMetadata()); // CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/generics/resilient-generic-function-execution.cpp b/test/Interop/SwiftToCxx/generics/resilient-generic-function-execution.cpp new file mode 100644 index 0000000000000..a6e7d11804616 --- /dev/null +++ b/test/Interop/SwiftToCxx/generics/resilient-generic-function-execution.cpp @@ -0,0 +1,13 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend %S/generic-function-in-cxx.swift -typecheck -module-name Functions -enable-library-evolution -clang-header-expose-public-decls -emit-clang-header-path %t/functions.h + +// RUN: %target-interop-build-clangxx -std=gnu++20 -c %s -I %t -o %t/swift-functions-execution.o +// RUN: %target-interop-build-swift %S/generic-function-in-cxx.swift -o %t/swift-functions-execution -Xlinker %t/swift-functions-execution.o -enable-library-evolution -module-name Functions -Xfrontend -entry-point-function-name -Xfrontend swiftMain + +// RUN: %target-codesign %t/swift-functions-execution +// RUN: %target-run %t/swift-functions-execution | %FileCheck %S/generic-function-execution.cpp + +// REQUIRES: executable_test + +#include "generic-function-execution.cpp" diff --git a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx-execution.cpp b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx-execution.cpp index dee3b043680b6..8effef0d2795a 100644 --- a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx-execution.cpp +++ b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx-execution.cpp @@ -40,6 +40,11 @@ int main() { // CHECK: find - small dump // CURRENT-NEXT: x = 66 // CHANGE-NEXT: x&y = 0&65 + copySmallStruct.mutate(); + copySmallStruct.dump(); +// CHECK: find - small dump +// CURRENT-NEXT: x = 132 +// CHANGE-NEXT: x&y = 0&4294967230 printSmallAndLarge(smallStruct, largeStruct); // CHECK: find - small dump diff --git a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift index fb9efe969ceef..b32a83165a46a 100644 --- a/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift +++ b/test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx.swift @@ -16,6 +16,13 @@ public struct FirstSmallStruct { print("x&y = \(x)&\(y)") #else print("x = \(x)") +#endif + } + + public mutating func mutate() { + x = x * 2 +#if CHANGE_LAYOUT + y = ~y #endif } } @@ -30,11 +37,11 @@ public struct FirstSmallStruct { // CHECK-NEXT: #else // CHECK-NEXT: auto *vwTable = *vwTableAddr; // CHECK-NEXT: #endif -// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable); +// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable->size, vwTable->getAlignment()); // CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0); // CHECK-NEXT: } // CHECK: private: -// CHECK-NEXT: inline FirstSmallStruct(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable) {} +// CHECK-NEXT: inline FirstSmallStruct(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, vwTable->getAlignment()) {} // CHECK-NEXT: static inline FirstSmallStruct _make() { // CHECK-NEXT: auto metadata = _impl::$s7Structs16FirstSmallStructVMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -52,6 +59,36 @@ public struct FirstSmallStruct { // CHECK-NEXT: friend class _impl::_impl_FirstSmallStruct; // CHECK-NEXT:}; +// CHECK: class _impl_FirstSmallStruct { +// CHECK: }; +// CHECK-EMPTY: +// CHECK-NEXT: } + +// CHECK-EMPTY: +// CHECK-NEXT: } // end namespace +// CHECK-EMPTY: +// CHECK-NEXT: namespace swift { +// CHECK-NEXT: #pragma clang diagnostic push +// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions" +// CHECK-NEXT: template<> +// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext = true; +// CHECK-NEXT: template<> +// CHECK-NEXT: inline void * _Nonnull getTypeMetadata() { +// CHECK-NEXT: return Structs::_impl::$s7Structs16FirstSmallStructVMa(0)._0; +// CHECK-NEXT: } +// CHECK-NEXT: namespace _impl{ +// CHECK-NEXT: template<> +// CHECK-NEXT: static inline const constexpr bool isValueType = true; +// CHECK-NEXT: template<> +// CHECK-NEXT: static inline const constexpr bool isOpaqueLayout = true; +// CHECK-NEXT: template<> +// CHECK-NEXT: struct implClassFor { using type = Structs::_impl::_impl_FirstSmallStruct; }; +// CHECK-NEXT: } // namespace +// CHECK-NEXT: #pragma clang diagnostic pop +// CHECK-NEXT: } // namespace swift +// CHECK-EMPTY: +// CHECK-NEXT: namespace Structs { + // CHECK: inline uint32_t FirstSmallStruct::getX() const { // CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV1xs6UInt32Vvg(_getOpaquePointer()); // CHECK-NEXT: } @@ -61,6 +98,9 @@ public struct FirstSmallStruct { // CHECK-NEXT: inline void FirstSmallStruct::dump() const { // CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV4dumpyyF(_getOpaquePointer()); // CHECK-NEXT: } +// CHECK-NEXT: inline void FirstSmallStruct::mutate() { +// CHECK-NEXT: return _impl::$s7Structs16FirstSmallStructV6mutateyyF(_getOpaquePointer()); +// CHECK-NEXT: } @frozen public struct FrozenStruct { private let storedInt: Int32 @@ -93,11 +133,11 @@ public struct LargeStruct { // CHECK-NEXT: #else // CHECK-NEXT: auto *vwTable = *vwTableAddr; // CHECK-NEXT: #endif -// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable); +// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable->size, vwTable->getAlignment()); // CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0); // CHECK-NEXT: } // CHECK: private: -// CHECK-NEXT: inline LargeStruct(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable) {} +// CHECK-NEXT: inline LargeStruct(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, vwTable->getAlignment()) {} // CHECK-NEXT: static inline LargeStruct _make() { // CHECK-NEXT: auto metadata = _impl::$s7Structs11LargeStructVMa(0); // CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; @@ -151,7 +191,7 @@ public struct StructWithRefCountStoredProp { } } -// CHECK: inline StructWithRefCountStoredProp(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable) {} +// CHECK: inline StructWithRefCountStoredProp(swift::_impl::ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, vwTable->getAlignment()) {} // CHECK: inline void StructWithRefCountStoredProp::dump() const { // CHECK-NEXT: return _impl::$s7Structs28StructWithRefCountStoredPropV4dumpyyF(_getOpaquePointer()); // CHECK-NEXT: } diff --git a/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift b/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift index 12aa53cf8be27..968ff81239d7d 100644 --- a/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift +++ b/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift @@ -61,6 +61,29 @@ // CHECK-NEXT: }; // CHECK-EMPTY: // CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } // end namespace +// CHECK-EMPTY: +// CHECK-NEXT: namespace swift { +// CHECK-NEXT: #pragma clang diagnostic push +// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions" +// CHECK-NEXT: template<> +// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext = true; +// CHECK-NEXT: template<> +// CHECK-NEXT: inline void * _Nonnull getTypeMetadata() { +// CHECK-NEXT: return Structs::_impl::$s7Structs18StructWithIntFieldVMa(0)._0; +// CHECK-NEXT: } +// CHECK-NEXT: namespace _impl{ +// CHECK-NEXT: template<> +// CHECK-NEXT: static inline const constexpr bool isValueType = true; +// CHECK-NEXT: template<> +// CHECK-NEXT: struct implClassFor { using type = Structs::_impl::_impl_StructWithIntField; }; +// CHECK-NEXT: } // namespace +// CHECK-NEXT: #pragma clang diagnostic pop +// CHECK-NEXT: } // namespace swift +// CHECK-EMPTY: +// CHECK-NEXT: namespace Structs { + public struct StructWithIntField { let field: Int64 } diff --git a/test/api-digester/stability-stdlib-abi-without-asserts.test b/test/api-digester/stability-stdlib-abi-without-asserts.test index f36f60149490a..d4872d1ea1e30 100644 --- a/test/api-digester/stability-stdlib-abi-without-asserts.test +++ b/test/api-digester/stability-stdlib-abi-without-asserts.test @@ -65,6 +65,8 @@ Protocol CodingKey has added inherited protocol Sendable Protocol CodingKey has generic signature change from to Protocol Error has added inherited protocol Sendable Protocol Error has generic signature change from to +Constructor _SmallString.init(taggedCocoa:) has mangled name changing from 'Swift._SmallString.init(taggedCocoa: Swift.AnyObject) -> Swift._SmallString' to 'Swift._SmallString.init(taggedCocoa: Swift.AnyObject) -> Swift.Optional' +Constructor _SmallString.init(taggedCocoa:) has return type change from Swift._SmallString to Swift._SmallString? Enum Never has added a conformance to an existing protocol Identifiable // These haven't actually been removed; they are simply marked unavailable. diff --git a/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.h b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.h new file mode 100644 index 0000000000000..e39908cb40465 --- /dev/null +++ b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.h @@ -0,0 +1,10 @@ +#import +#import + + +@interface NSSlowTaggedLocalizedString : NSObject + ++ (instancetype) createTestString; ++ (void) setContents: (const char *)newContents; + +@end diff --git a/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m new file mode 100644 index 0000000000000..2a3f643ea46aa --- /dev/null +++ b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m @@ -0,0 +1,116 @@ +#import +#import "NSSlowTaggedLocalizedString.h" +#import +#import +#import + +/* + This horrific mess is simulating the new-in-macOS-Ventura tagged pointer strings, + which can have lengths >15 characters, which can cause problems in SmallString, + which used to assume that would never happen. Once CI is running on Ventura or + later, this can be rewritten to use a regular NSLocalizedString. + */ + +@implementation NSSlowTaggedLocalizedString + ++ (instancetype) createTestString { +#if __LP64__ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [[[NSString alloc] init] release]; //Make sure NSString is initialized + Class tagClass = objc_lookUpClass("NSTaggedPointerString"); + Class ourClass = [NSSlowTaggedLocalizedString class]; + + Method fastCString = class_getInstanceMethod(ourClass, @selector(_fastCStringContents:)); + class_replaceMethod(tagClass, @selector(_fastCStringContents:), method_getImplementation(fastCString), method_getTypeEncoding(fastCString)); + + Method length = class_getInstanceMethod(ourClass, @selector(length)); + class_replaceMethod(tagClass, @selector(length), method_getImplementation(length), method_getTypeEncoding(length)); + + Method charIndex = class_getInstanceMethod(ourClass, @selector(characterAtIndex:)); + class_replaceMethod(tagClass, @selector(characterAtIndex:), method_getImplementation(charIndex), method_getTypeEncoding(charIndex)); + + Method fastChars = class_getInstanceMethod(ourClass, @selector(_fastCharacterContents)); + class_replaceMethod(tagClass, @selector(_fastCharacterContents), method_getImplementation(fastChars), method_getTypeEncoding(fastChars)); + + Method retain = class_getInstanceMethod(ourClass, @selector(retain)); + class_replaceMethod(tagClass, @selector(retain), method_getImplementation(retain), method_getTypeEncoding(retain)); + + Method release = class_getInstanceMethod(ourClass, @selector(release)); + class_replaceMethod(tagClass, @selector(release), method_getImplementation(release), method_getTypeEncoding(release)); + + Method typeID = class_getInstanceMethod(ourClass, @selector(_cfTypeID)); + class_replaceMethod(tagClass, @selector(_cfTypeID), method_getImplementation(typeID), method_getTypeEncoding(typeID)); + + Method description = class_getInstanceMethod(ourClass, @selector(description)); + class_replaceMethod(tagClass, @selector(description), method_getImplementation(description), method_getTypeEncoding(description)); + + Method getBytes = class_getInstanceMethod(ourClass, @selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:)); + class_replaceMethod(tagClass, @selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:), method_getImplementation(getBytes), method_getTypeEncoding(getBytes)); + }); + return (NSSlowTaggedLocalizedString *)(void *)CFStringCreateWithCString(NULL, "a", kCFStringEncodingASCII); //make a tagged pointer string +#else + return nil; +#endif +} + +static const char *contents = NULL; + ++ (void) setContents: (const char *)newContents { + const char *oldContents = contents; + if (newContents) { + contents = strdup(newContents); + } else { + contents = NULL; + } + free((void *)oldContents); +} + +- (const char *)_fastCStringContents:(BOOL)nullTerminationRequired { + return contents; +} + +- (uint64_t)length { + return strlen(contents); +} + +- (id)copyWithZone:(id)unused { + return self; +} + +- (uint16_t)characterAtIndex:(NSUInteger)index { + if (index >= [self length]) { + abort(); + } + return (uint16_t)contents[index]; +} + +- (void *) _fastCharacterContents { + return nil; +} + +- (id) retain { return self; } +- (oneway void) release {} + +- (uint64_t)_cfTypeID { + return 7; //CFString +} + +- (id) description { + return self; +} + +- (BOOL)getBytes:(void *)buffer maxLength:(uint64_t)max usedLength:(uint64_t *)used encoding:(uint64_t)encoding options:(uint64_t)options range:(NSRange)range remainingRange:(NSRange *)leftover { + assert(encoding == 1 /* ASCII */ || encoding == 4 /* UTF8 */); + strncpy(buffer, contents, max); + if (strlen(contents) > max) { + leftover->location = max; + leftover->length = strlen(contents) - max; + return false; + } + leftover->location = 0; + leftover->length = 0; + return true; +} + +@end diff --git a/test/stdlib/Inputs/NSSlowTaggedLocalizedString/module.map b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/module.map new file mode 100644 index 0000000000000..0761d14942800 --- /dev/null +++ b/test/stdlib/Inputs/NSSlowTaggedLocalizedString/module.map @@ -0,0 +1,3 @@ +module NSSlowTaggedLocalizedString { + header "NSSlowTaggedLocalizedString.h" +} diff --git a/test/stdlib/NSSlowTaggedLocalizedString.swift b/test/stdlib/NSSlowTaggedLocalizedString.swift new file mode 100644 index 0000000000000..5f385745e702f --- /dev/null +++ b/test/stdlib/NSSlowTaggedLocalizedString.swift @@ -0,0 +1,38 @@ +// RUN: mkdir -p %t +// RUN: %target-clang %S/Inputs/NSSlowTaggedLocalizedString/NSSlowTaggedLocalizedString.m -fno-objc-arc -c -o %t/NSSlowTaggedLocalizedString.o +// RUN: %target-build-swift -g -parse-stdlib -Xfrontend -disable-access-control -I %S/Inputs/NSSlowTaggedLocalizedString/ %t/NSSlowTaggedLocalizedString.o %s -o %t/a.out +// RUN: %target-codesign %t/a.out +// RUN: %target-run %t/a.out + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +import NSSlowTaggedLocalizedString +import Swift + +import StdlibUnittest + +let longTaggedTests = TestSuite("NonContiguousTaggedStrings") +var constant = "Send Message to different Team" + +func runEqualLongTagged() { + let native = constant.withUTF8 { String(decoding: $0, as: UTF8.self) } + let longTagged = NSSlowTaggedLocalizedString.createTest()! + constant.withCString { + NSSlowTaggedLocalizedString.setContents($0) + } + defer { + NSSlowTaggedLocalizedString.setContents(nil) + } + let reverseBridged = unsafeBitCast(native._guts._object.largeAddressBits, to: AnyObject.self) + let eq = reverseBridged.isEqual(to: longTagged) + expectEqual(eq, 1) + _fixLifetime(native) +} + +longTaggedTests.test("EqualLongTagged") { + runEqualLongTagged() +} + +runAllTests() +