diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index 95e3c21662bbc..f623ef33f8db8 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -193,6 +193,7 @@ class Node { }; using IndexType = uint64_t; + using RemoteAddressType = std::pair; friend class NodeFactory; @@ -209,14 +210,20 @@ class Node { IndexType Index; NodePointer InlineChildren[2]; NodeVector Children; + RemoteAddressType RemoteAddress; }; Kind NodeKind; enum class PayloadKind : uint8_t { - None = 0, OneChild = 1, TwoChildren = 2, - Text, Index, ManyChildren + None = 0, + OneChild = 1, + TwoChildren = 2, + Text, + Index, + ManyChildren, + RemoteAddress }; PayloadKind NodePayloadKind; @@ -231,6 +238,10 @@ class Node { : NodeKind(k), NodePayloadKind(PayloadKind::Index) { Index = index; } + Node(Kind k, uint64_t remoteAddress, uint8_t addressSpace) + : NodeKind(k), NodePayloadKind(PayloadKind::RemoteAddress) { + RemoteAddress = {remoteAddress, addressSpace}; + } Node(const Node &) = delete; Node &operator=(const Node &) = delete; @@ -284,6 +295,14 @@ class Node { return Index; } + bool hasRemoteAddress() const { + return NodePayloadKind == PayloadKind::RemoteAddress; + } + std::pair getRemoteAddress() const { + assert(hasRemoteAddress()); + return RemoteAddress; + } + using iterator = const NodePointer *; size_t getNumChildren() const { diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h index 8a4a6f2722086..62f0298cf6e93 100644 --- a/include/swift/Demangling/Demangler.h +++ b/include/swift/Demangling/Demangler.h @@ -249,6 +249,12 @@ class NodeFactory { /// Creates a node of kind \p K with an \p Index payload. NodePointer createNode(Node::Kind K, Node::IndexType Index); + /// Creates a node of kind \p K with a \p RemoteAddress payload. + /// + /// These nodes are created and consumed by the reflection library. + NodePointer createNode(Node::Kind K, uint64_t RemoteAddress, + uint8_t AddressSpace); + /// Creates a node of kind \p K with a \p Text payload. /// /// The \p Text string must be already allocated with the Factory and therefore diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index 36ddfd841e23b..77bb3bc6ccd8e 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -573,6 +573,43 @@ void decodeRequirement( } } +/// Extract the protocol and requirement nodes from a shape symbol. +static inline std::pair +decodeShape(NodePointer Node) { + if (!Node || Node->getKind() != Node::Kind::Global || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + Node = Node->getChild(0); + if (Node && (Node->getKind() == Node::Kind::Uniquable) && + Node->getNumChildren() == 1) + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::ExtendedExistentialTypeShape || + Node->getNumChildren() != 2) + return {nullptr, nullptr}; + Node = Node->getChild(1); + if (!Node || Node->getKind() != Node::Kind::Type || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::ConstrainedExistential || + Node->getNumChildren() != 2) + return {nullptr, nullptr}; + NodePointer Requirements = Node->getChild(1); + if (!Requirements || Requirements->getKind() != + Node::Kind::ConstrainedExistentialRequirementList) + return {nullptr, nullptr}; + + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::Type || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + NodePointer Protocol = Node; + if (!Protocol) + return {nullptr, nullptr}; + + return {Protocol, Requirements}; +} + #define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \ TYPE_LOOKUP_ERROR_FMT("TypeDecoder.h:%u: Node kind %u \"%.*s\" - " Fmt, \ __LINE__, (unsigned)Node->getKind(), \ diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 51a4687815616..ece14f7d91b14 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -480,16 +480,13 @@ class MetadataReader { // Try to preserve a reference to an OpaqueTypeDescriptor // symbolically, since we'd like to read out and resolve the type ref // to the underlying type if available. - if (useOpaqueTypeSymbolicReferences - && context.isResolved() - && context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){ - // FIXME: this loses the address space. This can be fixed by adding an - // opaque field in Node that can store the address space. This - // wouldn't degrade performance as Node's address is part of an union - // which is 16 bytes longs + if (useOpaqueTypeSymbolicReferences && context.isResolved() && + context.getResolved()->getKind() == + ContextDescriptorKind::OpaqueType) { return dem.createNode( Node::Kind::OpaqueTypeDescriptorSymbolicReference, - context.getResolved().getRemoteAddress().getRawAddress()); + context.getResolved().getRemoteAddress().getRawAddress(), + context.getResolved().getRemoteAddress().getAddressSpace()); } return buildContextMangling(context, dem); @@ -504,15 +501,16 @@ class MetadataReader { // existential type shape. return dem.createNode( Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference, - resolved.getResolvedAddress().getRawAddress()); + resolved.getResolvedAddress().getRawAddress(), + resolved.getResolvedAddress().getAddressSpace()); } case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: { // The symbolic reference points at a non-unique extended // existential type shape. - // FIXME: this loses the address space. return dem.createNode( Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, - resolved.getResolvedAddress().getRawAddress()); + resolved.getResolvedAddress().getRawAddress(), + resolved.getResolvedAddress().getAddressSpace()); } case Demangle::SymbolicReferenceKind::ObjectiveCProtocol: { // 'resolved' points to a struct of two relative addresses. @@ -879,6 +877,73 @@ class MetadataReader { return resolver.swiftProtocol(Demangled); } + BuiltType readTypeFromShape( + RemoteAbsolutePointer shapeAddress, + std::function>(unsigned)> getArgs) { + RemoteAddress addr = shapeAddress.getResolvedAddress(); + ShapeRef Shape = readShape(addr); + if (!Shape) + return BuiltType(); + + assert(Shape->hasGeneralizationSignature()); + + // Pull out the existential type from the mangled type name. + Demangler dem; + auto mangledExistentialAddr = + resolveRelativeField(Shape, Shape->ExistentialType); + auto node = + readMangledName(mangledExistentialAddr, MangledNameKind::Type, dem); + if (!node) + return BuiltType(); + + BuiltType builtProto = decodeMangledType(node).getType(); + if (!builtProto) + return BuiltType(); + + if (auto builtArgs = getArgs(Shape->getGenSigArgumentLayoutSizeInWords())) { + // Build up a substitution map for the generalized signature. + BuiltGenericSignature sig = + decodeRuntimeGenericSignature(Shape, + Shape->getGeneralizationSignature()) + .getType(); + if (!sig) + return BuiltType(); + + BuiltSubstitutionMap subst = + Builder.createSubstitutionMap(sig, *builtArgs); + if (subst.empty()) + return BuiltType(); + + builtProto = Builder.subst(builtProto, subst); + if (!builtProto) + return BuiltType(); + } + + // Read the type expression to build up any remaining layers of + // existential metatype. + if (Shape->Flags.hasTypeExpression()) { + Demangler dem; + + // Read the mangled name. + auto mangledContextName = Shape->getTypeExpression(); + auto mangledNameAddress = + resolveRelativeField(Shape, mangledContextName->name); + auto node = + readMangledName(mangledNameAddress, MangledNameKind::Type, dem); + if (!node) + return BuiltType(); + + while (node->getKind() == Demangle::Node::Kind::Type && + node->hasChildren() && + node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype && + node->getChild(0)->getNumChildren()) { + builtProto = Builder.createExistentialMetatypeType(builtProto); + node = node->getChild(0)->getChild(0); + } + } + return builtProto; + } + /// Given a remote pointer to metadata, attempt to turn it into a type. BuiltType readTypeFromMetadata(RemoteAddress MetadataAddress, @@ -1091,82 +1156,27 @@ class MetadataReader { } case MetadataKind::ExtendedExistential: { auto Exist = cast>(Meta); - // Read the shape for this existential. - RemoteAddress shapeAddress = stripSignedPointer(Exist->Shape); - ShapeRef Shape = readShape(shapeAddress); - if (!Shape) - return BuiltType(); - - const unsigned shapeArgumentCount - = Shape->getGenSigArgumentLayoutSizeInWords(); - // Pull out the arguments to the generalization signature. - assert(Shape->hasGeneralizationSignature()); - std::vector builtArgs; - for (unsigned i = 0; i < shapeArgumentCount; ++i) { - auto remoteArg = Exist->getGeneralizationArguments()[i]; - auto remoteArgAddress = - RemoteAddress(remoteArg, MetadataAddress.getAddressSpace()); - auto builtArg = - readTypeFromMetadata(remoteArgAddress, false, recursion_limit); - if (!builtArg) - return BuiltType(); - builtArgs.push_back(builtArg); - } - - // Pull out the existential type from the mangled type name. - Demangler dem; - auto mangledExistentialAddr = - resolveRelativeField(Shape, Shape->ExistentialType); - auto node = - readMangledName(mangledExistentialAddr, MangledNameKind::Type, dem); - if (!node) - return BuiltType(); - - BuiltType builtProto = decodeMangledType(node).getType(); - if (!builtProto) - return BuiltType(); - - // Build up a substitution map for the generalized signature. - BuiltGenericSignature sig = - decodeRuntimeGenericSignature(Shape, - Shape->getGeneralizationSignature()) - .getType(); - if (!sig) - return BuiltType(); - - BuiltSubstitutionMap subst = - Builder.createSubstitutionMap(sig, builtArgs); - if (subst.empty()) - return BuiltType(); - - builtProto = Builder.subst(builtProto, subst); - if (!builtProto) - return BuiltType(); - - // Read the type expression to build up any remaining layers of - // existential metatype. - if (Shape->Flags.hasTypeExpression()) { - Demangler dem; - - // Read the mangled name. - auto mangledContextName = Shape->getTypeExpression(); - auto mangledNameAddress = - resolveRelativeField(Shape, mangledContextName->name); - auto node = - readMangledName(mangledNameAddress, MangledNameKind::Type, dem); - if (!node) - return BuiltType(); - - while (node->getKind() == Demangle::Node::Kind::Type && - node->getNumChildren() && - node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype && - node->getChild(0)->getNumChildren()) { - builtProto = Builder.createExistentialMetatypeType(builtProto); - node = node->getChild(0)->getChild(0); - } - } + RemoteAddress shapeAddress = stripSignedPointer(Exist->Shape); + auto builtProto = readTypeFromShape( + RemoteAddress(shapeAddress), + [&](unsigned shapeArgumentCount) + -> std::optional> { + // Pull out the arguments to the generalization signature. + std::vector builtArgs; + for (unsigned i = 0; i < shapeArgumentCount; ++i) { + auto remoteArg = Exist->getGeneralizationArguments()[i]; + auto builtArg = readTypeFromMetadata( + remote::RemoteAddress(remoteArg, + shapeAddress.getAddressSpace()), + false, recursion_limit); + if (!builtArg) + return std::nullopt; + builtArgs.push_back(builtArg); + } + return builtArgs; + }); TypeCache[TypeCacheKey] = builtProto; return builtProto; } @@ -1405,51 +1415,51 @@ class MetadataReader { if (!address) return nullptr; + using ShapeHeader = TargetExtendedExistentialTypeShape; auto cached = ShapeCache.find(address); if (cached != ShapeCache.end()) - return ShapeRef(address, - reinterpret_cast *>( - cached->second.get())); + return ShapeRef( + address, reinterpret_cast(cached->second.get())); ExtendedExistentialTypeShapeFlags flags; if (!Reader->readBytes(address, (uint8_t *)&flags, sizeof(flags))) return nullptr; // Read the size of the requirement signature. - uint64_t reqSigGenericSize = 0; - uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader); + uint64_t descriptorSize; { - GenericContextDescriptorHeader header; - auto headerAddr = address + sizeof(flags); - - if (!Reader->readBytes(headerAddr, (uint8_t *)&header, sizeof(header))) + auto readResult = + Reader->readBytes(RemoteAddress(address), sizeof(ShapeHeader)); + if (!readResult) return nullptr; - - reqSigGenericSize = reqSigGenericSize - + (header.NumParams + 3u & ~3u) - + header.NumRequirements - * sizeof(TargetGenericRequirementDescriptor); - } - uint64_t typeExprSize = flags.hasTypeExpression() ? sizeof(StoredPointer) : 0; - uint64_t suggestedVWSize = flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0; - - uint64_t size = sizeof(ExtendedExistentialTypeShapeFlags) + - sizeof(TargetRelativeDirectPointer) + - genericHeaderSize + typeExprSize + suggestedVWSize + - reqSigGenericSize; - if (size > MaxMetadataSize) + auto shapeHeader = + reinterpret_cast(readResult.get()); + + // Read the size of the requirement signature. + uint64_t reqSigGenericSize = 0; + auto flags = shapeHeader->Flags; + auto &reqSigHeader = shapeHeader->ReqSigHeader; + reqSigGenericSize = + reqSigGenericSize + (reqSigHeader.NumParams + 3u & ~3u) + + reqSigHeader.NumRequirements * + sizeof(TargetGenericRequirementDescriptor); + uint64_t typeExprSize = + flags.hasTypeExpression() ? sizeof(StoredPointer) : 0; + uint64_t suggestedVWSize = + flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0; + + descriptorSize = sizeof(shapeHeader) + typeExprSize + suggestedVWSize + + reqSigGenericSize; + } + if (descriptorSize > MaxMetadataSize) return nullptr; - auto readResult = Reader->readBytes(address, size); + auto readResult = Reader->readBytes(RemoteAddress(address), descriptorSize); if (!readResult) return nullptr; - auto descriptor = - reinterpret_cast *>( - readResult.get()); + auto descriptor = reinterpret_cast(readResult.get()); - ShapeCache.insert( - std::make_pair(address, std::move(readResult))); + ShapeCache.insert(std::make_pair(address, std::move(readResult))); return ShapeRef(address, descriptor); } diff --git a/include/swift/RemoteInspection/TypeRef.h b/include/swift/RemoteInspection/TypeRef.h index 51093b9acc17f..354492a497b79 100644 --- a/include/swift/RemoteInspection/TypeRef.h +++ b/include/swift/RemoteInspection/TypeRef.h @@ -731,6 +731,64 @@ class ConstrainedExistentialTypeRef final : public TypeRef { } }; +class SymbolicExtendedExistentialTypeRef final : public TypeRef { + const ProtocolCompositionTypeRef *Protocol; + std::vector Requirements; + std::vector Arguments; + ExtendedExistentialTypeShapeFlags Flags; + + static TypeRefID Profile(const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Arguments, + ExtendedExistentialTypeShapeFlags Flags) { + TypeRefID ID; + ID.addPointer(Protocol); + for (auto reqt : Requirements) { + ID.addPointer(reqt.getFirstType()); + if (reqt.getKind() != RequirementKind::Layout) + ID.addPointer(reqt.getSecondType()); + else + ID.addInteger( + unsigned(0)); // FIXME: Layout constraints aren't implemented yet + ID.addInteger(unsigned(reqt.getKind())); + } + + for (auto &Arg : Arguments) + ID.addPointer(Arg); + return ID; + } + +public: + SymbolicExtendedExistentialTypeRef( + const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Args, + ExtendedExistentialTypeShapeFlags Flags) + : TypeRef(TypeRefKind::SymbolicExtendedExistential), Protocol(Protocol), + Requirements(Requirements), Arguments(Args), Flags(Flags) {} + + template + static const SymbolicExtendedExistentialTypeRef * + create(Allocator &A, const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Args, + ExtendedExistentialTypeShapeFlags Flags) { + FIND_OR_CREATE_TYPEREF(A, SymbolicExtendedExistentialTypeRef, Protocol, + Requirements, Args, Flags); + } + + const ProtocolCompositionTypeRef *getProtocol() const { return Protocol; } + llvm::ArrayRef getRequirements() const { + return Requirements; + } + llvm::ArrayRef getArguments() const { return Arguments; } + ExtendedExistentialTypeShapeFlags getFlags() const { return Flags; } + + static bool classof(const TypeRef *TR) { + return TR->getKind() == TypeRefKind::SymbolicExtendedExistential; + } +}; + class MetatypeTypeRef final : public TypeRef { const TypeRef *InstanceType; bool WasAbstract; diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index e1e35fa7533ec..2b07d09469042 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -1113,12 +1113,9 @@ class TypeRefBuilder { // Try to resolve to the underlying type, if we can. if (opaqueDescriptor->getKind() == Node::Kind::OpaqueTypeDescriptorSymbolicReference) { - // FIXME: Node should carry a data structure that can fit a remote - // address. For now assume that this is a virtual address. + auto [address, space] = opaqueDescriptor->getRemoteAddress(); auto underlyingTy = OpaqueUnderlyingTypeReader( - remote::RemoteAddress(opaqueDescriptor->getIndex(), - remote::RemoteAddress::DefaultAddressSpace), - ordinal); + remote::RemoteAddress(address, space), ordinal); if (!underlyingTy) return nullptr; @@ -1293,8 +1290,28 @@ class TypeRefBuilder { const TypeRef * createSymbolicExtendedExistentialType(NodePointer shapeNode, llvm::ArrayRef args) { - // Can't handle this here. - return nullptr; + // Non-unique shape symbols start with an offset to a cache variable, right + // before the shape. Metadata pointers point directly to the shape, but when + // reading from a shape symbol, this needs to be corrected. + uint32_t offset = 0; + if (shapeNode->getKind() == + Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference) + offset = sizeof(uint32_t); + auto [address, space] = shapeNode->getRemoteAddress(); + remote::RemoteAddress shape(address, space); + shape += offset; + + return OpaqueShapeReader( + shape, + [&](unsigned shapeArgumentCount) + -> std::optional> { + if (args.size() != shapeArgumentCount) + return std::nullopt; + if (llvm::any_of( + args, [](const TypeRef *arg) { return !arg->isConcrete(); })) + return std::nullopt; + return args; + }); } const ExistentialMetatypeTypeRef *createExistentialMetatypeType( @@ -1322,8 +1339,7 @@ class TypeRefBuilder { const DependentMemberTypeRef * createDependentMemberType(const std::string &member, const TypeRef *base) { - // Should not have unresolved dependent member types here. - return nullptr; + return DependentMemberTypeRef::create(*this, member, base, ""); } const DependentMemberTypeRef * @@ -1489,6 +1505,13 @@ class TypeRefBuilder { using PointerReader = std::function( remote::RemoteAddress, unsigned)>; + using ShapeReader = std::function>(unsigned)>)>; + + using PointerSymbolResolver = + std::function( + remote::RemoteAddress)>; using DynamicSymbolResolver = std::function( remote::RemoteAddress)>; @@ -1521,6 +1544,8 @@ class TypeRefBuilder { ByteReader OpaqueByteReader; StringReader OpaqueStringReader; PointerReader OpaquePointerReader; + ShapeReader OpaqueShapeReader; + PointerSymbolResolver OpaquePointerSymbolResolver; DynamicSymbolResolver OpaqueDynamicSymbolResolver; IntVariableReader OpaqueIntVariableReader; @@ -1559,6 +1584,18 @@ class TypeRefBuilder { -> std::optional { return reader.Reader->readPointer(address, size); }), + OpaqueShapeReader( + [&reader](remote::RemoteAbsolutePointer pointer, + std::function>( + unsigned)> + getArgs) -> const TypeRef * { + return reader.readTypeFromShape(pointer, getArgs); + }), + OpaquePointerSymbolResolver( + [&reader](remote::RemoteAddress address) + -> std::optional { + return reader.Reader->resolvePointerAsSymbol(address); + }), OpaqueDynamicSymbolResolver( [&reader](remote::RemoteAddress address) -> std::optional { @@ -1710,9 +1747,10 @@ class TypeRefBuilder { Node::Kind::OpaqueTypeDescriptorSymbolicReference) { // FIXME: Node should carry a data structure that can fit a remote // address. For now assume that this is a process address. + auto [address, space] = + opaqueTypeChildDemangleTree->getRemoteAddress(); extractOpaqueTypeProtocolRequirements( - remote::RemoteAddress(opaqueTypeChildDemangleTree->getIndex(), - remote::RemoteAddress::DefaultAddressSpace), + remote::RemoteAddress(address, space), opaqueTypeConformanceRequirements, sameTypeRequirements); } } diff --git a/include/swift/RemoteInspection/TypeRefs.def b/include/swift/RemoteInspection/TypeRefs.def index 353987794ee15..0fcd992999741 100644 --- a/include/swift/RemoteInspection/TypeRefs.def +++ b/include/swift/RemoteInspection/TypeRefs.def @@ -23,6 +23,7 @@ TYPEREF(Tuple, TypeRef) TYPEREF(Function, TypeRef) TYPEREF(ProtocolComposition, TypeRef) TYPEREF(ConstrainedExistential, TypeRef) +TYPEREF(SymbolicExtendedExistential, TypeRef) TYPEREF(Metatype, TypeRef) TYPEREF(ExistentialMetatype, TypeRef) TYPEREF(GenericTypeParameter, TypeRef) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index ca01ddffb68bd..7983d8d9831a0 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -791,7 +791,9 @@ Type ASTBuilder::createConstrainedExistentialType( if (auto *memberTy = req.getFirstType()->getAs()) { if (memberTy->getBase()->is()) { // This is the only case we understand so far. - primaryAssociatedTypes[memberTy->getAssocType()] = req.getSecondType(); + if (auto *assocTy = memberTy->getAssocType()) + primaryAssociatedTypes[assocTy] = req.getSecondType(); + continue; } } @@ -809,10 +811,11 @@ Type ASTBuilder::createConstrainedExistentialType( llvm::SmallVector args; for (auto *assocTy : proto->getPrimaryAssociatedTypes()) { auto found = primaryAssociatedTypes.find(assocTy); - if (found == primaryAssociatedTypes.end()) - return protoTy; - args.push_back(found->second); - claimed.insert(found->first); + if (found != primaryAssociatedTypes.end()) { + args.push_back(found->second); + claimed.insert(found->first); + continue; + } } // We may not have any arguments because the constrained existential is a diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index 88837089d4f2c..e6b5902ad0cb2 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -601,6 +601,11 @@ NodePointer NodeFactory::createNode(Node::Kind K) { NodePointer NodeFactory::createNode(Node::Kind K, Node::IndexType Index) { return new (Allocate()) Node(K, Index); } +NodePointer NodeFactory::createNode(Node::Kind K, uint64_t RemoteAddress, + uint8_t AddressSpace) { + return new (Allocate()) Node(K, RemoteAddress, AddressSpace); +} + NodePointer NodeFactory::createNodeWithAllocatedText(Node::Kind K, llvm::StringRef Text) { return new (Allocate()) Node(K, Text); diff --git a/stdlib/public/RemoteInspection/TypeLowering.cpp b/stdlib/public/RemoteInspection/TypeLowering.cpp index 2b48d2e470a88..ea901b844db77 100644 --- a/stdlib/public/RemoteInspection/TypeLowering.cpp +++ b/stdlib/public/RemoteInspection/TypeLowering.cpp @@ -1153,6 +1153,7 @@ class ExistentialTypeInfoBuilder { TypeConverter &TC; std::vector Protocols; const TypeRef *Superclass = nullptr; + remote::RemoteAbsolutePointer Shape; ExistentialTypeRepresentation Representation; ReferenceCounting Refcounting; bool ObjC; @@ -1320,6 +1321,24 @@ class ExistentialTypeInfoBuilder { Representation = ExistentialTypeRepresentation::Class; } + void addShape(const ProtocolCompositionTypeRef *Protocol, + ExtendedExistentialTypeShapeFlags Flags) { + switch (Flags.getSpecialKind()) { + case ExtendedExistentialTypeShapeFlags::SpecialKind::Class: + Representation = ExistentialTypeRepresentation::Class; + break; + case ExtendedExistentialTypeShapeFlags::SpecialKind::Metatype: + case ExtendedExistentialTypeShapeFlags::SpecialKind::ExplicitLayout: + case ExtendedExistentialTypeShapeFlags::SpecialKind::None: + Representation = ExistentialTypeRepresentation::Opaque; + break; + } + + if (Protocol) + for (auto *Protocol : Protocol->getProtocols()) + addProtocol(Protocol); + } + const TypeInfo *build(remote::TypeInfoProvider *ExternalTypeInfo) { examineProtocols(); @@ -1779,6 +1798,11 @@ class HasFixedSize return true; } + bool visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return true; + } + bool visitSILBoxTypeRef(const SILBoxTypeRef *SB) { return true; @@ -1922,6 +1946,11 @@ class HasSingletonMetatype return MetatypeRepresentation::Thin; } + MetatypeRepresentation visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return MetatypeRepresentation::Thin; + } + MetatypeRepresentation visitMetatypeTypeRef(const MetatypeTypeRef *M) { if (M->wasAbstract()) return MetatypeRepresentation::Thick; @@ -2519,6 +2548,13 @@ class LowerType return builder.buildMetatype(ExternalTypeInfo); } + const TypeInfo *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + ExistentialTypeInfoBuilder builder(TC); + builder.addShape(SEET->getProtocol(), SEET->getFlags()); + return builder.build(ExternalTypeInfo); + } + const TypeInfo * visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) { DEBUG_LOG(fprintf(stderr, "Unresolved generic TypeRef: "); GTP->dump()); diff --git a/stdlib/public/RemoteInspection/TypeRef.cpp b/stdlib/public/RemoteInspection/TypeRef.cpp index 6ea89e624fdcb..0c97ccb770153 100644 --- a/stdlib/public/RemoteInspection/TypeRef.cpp +++ b/stdlib/public/RemoteInspection/TypeRef.cpp @@ -289,6 +289,15 @@ class PrintTypeRef : public TypeRefVisitor { stream << ")"; } + void visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *CET) { + printHeader("symbolic_extended_existential_type"); + printRec(CET->getProtocol()); + for (auto &arg : CET->getArguments()) + printRec(arg); + stream << ")"; + } + void visitMetatypeTypeRef(const MetatypeTypeRef *M) { printHeader("metatype"); if (M->wasAbstract()) @@ -513,6 +522,15 @@ struct TypeRefIsConcrete return visit(CET->getBase()); } + bool visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + visit(SEET->getProtocol()); + for (auto &Arg : SEET->getArguments()) + if (!visit(Arg)) + return false; + return true; + } + bool visitMetatypeTypeRef(const MetatypeTypeRef *M) { return visit(M->getInstanceType()); } @@ -952,6 +970,19 @@ class DemanglingForTypeRef return node; } + Demangle::NodePointer visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + auto node = Dem.createNode(Node::Kind::ConstrainedExistential); + node->addChild(visit(SEET->getProtocol()), Dem); + auto constraintList = + Dem.createNode(Node::Kind::ConstrainedExistentialRequirementList); + for (auto req : SEET->getRequirements()) + constraintList->addChild(visitTypeRefRequirement(req), Dem); + node->addChild(constraintList, Dem); + // FIXME: This is lossy. We're dropping the Arguments here. + return node; + } + Demangle::NodePointer visitMetatypeTypeRef(const MetatypeTypeRef *M) { auto node = Dem.createNode(Node::Kind::Metatype); // FIXME: This is lossy. @objc_metatype is also abstract. @@ -1354,6 +1385,11 @@ class ThickenMetatype CET->getRequirements()); } + const TypeRef *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return SEET; + } + const TypeRef *visitMetatypeTypeRef(const MetatypeTypeRef *M) { return MetatypeTypeRef::create(Builder, visit(M->getInstanceType()), /*WasAbstract=*/true); @@ -1641,6 +1677,27 @@ class TypeRefSubstitution constraints); } + const TypeRef *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + std::vector reqs; + for (auto &req : SEET->getRequirements()) { + auto substReq = visitTypeRefRequirement(req); + if (!substReq) + continue; + reqs.emplace_back(*substReq); + } + + std::vector args; + for (auto *arg : SEET->getArguments()) { + auto *substArg = visit(arg); + if (!substArg) + return nullptr; + args.push_back(substArg); + } + return SymbolicExtendedExistentialTypeRef::create( + Builder, SEET->getProtocol(), reqs, args, SEET->getFlags()); + } + const TypeRef * visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) { auto found = Substitutions.find({GTP->getDepth(), GTP->getIndex()});