diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst index 9534d643eb16..fafa64f64997 100644 --- a/docs/ABI/Mangling.rst +++ b/docs/ABI/Mangling.rst @@ -646,6 +646,9 @@ Types global-actor :: = type 'Yc' // Global actor on function type #endif throws ::= 'K' // 'throws' annotation on function types + #if SWIFT_RUNTIME_VERSION >= 5.11 + throws ::= type 'YK' // 'throws(type)' annotation on function types + #endif differentiable ::= 'Yjf' // @differentiable(_forward) on function type differentiable ::= 'Yjr' // @differentiable(reverse) on function type differentiable ::= 'Yjd' // @differentiable on function type diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 99fb5ac17e78..2a5a1265b870 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -1459,21 +1459,91 @@ struct TargetEnumMetadata : public TargetValueMetadata { }; using EnumMetadata = TargetEnumMetadata; +template +struct TargetFunctionGlobalActorMetadata { + ConstTargetMetadataPointer GlobalActorType; +}; +using FunctionGlobalActorMetadata = TargetFunctionGlobalActorMetadata; + +template +struct TargetFunctionThrownErrorMetadata { + ConstTargetMetadataPointer ThrownErrorType; +}; +using FunctionThrownErrorMetadata = TargetFunctionThrownErrorMetadata; + /// The structure of function type metadata. template -struct TargetFunctionTypeMetadata : public TargetMetadata { +struct TargetFunctionTypeMetadata : public TargetMetadata, + swift::ABI::TrailingObjects< + TargetFunctionTypeMetadata, + ConstTargetMetadataPointer, + ParameterFlags, + TargetFunctionMetadataDifferentiabilityKind, + TargetFunctionGlobalActorMetadata, + ExtendedFunctionTypeFlags, + TargetFunctionThrownErrorMetadata> { using StoredSize = typename Runtime::StoredSize; using Parameter = ConstTargetMetadataPointer; +private: + using TrailingObjects = + swift::ABI::TrailingObjects< + TargetFunctionTypeMetadata, + Parameter, + ParameterFlags, + TargetFunctionMetadataDifferentiabilityKind, + TargetFunctionGlobalActorMetadata, + ExtendedFunctionTypeFlags, + TargetFunctionThrownErrorMetadata>; + friend TrailingObjects; + + template + using OverloadToken = typename TrailingObjects::template OverloadToken; + +public: TargetFunctionTypeFlags Flags; /// The type metadata for the result type. ConstTargetMetadataPointer ResultType; - Parameter *getParameters() { return reinterpret_cast(this + 1); } +private: + size_t numTrailingObjects(OverloadToken) const { + return getNumParameters(); + } + + size_t numTrailingObjects(OverloadToken) const { + return hasParameterFlags() ? getNumParameters() : 0; + } + + size_t numTrailingObjects( + OverloadToken> + ) const { + return isDifferentiable() ? 1 : 0; + } + + size_t numTrailingObjects( + OverloadToken> + ) const { + return hasGlobalActor() ? 1 : 0; + } + + size_t numTrailingObjects(OverloadToken) const { + return hasExtendedFlags() ? 1 : 0; + } + + size_t numTrailingObjects( + OverloadToken> + ) const { + return hasThrownError() ? 1 : 0; + } + +public: + Parameter *getParameters() { + return this->template getTrailingObjects(); + } const Parameter *getParameters() const { - return reinterpret_cast(this + 1); + return this->template getTrailingObjects(); } Parameter getParameter(unsigned index) const { @@ -1483,8 +1553,7 @@ struct TargetFunctionTypeMetadata : public TargetMetadata { ParameterFlags getParameterFlags(unsigned index) const { assert(index < getNumParameters()); - auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0; - return ParameterFlags::fromIntValue(flags); + return hasParameterFlags() ? getParameterFlags()[index] : ParameterFlags(); } StoredSize getNumParameters() const { @@ -1500,6 +1569,13 @@ struct TargetFunctionTypeMetadata : public TargetMetadata { bool hasParameterFlags() const { return Flags.hasParameterFlags(); } bool isEscaping() const { return Flags.isEscaping(); } bool hasGlobalActor() const { return Flags.hasGlobalActor(); } + bool hasExtendedFlags() const { return Flags.hasExtendedFlags(); } + bool hasThrownError() const { + if (!Flags.hasExtendedFlags()) + return false; + + return getExtendedFlags().isTypedThrows(); + } static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata); @@ -1507,32 +1583,24 @@ struct TargetFunctionTypeMetadata : public TargetMetadata { return metadata->getKind() == MetadataKind::Function; } - uint32_t *getParameterFlags() { - return reinterpret_cast(getParameters() + getNumParameters()); + ParameterFlags *getParameterFlags() { + return this->template getTrailingObjects(); } - const uint32_t *getParameterFlags() const { - return reinterpret_cast(getParameters() + - getNumParameters()); + const ParameterFlags *getParameterFlags() const { + return this->template getTrailingObjects(); } TargetFunctionMetadataDifferentiabilityKind * getDifferentiabilityKindAddress() { assert(isDifferentiable()); - void *previousEndAddr = hasParameterFlags() - ? reinterpret_cast(getParameterFlags() + getNumParameters()) - : reinterpret_cast(getParameters() + getNumParameters()); - return reinterpret_cast< - TargetFunctionMetadataDifferentiabilityKind *>( - llvm::alignAddr(previousEndAddr, - llvm::Align(alignof(typename Runtime::StoredPointer)))); + return this->template getTrailingObjects>(); } TargetFunctionMetadataDifferentiabilityKind getDifferentiabilityKind() const { if (isDifferentiable()) { - return *const_cast *>(this) - ->getDifferentiabilityKindAddress(); + return *(this->template getTrailingObjects>()); } return TargetFunctionMetadataDifferentiabilityKind ::NonDifferentiable; @@ -1541,26 +1609,47 @@ struct TargetFunctionTypeMetadata : public TargetMetadata { ConstTargetMetadataPointer * getGlobalActorAddr() { assert(hasGlobalActor()); - - void *endAddr = - isDifferentiable() - ? reinterpret_cast(getDifferentiabilityKindAddress() + 1) : - hasParameterFlags() - ? reinterpret_cast(getParameterFlags() + getNumParameters()) : - reinterpret_cast(getParameters() + getNumParameters()); - return reinterpret_cast< - ConstTargetMetadataPointer *>( - llvm::alignAddr( - endAddr, llvm::Align(alignof(typename Runtime::StoredPointer)))); + auto globalActorAddr = + this->template getTrailingObjects>(); + return &globalActorAddr->GlobalActorType; } ConstTargetMetadataPointer getGlobalActor() const { if (!hasGlobalActor()) return ConstTargetMetadataPointer(); + auto globalActorAddr = + this->template getTrailingObjects>(); + return globalActorAddr->GlobalActorType; + } + + ExtendedFunctionTypeFlags *getExtendedFlagsAddr() { + assert(hasExtendedFlags()); + return this->template getTrailingObjects(); + } + + ExtendedFunctionTypeFlags getExtendedFlags() const { + if (!hasExtendedFlags()) + return ExtendedFunctionTypeFlags(); + + return this->template getTrailingObjects()[0]; + } + + ConstTargetMetadataPointer * + getThrownErrorAddr() { + assert(hasThrownError()); + auto thrownErrorAddr = + this->template getTrailingObjects>(); + return &thrownErrorAddr->ThrownErrorType; + } - return *const_cast *>(this) - ->getGlobalActorAddr(); + ConstTargetMetadataPointer + getThrownError() const { + if (!hasThrownError()) + return ConstTargetMetadataPointer(); + auto thrownErrorAddr = + this->template getTrailingObjects>(); + return thrownErrorAddr->ThrownErrorType; } }; using FunctionTypeMetadata = TargetFunctionTypeMetadata; diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index 019e1ed1a58f..783825814d53 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -1037,7 +1037,8 @@ class TargetFunctionTypeFlags { GlobalActorMask = 0x10000000U, AsyncMask = 0x20000000U, SendableMask = 0x40000000U, - // NOTE: The next bit will need to introduce a separate flags word. + ExtendedFlagsMask = 0x80000000U, + // NOTE: No more room for flags here. Use TargetExtendedFunctionTypeFlags. }; int_type Data; @@ -1099,6 +1100,12 @@ class TargetFunctionTypeFlags { (Data & ~GlobalActorMask) | (globalActor ? GlobalActorMask : 0)); } + constexpr TargetFunctionTypeFlags + withExtendedFlags(bool extendedFlags) const { + return TargetFunctionTypeFlags( + (Data & ~ExtendedFlagsMask) | (extendedFlags ? ExtendedFlagsMask : 0)); + } + unsigned getNumParameters() const { return Data & NumParametersMask; } FunctionMetadataConvention getConvention() const { @@ -1127,6 +1134,10 @@ class TargetFunctionTypeFlags { return bool (Data & GlobalActorMask); } + bool hasExtendedFlags() const { + return bool (Data & ExtendedFlagsMask); + } + int_type getIntValue() const { return Data; } @@ -1144,6 +1155,43 @@ class TargetFunctionTypeFlags { }; using FunctionTypeFlags = TargetFunctionTypeFlags; +/// Extended flags in a function type metadata record. +template +class TargetExtendedFunctionTypeFlags { + enum : int_type { + TypedThrowsMask = 0x00000001U, + }; + int_type Data; + + constexpr TargetExtendedFunctionTypeFlags(int_type Data) : Data(Data) {} +public: + constexpr TargetExtendedFunctionTypeFlags() : Data(0) {} + + constexpr TargetExtendedFunctionTypeFlags + withTypedThrows(bool typedThrows) const { + return TargetExtendedFunctionTypeFlags( + (Data & ~TypedThrowsMask) | (typedThrows ? TypedThrowsMask : 0)); + } + + bool isTypedThrows() const { return bool(Data & TypedThrowsMask); } + + int_type getIntValue() const { + return Data; + } + + static TargetExtendedFunctionTypeFlags fromIntValue(int_type Data) { + return TargetExtendedFunctionTypeFlags(Data); + } + + bool operator==(TargetExtendedFunctionTypeFlags other) const { + return Data == other.Data; + } + bool operator!=(TargetExtendedFunctionTypeFlags other) const { + return Data != other.Data; + } +}; +using ExtendedFunctionTypeFlags = TargetExtendedFunctionTypeFlags; + template class TargetParameterTypeFlags { enum : int_type { diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index c6a25ae8b3d6..a6f892029a24 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -914,6 +914,9 @@ class ASTContext final { /// Get the runtime availability of support for differentiation. AvailabilityContext getDifferentiationAvailability(); + /// Get the runtime availability of support for typed throws. + AvailabilityContext getTypedThrowsAvailability(); + /// Get the runtime availability of getters and setters of multi payload enum /// tag single payloads. AvailabilityContext getMultiPayloadEnumTagSinglePayload(); @@ -982,6 +985,10 @@ class ASTContext final { /// compiler for the target platform. AvailabilityContext getSwift59Availability(); + /// Get the runtime availability of features introduced in the Swift 5.9 + /// compiler for the target platform. + AvailabilityContext getSwift511Availability(); + // Note: Update this function if you add a new getSwiftXYAvailability above. /// Get the runtime availability for a particular version of Swift (5.0+). AvailabilityContext diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 794a31cf4b0a..18c448e2b4b1 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -144,7 +144,8 @@ class ASTBuilder { Type createFunctionType( ArrayRef> params, Type output, FunctionTypeFlags flags, - FunctionMetadataDifferentiabilityKind diffKind, Type globalActor); + FunctionMetadataDifferentiabilityKind diffKind, Type globalActor, + Type thrownError); Type createImplFunctionType( Demangle::ImplParameterConvention calleeConvention, diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index 9ad0b3d9066f..f0bea551d6f2 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -286,6 +286,7 @@ NODE(BaseConformanceDescriptor) NODE(AssociatedTypeDescriptor) NODE(AsyncAnnotation) NODE(ThrowsAnnotation) +NODE(TypedThrowsAnnotation) NODE(EmptyList) NODE(FirstElementMarker) NODE(VariadicMarker) diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index 6bc0e5b154d6..10145d0b5fd9 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -855,11 +855,29 @@ class TypeDecoder { ++firstChildIdx; } + BuiltType thrownErrorType = BuiltType(); bool isThrow = false; if (Node->getChild(firstChildIdx)->getKind() == NodeKind::ThrowsAnnotation) { isThrow = true; ++firstChildIdx; + } else if (Node->getChild(firstChildIdx)->getKind() + == NodeKind::TypedThrowsAnnotation) { + isThrow = true; + + auto child = Node->getChild(firstChildIdx); + if (child->getNumChildren() < 1) { + return MAKE_NODE_TYPE_ERROR0(child, + "Thrown error node is missing child"); + } + + auto thrownErrorResult = + decodeMangledType(child->getChild(0), depth + 1); + if (thrownErrorResult.isError()) + return thrownErrorResult; + + thrownErrorType = thrownErrorResult.getType(); + ++firstChildIdx; } bool isSendable = false; @@ -905,8 +923,10 @@ class TypeDecoder { /*forRequirement=*/false); if (result.isError()) return result; + return Builder.createFunctionType( - parameters, result.getType(), flags, diffKind, globalActorType); + parameters, result.getType(), flags, diffKind, globalActorType, + thrownErrorType); } case NodeKind::ImplFunctionType: { auto calleeConvention = ImplParameterConvention::Direct_Unowned; diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 80464874f541..9b38e42e9b33 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -1001,8 +1001,14 @@ class MetadataReader { #undef CASE } + BuiltType thrownError = BuiltType(); + if (Function->hasThrownError()) { + thrownError = readTypeFromMetadata(Function->getThrownError(), false, + recursion_limit); + } + auto BuiltFunction = Builder.createFunctionType( - Parameters, Result, flags, diffKind, globalActor); + Parameters, Result, flags, diffKind, globalActor, thrownError); TypeCache[TypeCacheKey] = BuiltFunction; return BuiltFunction; } diff --git a/include/swift/RemoteInspection/TypeRef.h b/include/swift/RemoteInspection/TypeRef.h index 54f81535cc8c..28491c67719c 100644 --- a/include/swift/RemoteInspection/TypeRef.h +++ b/include/swift/RemoteInspection/TypeRef.h @@ -485,11 +485,13 @@ class FunctionTypeRef final : public TypeRef { FunctionTypeFlags Flags; FunctionMetadataDifferentiabilityKind DifferentiabilityKind; const TypeRef *GlobalActor; + const TypeRef *ThrownError; static TypeRefID Profile(const std::vector &Parameters, const TypeRef *Result, FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind, - const TypeRef *GlobalActor) { + const TypeRef *GlobalActor, + const TypeRef *ThrownError) { TypeRefID ID; for (const auto &Param : Parameters) { ID.addString(Param.getLabel().str()); @@ -500,6 +502,7 @@ class FunctionTypeRef final : public TypeRef { ID.addInteger(static_cast(Flags.getIntValue())); ID.addInteger(static_cast(DiffKind.getIntValue())); ID.addPointer(GlobalActor); + ID.addPointer(ThrownError); return ID; } @@ -508,18 +511,20 @@ class FunctionTypeRef final : public TypeRef { FunctionTypeRef(std::vector Params, const TypeRef *Result, FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind, - const TypeRef *GlobalActor) + const TypeRef *GlobalActor, + const TypeRef *ThrownError) : TypeRef(TypeRefKind::Function), Parameters(Params), Result(Result), Flags(Flags), DifferentiabilityKind(DiffKind), - GlobalActor(GlobalActor) {} + GlobalActor(GlobalActor), ThrownError(ThrownError) {} template static const FunctionTypeRef *create( Allocator &A, std::vector Params, const TypeRef *Result, FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind, - const TypeRef *GlobalActor) { + const TypeRef *GlobalActor, const TypeRef *ThrownError) { FIND_OR_CREATE_TYPEREF( - A, FunctionTypeRef, Params, Result, Flags, DiffKind, GlobalActor); + A, FunctionTypeRef, Params, Result, Flags, DiffKind, GlobalActor, + ThrownError); } const std::vector &getParameters() const { return Parameters; }; @@ -540,6 +545,10 @@ class FunctionTypeRef final : public TypeRef { return GlobalActor; } + const TypeRef *getThrownError() const { + return ThrownError; + } + static bool classof(const TypeRef *TR) { return TR->getKind() == TypeRefKind::Function; } diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index 2f97fdefee3c..56d95f84769a 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -793,9 +793,9 @@ class TypeRefBuilder { llvm::ArrayRef> params, const TypeRef *result, FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind, - const TypeRef *globalActor) { + const TypeRef *globalActor, const TypeRef *thrownError) { return FunctionTypeRef::create( - *this, params, result, flags, diffKind, globalActor); + *this, params, result, flags, diffKind, globalActor, thrownError); } const FunctionTypeRef *createImplFunctionType( @@ -852,7 +852,7 @@ class TypeRefBuilder { auto result = createTupleType({}, llvm::ArrayRef()); return FunctionTypeRef::create( - *this, {}, result, funcFlags, diffKind, nullptr); + *this, {}, result, funcFlags, diffKind, nullptr, nullptr); } BuiltType createProtocolTypeFromDecl(BuiltProtocolDecl protocol) { diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 763469260fb6..7131a106db44 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -504,6 +504,14 @@ swift_getFunctionTypeMetadataGlobalActor( const Metadata *const *parameters, const uint32_t *parameterFlags, const Metadata *result, const Metadata *globalActor); +SWIFT_RUNTIME_EXPORT +const FunctionTypeMetadata * +swift_getExtendedFunctionTypeMetadata( + FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind, + const Metadata *const *parameters, const uint32_t *parameterFlags, + const Metadata *result, const Metadata *globalActor, + ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError); + SWIFT_RUNTIME_EXPORT const FunctionTypeMetadata * swift_getFunctionTypeMetadata0(FunctionTypeFlags flags, diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index c4a2e265554e..a3d6de1ebebd 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -786,6 +786,31 @@ FUNCTION(GetFunctionMetadataDifferentiable, EFFECT(MetaData), MEMEFFECTS(ReadOnly)) +// Metadata * +// swift_getExtendedFunctionTypeMetadata(unsigned long flags, +// unsigned long diffKind, +// const Metadata **parameters, +// const uint32_t *parameterFlags, +// const Metadata *result, +// const Metadata *globalActor, +// uint32_t extendedflags, +// const Metadata *thrownError); +FUNCTION(GetFunctionMetadataExtended, + swift_getExtendedFunctionTypeMetadata, + C_CC, TypedThrowsAvailability, + RETURNS(TypeMetadataPtrTy), + ARGS(SizeTy, + SizeTy, + TypeMetadataPtrTy->getPointerTo(0), + Int32Ty->getPointerTo(0), + TypeMetadataPtrTy, + TypeMetadataPtrTy, + Int32Ty, + TypeMetadataPtrTy), + ATTRS(NoUnwind), + EFFECT(MetaData), + MEMEFFECTS(ReadOnly)) + // Metadata * // swift_getFunctionTypeMetadataGlobalActor(unsigned long flags, // unsigned long diffKind, diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 80659a10c960..1a89a1b2adde 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -390,7 +390,8 @@ void ASTBuilder::endPackExpansion() { Type ASTBuilder::createFunctionType( ArrayRef> params, Type output, FunctionTypeFlags flags, - FunctionMetadataDifferentiabilityKind diffKind, Type globalActor) { + FunctionMetadataDifferentiabilityKind diffKind, Type globalActor, + Type thrownError) { // The result type must be materializable. if (!output->isMaterializable()) return Type(); @@ -454,9 +455,6 @@ Type ASTBuilder::createFunctionType( clangFunctionType = Ctx.getClangFunctionType(funcParams, output, representation); - // FIXME: Populate thrownError - Type thrownError; - auto einfo = FunctionType::ExtInfoBuilder(representation, noescape, flags.isThrowing(), thrownError, resultDiffKind, diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index ecc945de563c..3c0ab1d8b0d9 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2828,8 +2828,14 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn, appendOperator("Ya"); if (fn->isSendable()) appendOperator("Yb"); - if (fn->isThrowing()) - appendOperator("K"); + if (auto thrownError = fn->getEffectiveThrownErrorType()) { + if ((*thrownError)->isEqual(fn->getASTContext().getErrorExistentialType())){ + appendOperator("K"); + } else { + appendType(*thrownError, sig); + appendOperator("YK"); + } + } switch (auto diffKind = fn->getDifferentiabilityKind()) { case DifferentiabilityKind::NonDifferentiable: break; diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 6486284f71aa..c7d0a1c2123b 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -545,6 +545,10 @@ AvailabilityContext ASTContext::getDifferentiationAvailability() { return getSwiftFutureAvailability(); } +AvailabilityContext ASTContext::getTypedThrowsAvailability() { + return getSwift511Availability(); +} + AvailabilityContext ASTContext::getMultiPayloadEnumTagSinglePayload() { return getSwift56Availability(); } @@ -752,6 +756,11 @@ AvailabilityContext ASTContext::getSwift59Availability() { } } +AvailabilityContext ASTContext::getSwift511Availability() { + // Placeholder + return getSwiftFutureAvailability(); +} + AvailabilityContext ASTContext::getSwiftFutureAvailability() { auto target = LangOpts.Target; diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index c685f2ecb1ce..6b89321c92a4 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -926,6 +926,8 @@ NodePointer Demangler::demangleTypeAnnotation() { case 'k': return createType( createWithChild(Node::Kind::NoDerivative, popTypeAndGetChild())); + case 'K': + return createWithChild(Node::Kind::TypedThrowsAnnotation, popTypeAndGetChild()); case 't': return createType( createWithChild(Node::Kind::CompileTimeConst, popTypeAndGetChild())); @@ -1530,7 +1532,10 @@ NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) { addChild(FuncType, ClangType); addChild(FuncType, popNode(Node::Kind::GlobalActorFunctionType)); addChild(FuncType, popNode(Node::Kind::DifferentiableFunctionType)); - addChild(FuncType, popNode(Node::Kind::ThrowsAnnotation)); + addChild(FuncType, popNode([](Node::Kind kind) { + return kind == Node::Kind::ThrowsAnnotation || + kind == Node::Kind::TypedThrowsAnnotation; + })); addChild(FuncType, popNode(Node::Kind::ConcurrentFunctionType)); addChild(FuncType, popNode(Node::Kind::AsyncAnnotation)); @@ -1572,7 +1577,9 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) { == Node::Kind::DifferentiableFunctionType) ++FirstChildIdx; if (FuncType->getChild(FirstChildIdx)->getKind() - == Node::Kind::ThrowsAnnotation) + == Node::Kind::ThrowsAnnotation || + FuncType->getChild(FirstChildIdx)->getKind() + == Node::Kind::TypedThrowsAnnotation) ++FirstChildIdx; if (FuncType->getChild(FirstChildIdx)->getKind() == Node::Kind::ConcurrentFunctionType) diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 71c1a70353ae..a2f102213c17 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -557,6 +557,7 @@ class NodePrinter { case Node::Kind::GlobalActorFunctionType: case Node::Kind::AsyncAnnotation: case Node::Kind::ThrowsAnnotation: + case Node::Kind::TypedThrowsAnnotation: case Node::Kind::EmptyList: case Node::Kind::FirstElementMarker: case Node::Kind::VariadicMarker: @@ -863,7 +864,7 @@ class NodePrinter { unsigned argIndex = node->getNumChildren() - 2; unsigned startIndex = 0; - bool isSendable = false, isAsync = false, isThrows = false; + bool isSendable = false, isAsync = false; auto diffKind = MangledDifferentiabilityKind::NonDifferentiable; if (node->getChild(startIndex)->getKind() == Node::Kind::ClangType) { // handled earlier @@ -880,10 +881,15 @@ class NodePrinter { (MangledDifferentiabilityKind)node->getChild(startIndex)->getIndex(); ++startIndex; } - if (node->getChild(startIndex)->getKind() == Node::Kind::ThrowsAnnotation) { + + Node *thrownErrorNode = nullptr; + if (node->getChild(startIndex)->getKind() == Node::Kind::ThrowsAnnotation || + node->getChild(startIndex)->getKind() + == Node::Kind::TypedThrowsAnnotation) { + thrownErrorNode = node->getChild(startIndex); ++startIndex; - isThrows = true; } + if (node->getChild(startIndex)->getKind() == Node::Kind::ConcurrentFunctionType) { ++startIndex; @@ -923,8 +929,9 @@ class NodePrinter { if (isAsync) Printer << " async"; - if (isThrows) - Printer << " throws"; + if (thrownErrorNode) { + print(thrownErrorNode, depth + 1); + } print(node->getChild(argIndex + 1), depth + 1); } @@ -2909,10 +2916,16 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth, return nullptr; } case Node::Kind::AsyncAnnotation: - Printer << " async "; + Printer << " async"; return nullptr; case Node::Kind::ThrowsAnnotation: - Printer << " throws "; + Printer << " throws"; + return nullptr; + case Node::Kind::TypedThrowsAnnotation: + Printer << " throws("; + if (Node->getNumChildren() == 1) + print(Node->getChild(0), depth + 1); + Printer << ")"; return nullptr; case Node::Kind::EmptyList: Printer << " empty-list "; diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index cde432f567e4..0ebb7645577b 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -829,6 +829,11 @@ ManglingError Remangler::mangleThrowsAnnotation(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleTypedThrowsAnnotation(Node *node, unsigned depth) { + Buffer << "z"; + return ManglingError::Success; +} + ManglingError Remangler::mangleDifferentiableFunctionType(Node *node, unsigned depth) { Buffer << "D"; diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index e1a4a8e21de4..d1fecfd927d4 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -3273,6 +3273,12 @@ ManglingError Remangler::mangleThrowsAnnotation(Node *node, unsigned depth) { return ManglingError::Success; } +ManglingError Remangler::mangleTypedThrowsAnnotation(Node *node, unsigned depth) { + RETURN_IF_ERROR(mangleChildNodes(node, depth + 1)); + Buffer << "YK"; + return ManglingError::Success; +} + ManglingError Remangler::mangleEmptyList(Node *node, unsigned depth) { Buffer << 'y'; return ManglingError::Success; diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index a4973310a110..5324e706ff73 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -378,6 +378,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments, runtimeCompatibilityVersion = llvm::VersionTuple(5, 6); } else if (value.equals("5.8")) { runtimeCompatibilityVersion = llvm::VersionTuple(5, 8); + } else if (value.equals("5.11")) { + runtimeCompatibilityVersion = llvm::VersionTuple(5, 11); } else if (value.equals("none")) { runtimeCompatibilityVersion = llvm::None; } else { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 057173d09a81..3cbe29bd8b17 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2811,6 +2811,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, runtimeCompatibilityVersion = llvm::VersionTuple(5, 6); } else if (version.equals("5.8")) { runtimeCompatibilityVersion = llvm::VersionTuple(5, 8); + } else if (version.equals("5.11")) { + runtimeCompatibilityVersion = llvm::VersionTuple(5, 11); } else { Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, versionArg->getAsString(Args), version); diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 301f0fe9b9ef..d5a974135601 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -176,6 +176,20 @@ class PrintMetadataSource llvm::Optional getRuntimeVersionThatSupportsDemanglingType(CanType type) { + // The Swift 5.11 runtime is the first version able to demangle types + // that involve typed throws. + bool usesTypedThrows = type.findIf([](CanType t) -> bool { + if (auto fn = dyn_cast(t)) { + if (!fn.getThrownError().isNull()) + return true; + } + + return false; + }); + if (usesTypedThrows) { + return llvm::VersionTuple(5, 11); + } + // The Swift 5.5 runtime is the first version able to demangle types // related to concurrency. bool needsConcurrency = type.findIf([](CanType t) -> bool { diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 883bd744b07c..edb91925e97d 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -883,6 +883,14 @@ namespace RuntimeConstants { return RuntimeAvailability::AlwaysAvailable; } + RuntimeAvailability TypedThrowsAvailability(ASTContext &Context) { + auto featureAvailability = Context.getTypedThrowsAvailability(); + if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) { + return RuntimeAvailability::ConditionallyAvailable; + } + return RuntimeAvailability::AlwaysAvailable; + } + RuntimeAvailability MultiPayloadEnumTagSinglePayloadAvailability(ASTContext &context) { auto featureAvailability = context.getMultiPayloadEnumTagSinglePayload(); diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 94014d1c4074..e7b815d985fc 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -1397,7 +1397,8 @@ ParameterFlags irgen::getABIParameterFlags(ParameterTypeFlags flags) { .withIsolated(flags.isIsolated()); } -static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) { +static std::pair +getFunctionTypeFlags(CanFunctionType type) { bool hasParameterFlags = false; for (auto param : type.getParams()) { if (!getABIParameterFlags(param.getParameterFlags()).isNone()) { @@ -1425,7 +1426,10 @@ static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) { break; } - return FunctionTypeFlags() + auto extFlags = ExtendedFunctionTypeFlags() + .withTypedThrows(!type->getThrownError().isNull()); + + auto flags = FunctionTypeFlags() .withConvention(metadataConvention) .withAsync(type->isAsync()) .withConcurrent(type->isSendable()) @@ -1433,7 +1437,10 @@ static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) { .withParameterFlags(hasParameterFlags) .withEscaping(isEscaping) .withDifferentiable(type->isDifferentiable()) - .withGlobalActor(!type->getGlobalActor().isNull()); + .withGlobalActor(!type->getGlobalActor().isNull()) + .withExtendedFlags(extFlags.getIntValue() != 0); + + return std::make_pair(flags, extFlags); } namespace { @@ -1559,7 +1566,10 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF, auto params = type.getParams(); bool hasPackExpansion = type->containsPackExpansionParam(); - auto flags = getFunctionTypeFlags(type); + FunctionTypeFlags flags; + ExtendedFunctionTypeFlags extFlags; + + std::tie(flags, extFlags) = getFunctionTypeFlags(type); llvm::Value *flagsVal = nullptr; llvm::Value *shapeExpression = nullptr; CanPackType packType; @@ -1615,7 +1625,8 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF, case 2: case 3: { if (!flags.hasParameterFlags() && !type->isDifferentiable() && - !type->getGlobalActor() && !hasPackExpansion) { + !type->getGlobalActor() && !hasPackExpansion && + !flags.hasExtendedFlags()) { llvm::SmallVector arguments; auto metadataFn = constructSimpleCall(arguments); auto *call = IGF.Builder.CreateCall(metadataFn, arguments); @@ -1669,7 +1680,7 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF, assert(metadataDifferentiabilityKind.isDifferentiable()); diffKindVal = llvm::ConstantInt::get( IGF.IGM.SizeTy, metadataDifferentiabilityKind.getIntValue()); - } else if (type->getGlobalActor()) { + } else if (type->getGlobalActor() || flags.hasExtendedFlags()) { diffKindVal = llvm::ConstantInt::get( IGF.IGM.SizeTy, FunctionMetadataDifferentiabilityKind::NonDifferentiable); @@ -1695,10 +1706,27 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF, if (Type globalActor = type->getGlobalActor()) { arguments.push_back( IGF.emitAbstractTypeMetadataRef(globalActor->getCanonicalType())); + } else if (flags.hasExtendedFlags()) { + arguments.push_back(llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy)); + } + + if (flags.hasExtendedFlags()) { + auto extFlagsVal = llvm::ConstantInt::get(IGF.IGM.Int32Ty, + extFlags.getIntValue()); + arguments.push_back(extFlagsVal); + } + + if (Type thrownError = type->getThrownError()) { + arguments.push_back( + IGF.emitAbstractTypeMetadataRef(thrownError->getCanonicalType())); + } else if (flags.hasExtendedFlags()) { + arguments.push_back(llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy)); } auto getMetadataFn = - type->getGlobalActor() + flags.hasExtendedFlags() + ? IGF.IGM.getGetFunctionMetadataExtendedFunctionPointer() + : type->getGlobalActor() ? (IGF.IGM.isConcurrencyAvailable() ? IGF.IGM .getGetFunctionMetadataGlobalActorFunctionPointer() diff --git a/stdlib/public/RemoteInspection/TypeRef.cpp b/stdlib/public/RemoteInspection/TypeRef.cpp index bf367ab6a574..7563a6a864a5 100644 --- a/stdlib/public/RemoteInspection/TypeRef.cpp +++ b/stdlib/public/RemoteInspection/TypeRef.cpp @@ -779,8 +779,17 @@ class DemanglingForTypeRef Dem); } - if (F->getFlags().isThrowing()) - funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + if (F->getFlags().isThrowing()) { + if (auto thrownError = F->getThrownError()) { + auto node = Dem.createNode(Node::Kind::TypedThrowsAnnotation); + auto thrownErrorNode = visit(thrownError); + node->addChild(thrownErrorNode, Dem); + funcNode->addChild(node, Dem); + } else { + funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + } + } + if (F->getFlags().isSendable()) { funcNode->addChild( Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem); @@ -1166,12 +1175,16 @@ class ThickenMetatype if (F->getGlobalActor()) globalActorType = visit(F->getGlobalActor()); + const TypeRef *thrownErrorType = nullptr; + if (F->getThrownError()) + thrownErrorType = visit(F->getThrownError()); + auto SubstitutedResult = visit(F->getResult()); return FunctionTypeRef::create(Builder, SubstitutedParams, SubstitutedResult, F->getFlags(), F->getDifferentiabilityKind(), - globalActorType); + globalActorType, thrownErrorType); } const TypeRef * @@ -1303,10 +1316,14 @@ class TypeRefSubstitution if (F->getGlobalActor()) globalActorType = visit(F->getGlobalActor()); + const TypeRef *thrownErrorType = nullptr; + if (F->getThrownError()) + thrownErrorType = visit(F->getThrownError()); + return FunctionTypeRef::create(Builder, SubstitutedParams, SubstitutedResult, F->getFlags(), F->getDifferentiabilityKind(), - globalActorType); + globalActorType, thrownErrorType); } const TypeRef * diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index 7b5936129494..8c3a441ae04c 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -805,8 +805,18 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type, (Node::IndexType)MangledDifferentiabilityKind::Linear), Dem); break; } - if (func->isThrowing()) - funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + if (func->isThrowing()) { + if (auto thrownError = func->getThrownError()) { + auto thrownErrorTypeNode = + _swift_buildDemanglingForMetadata(thrownError, Dem); + NodePointer thrownErrorNode = + Dem.createNode(Node::Kind::TypedThrowsAnnotation); + thrownErrorNode->addChild(thrownErrorTypeNode, Dem); + funcNode->addChild(thrownErrorNode, Dem); + } else { + funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + } + } if (func->isSendable()) { funcNode->addChild( Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem); diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index f9b5b18407a9..b503d28788dc 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -1354,11 +1354,14 @@ class FunctionCacheEntry { const FunctionTypeFlags Flags; const FunctionMetadataDifferentiabilityKind DifferentiabilityKind; const Metadata *const *Parameters; - const uint32_t *ParameterFlags; + const ::ParameterFlags *ParameterFlags; const Metadata *Result; const Metadata *GlobalActor; + const ExtendedFunctionTypeFlags ExtFlags; + const Metadata *ThrownError; FunctionTypeFlags getFlags() const { return Flags; } + ExtendedFunctionTypeFlags getExtFlags() const { return ExtFlags; } FunctionMetadataDifferentiabilityKind getDifferentiabilityKind() const { return DifferentiabilityKind; @@ -1370,23 +1373,24 @@ class FunctionCacheEntry { } const Metadata *getResult() const { return Result; } - const uint32_t *getParameterFlags() const { + const ::ParameterFlags *getParameterFlags() const { return ParameterFlags; } ::ParameterFlags getParameterFlags(unsigned index) const { assert(index < Flags.getNumParameters()); - auto flags = Flags.hasParameterFlags() ? ParameterFlags[index] : 0; - return ParameterFlags::fromIntValue(flags); + return Flags.hasParameterFlags() ? ParameterFlags[index] : ::ParameterFlags(); } const Metadata *getGlobalActor() const { return GlobalActor; } + const Metadata *getThrownError() const { return ThrownError; } friend llvm::hash_code hash_value(const Key &key) { auto hash = llvm::hash_combine( key.Flags.getIntValue(), key.DifferentiabilityKind.getIntValue(), - key.Result, key.GlobalActor); + key.Result, key.GlobalActor, + key.ExtFlags.getIntValue(), key.ThrownError); for (unsigned i = 0, e = key.getFlags().getNumParameters(); i != e; ++i) { hash = llvm::hash_combine(hash, key.getParameter(i)); hash = llvm::hash_combine(hash, key.getParameterFlags(i).getIntValue()); @@ -1411,6 +1415,10 @@ class FunctionCacheEntry { return false; if (key.getGlobalActor() != Data.getGlobalActor()) return false; + if (key.getExtFlags().getIntValue() != Data.getExtendedFlags().getIntValue()) + return false; + if (key.getThrownError() != Data.getThrownError()) + return false; for (unsigned i = 0, e = key.getFlags().getNumParameters(); i != e; ++i) { if (key.getParameter(i) != Data.getParameter(i)) return false; @@ -1424,29 +1432,31 @@ class FunctionCacheEntry { friend llvm::hash_code hash_value(const FunctionCacheEntry &value) { Key key = {value.Data.Flags, value.Data.getDifferentiabilityKind(), value.Data.getParameters(), value.Data.getParameterFlags(), - value.Data.ResultType, value.Data.getGlobalActor()}; + value.Data.ResultType, value.Data.getGlobalActor(), + value.Data.getExtendedFlags(), value.Data.getThrownError()}; return hash_value(key); } static size_t getExtraAllocationSize(const Key &key) { - return getExtraAllocationSize(key.Flags); + return getExtraAllocationSize(key.Flags, key.ExtFlags); } size_t getExtraAllocationSize() const { - return getExtraAllocationSize(Data.Flags); + return getExtraAllocationSize(Data.Flags, Data.getExtendedFlags()); } - static size_t getExtraAllocationSize(const FunctionTypeFlags &flags) { + static size_t getExtraAllocationSize(const FunctionTypeFlags &flags, + const ExtendedFunctionTypeFlags &extFlags) { const auto numParams = flags.getNumParameters(); - auto size = numParams * sizeof(FunctionTypeMetadata::Parameter); - if (flags.hasParameterFlags()) - size += numParams * sizeof(uint32_t); - if (flags.isDifferentiable()) - size = roundUpToAlignment(size, sizeof(void *)) + - sizeof(FunctionMetadataDifferentiabilityKind); - if (flags.hasGlobalActor()) - size = roundUpToAlignment(size, sizeof(void *)) + sizeof(Metadata *); - return roundUpToAlignment(size, sizeof(void *)); + return FunctionTypeMetadata::additionalSizeToAlloc< + const Metadata *, ParameterFlags, FunctionMetadataDifferentiabilityKind, + FunctionGlobalActorMetadata, ExtendedFunctionTypeFlags, + FunctionThrownErrorMetadata>(numParams, + flags.hasParameterFlags() ? numParams : 0, + flags.isDifferentiable() ? 1 : 0, + flags.hasGlobalActor() ? 1 : 0, + flags.hasExtendedFlags() ? 1 : 0, + extFlags.isTypedThrows() ? 1 : 0); } }; @@ -1507,9 +1517,13 @@ swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags, assert(!flags.hasGlobalActor() && "Global actor function type metadata should be obtained using " "'swift_getFunctionTypeMetadataGlobalActor'"); + assert(!flags.hasExtendedFlags() + && "Extended flags function type metadata should be obtained using " + "'swift_getExtendedFunctionTypeMetadata'"); FunctionCacheEntry::Key key = { flags, FunctionMetadataDifferentiabilityKind::NonDifferentiable, parameters, - parameterFlags, result, nullptr + reinterpret_cast(parameterFlags), result, nullptr, + ExtendedFunctionTypeFlags(), nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1522,10 +1536,15 @@ swift::swift_getFunctionTypeMetadataDifferentiable( assert(!flags.hasGlobalActor() && "Global actor function type metadata should be obtained using " "'swift_getFunctionTypeMetadataGlobalActor'"); + assert(!flags.hasExtendedFlags() + && "Extended flags function type metadata should be obtained using " + "'swift_getExtendedFunctionTypeMetadata'"); assert(flags.isDifferentiable()); assert(diffKind.isDifferentiable()); FunctionCacheEntry::Key key = { - flags, diffKind, parameters, parameterFlags, result, nullptr + flags, diffKind, parameters, + reinterpret_cast(parameterFlags), result, nullptr, + ExtendedFunctionTypeFlags(), nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1535,9 +1554,29 @@ swift::swift_getFunctionTypeMetadataGlobalActor( FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind, const Metadata *const *parameters, const uint32_t *parameterFlags, const Metadata *result, const Metadata *globalActor) { - assert(flags.hasGlobalActor()); + assert(!flags.hasExtendedFlags() + && "Extended flags function type metadata should be obtained using " + "'swift_getExtendedFunctionTypeMetadata'"); FunctionCacheEntry::Key key = { - flags, diffKind, parameters, parameterFlags, result, globalActor + flags, diffKind, parameters, + reinterpret_cast(parameterFlags), result, + globalActor, ExtendedFunctionTypeFlags(), nullptr + }; + return &FunctionTypes.getOrInsert(key).first->Data; +} + +const FunctionTypeMetadata * +swift::swift_getExtendedFunctionTypeMetadata( + FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind, + const Metadata *const *parameters, const uint32_t *parameterFlags, + const Metadata *result, const Metadata *globalActor, + ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError) { + assert(flags.hasExtendedFlags() || extFlags.getIntValue() == 0); + assert(flags.hasExtendedFlags() || thrownError == nullptr); + FunctionCacheEntry::Key key = { + flags, diffKind, parameters, + reinterpret_cast(parameterFlags), result, + globalActor, extFlags, thrownError }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1591,11 +1630,18 @@ FunctionCacheEntry::FunctionCacheEntry(const Key &key) { *Data.getGlobalActorAddr() = key.getGlobalActor(); if (flags.isDifferentiable()) *Data.getDifferentiabilityKindAddress() = key.getDifferentiabilityKind(); + if (flags.hasExtendedFlags()) { + auto extFlags = key.getExtFlags(); + *Data.getExtendedFlagsAddr() = extFlags; + + if (extFlags.isTypedThrows()) + *Data.getThrownErrorAddr() = key.getThrownError(); + } for (unsigned i = 0; i < numParameters; ++i) { Data.getParameters()[i] = key.getParameter(i); if (flags.hasParameterFlags()) - Data.getParameterFlags()[i] = key.getParameterFlags(i).getIntValue(); + Data.getParameterFlags()[i] = key.getParameterFlags(i); } } diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index e2813d9cc3d7..9401c36abbeb 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -1934,7 +1934,7 @@ class DecodedMetadataBuilder { llvm::ArrayRef> params, BuiltType result, FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind, - BuiltType globalActorType) const { + BuiltType globalActorType, BuiltType thrownError) const { assert( (flags.isDifferentiable() && diffKind.isDifferentiable()) || (!flags.isDifferentiable() && !diffKind.isDifferentiable())); @@ -1969,20 +1969,18 @@ class DecodedMetadataBuilder { flags = flags.withGlobalActor(true); } + ExtendedFunctionTypeFlags extFlags; + if (thrownError) { + flags = flags.withExtendedFlags(true); + extFlags = extFlags.withTypedThrows(true); + } + return BuiltType( - flags.hasGlobalActor() - ? swift_getFunctionTypeMetadataGlobalActor(flags, diffKind, paramTypes.data(), + swift_getExtendedFunctionTypeMetadata( + flags, diffKind, paramTypes.data(), flags.hasParameterFlags() ? paramFlags.data() : nullptr, - result.getMetadata(), globalActorType.getMetadata()) - : flags.isDifferentiable() - ? swift_getFunctionTypeMetadataDifferentiable( - flags, diffKind, paramTypes.data(), - flags.hasParameterFlags() ? paramFlags.data() : nullptr, - result.getMetadata()) - : swift_getFunctionTypeMetadata( - flags, paramTypes.data(), - flags.hasParameterFlags() ? paramFlags.data() : nullptr, - result.getMetadata())); + result.getMetadata(), globalActorType.getMetadataOrNull(), extFlags, + thrownError.getMetadataOrNull())); } TypeLookupErrorOr createImplFunctionType( diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index 4862010a94fa..f9d90ccfb953 100644 --- a/test/Demangle/Inputs/manglings.txt +++ b/test/Demangle/Inputs/manglings.txt @@ -449,3 +449,4 @@ $s9MacroUser016testFreestandingA9ExpansionyyF4Foo3L_V23bitwidthNumberedStructsfM @__swiftmacro_9MacroUser16MemberNotCoveredV33_4361AD9339943F52AE6186DD51E04E91Ll0dE0fMf0_ ---> freestanding macro expansion #2 of NotCovered(in _4361AD9339943F52AE6186DD51E04E91) in MacroUser.MemberNotCovered $sxSo8_NSRangeVRlzCRl_Cr0_llySo12ModelRequestCyxq_GIsPetWAlYl_TC ---> coroutine continuation prototype for @escaping @convention(thin) @convention(witness_method) @yield_once @substituted (@inout A) -> (@yields @inout __C._NSRange) for <__C.ModelRequest> $SyyySGSS_IIxxxxx____xsIyFSySIxx_@xIxx____xxI ---> $SyyySGSS_IIxxxxx____xsIyFSySIxx_@xIxx____xxI +$s12typed_throws15rethrowConcreteyyAA7MyErrorOYKF --> typed_throws.rethrowConcrete() throws(typed_throws.MyError) -> () diff --git a/test/IRGen/typed_throws.swift b/test/IRGen/typed_throws.swift new file mode 100644 index 000000000000..a10a9f4550ba --- /dev/null +++ b/test/IRGen/typed_throws.swift @@ -0,0 +1,36 @@ +// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-experimental-feature TypedThrows -disable-availability-checking -runtime-compatibility-version none -target %module-target-future | %FileCheck %s --check-prefix=CHECK-MANGLE + +// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-experimental-feature TypedThrows -disable-availability-checking -runtime-compatibility-version 5.8 -disable-concrete-type-metadata-mangled-name-accessors | %FileCheck %s --check-prefix=CHECK-NOMANGLE + + +enum MyBigError: Error { + case epicFail +} + + +// CHECK-MANGLE: @"$s12typed_throws1XVAA1PAAWP" = hidden global [2 x ptr] [ptr @"$s12typed_throws1XVAA1PAAMc", ptr getelementptr inbounds (i8, ptr @"symbolic ySi_____YKc 12typed_throws10MyBigErrorO", {{i32|i64}} 1)] +struct X: P { + typealias A = (Int) throws(MyBigError) -> Void +} + +func requiresP(_: T.Type) { } +func createsP() { + requiresP(X.self) +} + +// CHECK-LABEL: define {{.*}}hidden swiftcc ptr @"$s12typed_throws13buildMetatypeypXpyF"() +func buildMetatype() -> Any.Type { + typealias Fn = (Int) throws(MyBigError) -> Void + + // CHECK-MANGLE: __swift_instantiateConcreteTypeFromMangledName(ptr @"$sySi12typed_throws10MyBigErrorOYKcMD + + // CHECK-NOMANGLE: call swiftcc %swift.metadata_response @"$sySi12typed_throws10MyBigErrorOYKcMa" + return Fn.self +} + +// CHECK-NOMANGLE: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sySi12typed_throws10MyBigErrorOYKcMa" +// CHECK: call ptr @swift_getExtendedFunctionTypeMetadata({{i32|i64}} 2231369729, {{i32|i64}} 0, ptr [[PARAMS:%.*]], ptr null, ptr getelementptr inbounds (%swift.full_existential_type, ptr @"$sytN", i32 0, i32 1), ptr null, i32 1, ptr getelementptr inbounds (<{ ptr, ptr, i64, ptr }>, ptr {{.*}}@"$s12typed_throws10MyBigErrorOMf" + +protocol P { + associatedtype A +} diff --git a/test/Runtime/demangleToMetadata.swift b/test/Runtime/demangleToMetadata.swift index f904757d3543..20142c1c63d8 100644 --- a/test/Runtime/demangleToMetadata.swift +++ b/test/Runtime/demangleToMetadata.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift -Xfrontend -disable-availability-checking -parse-stdlib %s -module-name main -o %t/a.out +// RUN: %target-build-swift -Xfrontend -disable-availability-checking -parse-stdlib -enable-experimental-feature TypedThrows %s -module-name main -o %t/a.out // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out // REQUIRES: executable_test @@ -522,5 +522,18 @@ if #available(SwiftStdlib 5.1, *) { } } +enum MyBigError: Error { + case epicFail +} + +if #available(SwiftStdlib 5.11, *) { + DemangleToMetadataTests.test("typed throws") { + typealias Fn = (Int) throws(MyBigError) -> Void + expectEqual("ySi4main10MyBigErrorOYKc", _mangledTypeName(Fn.self)!) + print("Looking up the typed throws... \(_typeByName("ySi4main10MyBigErrorOYKc"))") + expectEqual(Fn.self, _typeByName("ySi4main10MyBigErrorOYKc")!) + } +} + runAllTests() diff --git a/test/SILGen/typed_throws.swift b/test/SILGen/typed_throws.swift index 2b7a9b23f974..31957db2bf78 100644 --- a/test/SILGen/typed_throws.swift +++ b/test/SILGen/typed_throws.swift @@ -11,10 +11,10 @@ enum MyBigError: Error { func throwsMyBigError() throws(MyBigError) { } -// CHECK: sil hidden [ossa] @$s12typed_throws20doesNotThrowConcreteyyKF : $@convention(thin) () -> @error MyError +// CHECK: sil hidden [ossa] @$s12typed_throws20doesNotThrowConcreteyyAA7MyErrorOYKF : $@convention(thin) () -> @error MyError func doesNotThrowConcrete() throws(MyError) { } -// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws0B8ConcreteyyKF : $@convention(thin) () -> @error MyError +// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws0B8ConcreteyyAA7MyErrorOYKF : $@convention(thin) () -> @error MyError func throwsConcrete() throws(MyError) { // CHECK: [[ERROR:%[0-9]+]] = enum $MyError, #MyError.fail!enumelt // CHECK-NOT: builtin "willThrow" @@ -22,7 +22,7 @@ func throwsConcrete() throws(MyError) { throw .fail } -// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws15rethrowConcreteyyKF +// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws15rethrowConcreteyyAA7MyErrorOYKF func rethrowConcrete() throws(MyError) { // CHECK: try_apply [[FN:%[0-9]+]]() : $@convention(thin) () -> @error MyError, normal [[NORMALBB:bb[0-9]+]], error [[ERRORBB:bb[0-9]+]] // CHECK: [[ERRORBB]]([[ERROR:%[0-9]+]] : $MyError) @@ -85,7 +85,7 @@ func throwsOneOrTheOtherWithRethrow() throws { // CHECK-LABEL: sil hidden [ossa] @$s12typed_throws0B26ConcreteWithDoCatchRethrowyyKF : $@convention(thin) () -> @error any Error func throwsConcreteWithDoCatchRethrow() throws { do { - // CHECK: [[FN:%[0-9]+]] = function_ref @$s12typed_throws0B8ConcreteyyKF : $@convention(thin) () -> @error MyError + // CHECK: [[FN:%[0-9]+]] = function_ref @$s12typed_throws0B8ConcreteyyAA7MyErrorOYKF : $@convention(thin) () -> @error MyError // CHECK: try_apply [[FN]]() : $@convention(thin) () -> @error MyError, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] try throwsConcrete() @@ -100,10 +100,10 @@ func throwsConcreteWithDoCatchRethrow() throws { // CHECK: throw [[ERR:%[0-9]+]] : $any Error } -// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws0B31ConcreteWithDoCatchTypedRethrowyyKF : $@convention(thin) () -> @error MyError +// CHECK-LABEL: sil hidden [ossa] @$s12typed_throws0B31ConcreteWithDoCatchTypedRethrowyyAA7MyErrorOYKF : $@convention(thin) () -> @error MyError func throwsConcreteWithDoCatchTypedRethrow() throws(MyError) { do { - // CHECK: [[FN:%[0-9]+]] = function_ref @$s12typed_throws0B8ConcreteyyKF : $@convention(thin) () -> @error MyError + // CHECK: [[FN:%[0-9]+]] = function_ref @$s12typed_throws0B8ConcreteyyAA7MyErrorOYKF : $@convention(thin) () -> @error MyError // CHECK: try_apply [[FN]]() : $@convention(thin) () -> @error MyError, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] try throwsConcrete() diff --git a/test/SILGen/typed_throws_generic.swift b/test/SILGen/typed_throws_generic.swift index ccb1720f8340..d14e32c1cdf8 100644 --- a/test/SILGen/typed_throws_generic.swift +++ b/test/SILGen/typed_throws_generic.swift @@ -2,5 +2,5 @@ public func genericThrows(_: () throws(E) -> ()) throws(E) -> () {} -// CHECK-LABEL: sil [ossa] @$s20typed_throws_generic0C6ThrowsyyyyKXEKs5ErrorRzlF : $@convention(thin) (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> () -> @error_indirect τ_0_0 for ) -> @error_indirect E { -// CHECK: bb0(%0 : $*E, %1 : @guaranteed $@noescape @callee_guaranteed @substituted <τ_0_0> () -> @error_indirect τ_0_0 for ): \ No newline at end of file +// CHECK-LABEL: sil [ossa] @$s20typed_throws_generic0C6ThrowsyyyyxYKXExYKs5ErrorRzlF : $@convention(thin) (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0> () -> @error_indirect τ_0_0 for ) -> @error_indirect E { +// CHECK: bb0(%0 : $*E, %1 : @guaranteed $@noescape @callee_guaranteed @substituted <τ_0_0> () -> @error_indirect τ_0_0 for ): diff --git a/unittests/Reflection/TypeRef.cpp b/unittests/Reflection/TypeRef.cpp index 670822f03796..7d262ef43166 100644 --- a/unittests/Reflection/TypeRef.cpp +++ b/unittests/Reflection/TypeRef.cpp @@ -135,23 +135,23 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) { auto F1 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F2 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F3 = Builder.createFunctionType( Parameters2, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F1, F2); EXPECT_NE(F2, F3); auto F4 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withThrows(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F5 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withThrows(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F4, F5); EXPECT_NE(F4, F1); @@ -165,42 +165,42 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) { auto F6 = Builder.createFunctionType( {Param1.withFlags(inoutFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F6_1 = Builder.createFunctionType( {Param1.withFlags(inoutFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F6, F6_1); auto F7 = Builder.createFunctionType( {Param1.withFlags(variadicFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F7_1 = Builder.createFunctionType( {Param1.withFlags(variadicFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F7, F7_1); auto F8 = Builder.createFunctionType( {Param1.withFlags(sharedFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F8_1 = Builder.createFunctionType( {Param1.withFlags(sharedFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F8, F8_1); auto F9 = Builder.createFunctionType( {Param1.withFlags(ownedFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F9_1 = Builder.createFunctionType( {Param1.withFlags(ownedFlags)}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F9, F9_1); auto F10 = Builder.createFunctionType( {Param1}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F10_1 = Builder.createFunctionType( {Param1.withLabel("foo")}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_NE(F10, F10_1); EXPECT_NE(F6, F7); @@ -216,10 +216,10 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) { auto VoidVoid1 = Builder.createFunctionType(VoidParams, VoidResult, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto VoidVoid2 = Builder.createFunctionType(VoidParams, VoidResult, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(VoidVoid1, VoidVoid2); EXPECT_NE(VoidVoid1, F1); @@ -227,39 +227,39 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) { // Test escaping. auto F11 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withEscaping(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F12 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withEscaping(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F13 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withEscaping(false), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F11, F12); EXPECT_NE(F11, F13); // Test sendable. auto F14 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withConcurrent(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F15 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withConcurrent(true), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); auto F16 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withConcurrent(false), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); EXPECT_EQ(F14, F15); EXPECT_NE(F14, F16); // Test differentiable. auto F17 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withDifferentiable(true), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); auto F18 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withDifferentiable(true), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); auto F19 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withDifferentiable(false), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); EXPECT_EQ(F17, F18); EXPECT_NE(F17, F19); @@ -269,13 +269,13 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) { parameters[1].setNoDerivative(); auto f1 = Builder.createFunctionType( parameters, Result, FunctionTypeFlags().withDifferentiable(true), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); auto f2 = Builder.createFunctionType( parameters, Result, FunctionTypeFlags().withDifferentiable(true), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); auto f3 = Builder.createFunctionType( Parameters1, Result, FunctionTypeFlags().withDifferentiable(true), - FunctionMetadataDifferentiabilityKind::Reverse, nullptr); + FunctionMetadataDifferentiabilityKind::Reverse, nullptr, nullptr); EXPECT_EQ(f1, f2); EXPECT_NE(f1, f3); } @@ -522,7 +522,7 @@ TEST(TypeRefTest, DeriveSubstitutions) { ArrayRef()); auto Func = Builder.createFunctionType( {Nominal}, Result, FunctionTypeFlags(), - FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr); + FunctionMetadataDifferentiabilityKind::NonDifferentiable, nullptr, nullptr); TypeRefDecl SubstOneName("subst1"); auto SubstOne = Builder.createNominalType(SubstOneName, /*parent*/ nullptr);