From 4da1032f938e25b7a36b8139ac01d94fbc8abff9 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Oct 2023 15:39:15 -0700 Subject: [PATCH 1/4] Add name mangling support for functions with a thrown error type --- docs/ABI/Mangling.rst | 3 + include/swift/AST/ASTDemangler.h | 3 +- include/swift/Demangling/DemangleNodes.def | 1 + include/swift/Demangling/TypeDecoder.h | 22 ++++++- include/swift/Remote/MetadataReader.h | 5 +- include/swift/RemoteInspection/TypeRef.h | 19 ++++-- .../swift/RemoteInspection/TypeRefBuilder.h | 6 +- lib/AST/ASTDemangler.cpp | 6 +- lib/AST/ASTMangler.cpp | 10 +++- lib/Demangling/Demangler.cpp | 11 +++- lib/Demangling/NodePrinter.cpp | 27 ++++++--- lib/Demangling/OldRemangler.cpp | 5 ++ lib/Demangling/Remangler.cpp | 6 ++ stdlib/public/RemoteInspection/TypeRef.cpp | 13 +++- stdlib/public/runtime/Demangle.cpp | 1 + stdlib/public/runtime/MetadataLookup.cpp | 4 +- test/Demangle/Inputs/manglings.txt | 1 + test/SILGen/typed_throws.swift | 12 ++-- test/SILGen/typed_throws_generic.swift | 4 +- unittests/Reflection/TypeRef.cpp | 60 +++++++++---------- 20 files changed, 152 insertions(+), 67 deletions(-) diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst index 9534d643eb168..fafa64f649978 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/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 794a31cf4b0a4..18c448e2b4b14 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 9ad0b3d9066fb..f0bea551d6f20 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 6bc0e5b154d66..10145d0b5fd90 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 80464874f5410..bac581e8bf773 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -1001,8 +1001,11 @@ class MetadataReader { #undef CASE } + BuiltType thrownError = BuiltType(); + // FIXME: Read from metadata. + 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 54f81535cc8c1..28491c67719ce 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 2f97fdefee3c2..56d95f84769a4 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/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 80659a10c9608..1a89a1b2adde1 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 ecc945de563cd..3c0ab1d8b0d97 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/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index c685f2ecb1ce7..6b89321c92a4e 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 71c1a70353ae6..a2f102213c172 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 cde432f567e4a..0ebb7645577b5 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 e1a4a8e21de40..d1fecfd927d4c 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/stdlib/public/RemoteInspection/TypeRef.cpp b/stdlib/public/RemoteInspection/TypeRef.cpp index bf367ab6a5743..4d57bcff11e55 100644 --- a/stdlib/public/RemoteInspection/TypeRef.cpp +++ b/stdlib/public/RemoteInspection/TypeRef.cpp @@ -781,6 +781,7 @@ class DemanglingForTypeRef if (F->getFlags().isThrowing()) funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + // FIXME: TypedThrowsAnnotation if (F->getFlags().isSendable()) { funcNode->addChild( Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem); @@ -1166,12 +1167,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 +1308,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 7b5936129494e..47c2c8085f8ec 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -807,6 +807,7 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type, } if (func->isThrowing()) funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); + // FIXME: TypedThrowsAnnotation if (func->isSendable()) { funcNode->addChild( Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem); diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index e2813d9cc3d76..a15b08e875fff 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,6 +1969,8 @@ class DecodedMetadataBuilder { flags = flags.withGlobalActor(true); } + // FIXME: thrownError + return BuiltType( flags.hasGlobalActor() ? swift_getFunctionTypeMetadataGlobalActor(flags, diffKind, paramTypes.data(), diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index 4862010a94fa7..f9d90ccfb9532 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/SILGen/typed_throws.swift b/test/SILGen/typed_throws.swift index 2b7a9b23f9741..31957db2bf78e 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 ccb1720f83404..d14e32c1cdf8b 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 670822f037969..7d262ef43166a 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); From e82854d860ce0f1492d0af053cdf2460a383d234 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Oct 2023 18:45:58 -0700 Subject: [PATCH 2/4] Reimplement TargetFunctionTypeMetadata using TrailingObjects The layout is the same, but this eliminates the handwritten address computations. --- include/swift/ABI/Metadata.h | 98 ++++++++++++++++++++---------- stdlib/public/runtime/Metadata.cpp | 17 +++--- 2 files changed, 74 insertions(+), 41 deletions(-) diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 99fb5ac17e786..83e26c470c2b9 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -1459,21 +1459,70 @@ struct TargetEnumMetadata : public TargetValueMetadata { }; using EnumMetadata = TargetEnumMetadata; +template +struct TargetFunctionGlobalActorMetadata { + ConstTargetMetadataPointer GlobalActorType; +}; + /// The structure of function type metadata. template -struct TargetFunctionTypeMetadata : public TargetMetadata { +struct TargetFunctionTypeMetadata : public TargetMetadata, + swift::ABI::TrailingObjects< + TargetFunctionTypeMetadata, + ConstTargetMetadataPointer, + ParameterFlags, + TargetFunctionMetadataDifferentiabilityKind, + TargetFunctionGlobalActorMetadata> { using StoredSize = typename Runtime::StoredSize; using Parameter = ConstTargetMetadataPointer; +private: + using TrailingObjects = + swift::ABI::TrailingObjects< + TargetFunctionTypeMetadata, + Parameter, + ParameterFlags, + TargetFunctionMetadataDifferentiabilityKind, + TargetFunctionGlobalActorMetadata>; + 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; + } + +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 +1532,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 { @@ -1507,32 +1555,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 +1581,18 @@ 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(); - - return *const_cast *>(this) - ->getGlobalActorAddr(); + auto globalActorAddr = + this->template getTrailingObjects>(); + return globalActorAddr->GlobalActorType; } }; using FunctionTypeMetadata = TargetFunctionTypeMetadata; diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index f9b5b18407a96..53d347e2f1e7e 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -1354,7 +1354,7 @@ 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; @@ -1370,14 +1370,13 @@ 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; } @@ -1509,7 +1508,7 @@ swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags, "'swift_getFunctionTypeMetadataGlobalActor'"); FunctionCacheEntry::Key key = { flags, FunctionMetadataDifferentiabilityKind::NonDifferentiable, parameters, - parameterFlags, result, nullptr + reinterpret_cast(parameterFlags), result, nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1525,7 +1524,8 @@ swift::swift_getFunctionTypeMetadataDifferentiable( assert(flags.isDifferentiable()); assert(diffKind.isDifferentiable()); FunctionCacheEntry::Key key = { - flags, diffKind, parameters, parameterFlags, result, nullptr + flags, diffKind, parameters, + reinterpret_cast(parameterFlags), result, nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1537,7 +1537,8 @@ swift::swift_getFunctionTypeMetadataGlobalActor( const Metadata *result, const Metadata *globalActor) { assert(flags.hasGlobalActor()); FunctionCacheEntry::Key key = { - flags, diffKind, parameters, parameterFlags, result, globalActor + flags, diffKind, parameters, + reinterpret_cast(parameterFlags), result, globalActor }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1595,7 +1596,7 @@ FunctionCacheEntry::FunctionCacheEntry(const Key &key) { 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); } } From 40e07cf900b0904bc6eaa3a5064dc9fe7641b43f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 29 Oct 2023 07:33:04 -0700 Subject: [PATCH 3/4] [Typed throws] IR generation and runtime support for function type metadata Extend function type metadata with an entry for the thrown error type, so that thrown error types are represented at runtime as well. Note that this required the introduction of "extended" function type flags into function type metadata, because we would have used the last bit. Do so, and define one extended flag bit as representing typed throws. Add `swift_getExtendedFunctionTypeMetadata` to the runtime to build function types that have the extended flags and a thrown error type. Teach IR generation to call this function to form the metadata, when appropriate. Introduce all of the runtime mangling/demangling support needed for thrown error types. --- include/swift/ABI/Metadata.h | 61 +++++++++++++++- include/swift/ABI/MetadataValues.h | 50 ++++++++++++- include/swift/AST/ASTContext.h | 7 ++ include/swift/Remote/MetadataReader.h | 5 +- include/swift/Runtime/Metadata.h | 8 +++ include/swift/Runtime/RuntimeFunctions.def | 25 +++++++ lib/AST/Availability.cpp | 9 +++ lib/Driver/DarwinToolChains.cpp | 2 + lib/Frontend/CompilerInvocation.cpp | 2 + lib/IRGen/GenReflection.cpp | 14 ++++ lib/IRGen/IRGenModule.cpp | 8 +++ lib/IRGen/MetadataRequest.cpp | 42 +++++++++-- stdlib/public/RemoteInspection/TypeRef.cpp | 14 +++- stdlib/public/runtime/Demangle.cpp | 15 +++- stdlib/public/runtime/Metadata.cpp | 81 +++++++++++++++++----- stdlib/public/runtime/MetadataLookup.cpp | 22 +++--- test/IRGen/typed_throws.swift | 38 ++++++++++ test/Runtime/demangleToMetadata.swift | 15 +++- 18 files changed, 369 insertions(+), 49 deletions(-) create mode 100644 test/IRGen/typed_throws.swift diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 83e26c470c2b9..2a5a1265b8709 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -1463,6 +1463,13 @@ template struct TargetFunctionGlobalActorMetadata { ConstTargetMetadataPointer GlobalActorType; }; +using FunctionGlobalActorMetadata = TargetFunctionGlobalActorMetadata; + +template +struct TargetFunctionThrownErrorMetadata { + ConstTargetMetadataPointer ThrownErrorType; +}; +using FunctionThrownErrorMetadata = TargetFunctionThrownErrorMetadata; /// The structure of function type metadata. template @@ -1472,7 +1479,9 @@ struct TargetFunctionTypeMetadata : public TargetMetadata, ConstTargetMetadataPointer, ParameterFlags, TargetFunctionMetadataDifferentiabilityKind, - TargetFunctionGlobalActorMetadata> { + TargetFunctionGlobalActorMetadata, + ExtendedFunctionTypeFlags, + TargetFunctionThrownErrorMetadata> { using StoredSize = typename Runtime::StoredSize; using Parameter = ConstTargetMetadataPointer; @@ -1483,7 +1492,9 @@ struct TargetFunctionTypeMetadata : public TargetMetadata, Parameter, ParameterFlags, TargetFunctionMetadataDifferentiabilityKind, - TargetFunctionGlobalActorMetadata>; + TargetFunctionGlobalActorMetadata, + ExtendedFunctionTypeFlags, + TargetFunctionThrownErrorMetadata>; friend TrailingObjects; template @@ -1516,6 +1527,16 @@ struct TargetFunctionTypeMetadata : public TargetMetadata, 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(); @@ -1548,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); @@ -1594,6 +1622,35 @@ struct TargetFunctionTypeMetadata : public TargetMetadata, 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; + } + + 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 019e1ed1a58f1..783825814d53d 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 c6a25ae8b3d68..a6f892029a243 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/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index bac581e8bf773..9b38e42e9b336 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -1002,7 +1002,10 @@ class MetadataReader { } BuiltType thrownError = BuiltType(); - // FIXME: Read from metadata. + if (Function->hasThrownError()) { + thrownError = readTypeFromMetadata(Function->getThrownError(), false, + recursion_limit); + } auto BuiltFunction = Builder.createFunctionType( Parameters, Result, flags, diffKind, globalActor, thrownError); diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 763469260fb69..7131a106db448 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 c4a2e265554ec..a3d6de1ebebd0 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/Availability.cpp b/lib/AST/Availability.cpp index 6486284f71aac..c7d0a1c2123b5 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/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index a4973310a1109..5324e706ff734 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 057173d09a81c..3cbe29bd8b172 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 301f0fe9b9efe..d5a974135601a 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 883bd744b07cb..edb91925e97d3 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 94014d1c4074b..e7b815d985fcd 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 4d57bcff11e55..7563a6a864a59 100644 --- a/stdlib/public/RemoteInspection/TypeRef.cpp +++ b/stdlib/public/RemoteInspection/TypeRef.cpp @@ -779,9 +779,17 @@ class DemanglingForTypeRef Dem); } - if (F->getFlags().isThrowing()) - funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); - // FIXME: TypedThrowsAnnotation + 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); diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index 47c2c8085f8ec..8c3a441ae04ce 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -805,9 +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); - // FIXME: TypedThrowsAnnotation + 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 53d347e2f1e7e..b503d28788dc4 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -1357,8 +1357,11 @@ class FunctionCacheEntry { 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; @@ -1380,12 +1383,14 @@ class FunctionCacheEntry { } 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()); @@ -1410,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; @@ -1423,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); } }; @@ -1506,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, - reinterpret_cast(parameterFlags), result, nullptr + reinterpret_cast(parameterFlags), result, nullptr, + ExtendedFunctionTypeFlags(), nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1521,11 +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, - reinterpret_cast(parameterFlags), result, nullptr + reinterpret_cast(parameterFlags), result, nullptr, + ExtendedFunctionTypeFlags(), nullptr }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1535,10 +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, + 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 + reinterpret_cast(parameterFlags), result, + globalActor, extFlags, thrownError }; return &FunctionTypes.getOrInsert(key).first->Data; } @@ -1592,6 +1630,13 @@ 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); diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index a15b08e875fff..9401c36abbebd 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -1969,22 +1969,18 @@ class DecodedMetadataBuilder { flags = flags.withGlobalActor(true); } - // FIXME: thrownError + 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/IRGen/typed_throws.swift b/test/IRGen/typed_throws.swift new file mode 100644 index 0000000000000..7a363d99d2bc7 --- /dev/null +++ b/test/IRGen/typed_throws.swift @@ -0,0 +1,38 @@ +// 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" + +// CHECK-NOMANGLE: declare extern_weak ptr @swift_getExtendedFunctionTypeMetadata + +protocol P { + associatedtype A +} diff --git a/test/Runtime/demangleToMetadata.swift b/test/Runtime/demangleToMetadata.swift index f904757d3543d..20142c1c63d85 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() From a5f41ce2661816e323fef2a672a2f24afed3c62d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 29 Oct 2023 14:39:09 -0700 Subject: [PATCH 4/4] Adjust test for non-Darwin --- test/IRGen/typed_throws.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/IRGen/typed_throws.swift b/test/IRGen/typed_throws.swift index 7a363d99d2bc7..a10a9f4550bac 100644 --- a/test/IRGen/typed_throws.swift +++ b/test/IRGen/typed_throws.swift @@ -31,8 +31,6 @@ func buildMetatype() -> Any.Type { // 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" -// CHECK-NOMANGLE: declare extern_weak ptr @swift_getExtendedFunctionTypeMetadata - protocol P { associatedtype A }