@@ -315,6 +315,7 @@ struct AssociatedType {
315315 std::string SubstitutedTypeMangledName;
316316 std::string SubstitutedTypeFullyQualifiedName;
317317 std::string SubstitutedTypeDiagnosticPrintName;
318+ std::vector<std::string> OpaqueTypeProtocolConformanceRequirements;
318319};
319320
320321// / Info about all of a given type's associated types, as read out from an Image
@@ -523,10 +524,10 @@ class TypeRefBuilder {
523524 Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
524525 auto underlyingTy = OpaqueUnderlyingTypeReader (
525526 opaqueDescriptor->getIndex (), ordinal);
526-
527+
527528 if (!underlyingTy)
528529 return nullptr ;
529-
530+
530531 GenericArgumentMap subs;
531532 for (unsigned d = 0 , de = genericArgs.size (); d < de; ++d) {
532533 auto argsForDepth = genericArgs[d];
@@ -1005,12 +1006,115 @@ class TypeRefBuilder {
10051006 bool printTypeName = false );
10061007 FieldTypeCollectionResult collectFieldTypes (llvm::Optional<std::string> forMangledTypeName);
10071008 void dumpFieldSection (std::ostream &stream);
1008- AssociatedTypeCollectionResult collectAssociatedTypes (llvm::Optional<std::string> forMangledTypeName);
1009- void dumpAssociatedTypeSection (std::ostream &stream);
10101009 void dumpBuiltinTypeSection (std::ostream &stream);
10111010 void dumpCaptureSection (std::ostream &stream);
10121011 void dumpMultiPayloadEnumSection (std::ostream &stream);
10131012
1013+ // /
1014+ // / Extraction of associated types
1015+ // /
1016+ public:
1017+ template <template <typename Runtime> class ObjCInteropKind ,
1018+ unsigned PointerSize>
1019+ AssociatedTypeCollectionResult
1020+ collectAssociatedTypes (llvm::Optional<std::string> forMangledTypeName) {
1021+ AssociatedTypeCollectionResult result;
1022+ for (const auto §ions : ReflectionInfos) {
1023+ for (auto descriptor : sections.AssociatedType ) {
1024+ // Read out the relevant info from the associated type descriptor:
1025+ // The type's name and which protocol conformance it corresponds to
1026+ auto typeRef = readTypeRef (descriptor, descriptor->ConformingTypeName );
1027+ auto typeName = nodeToString (demangleTypeRef (typeRef));
1028+ auto optionalMangledTypeName = normalizeReflectionName (typeRef);
1029+ auto protocolNode = demangleTypeRef (
1030+ readTypeRef (descriptor, descriptor->ProtocolTypeName ));
1031+ auto protocolName = nodeToString (protocolNode);
1032+ clearNodeFactory ();
1033+ if (optionalMangledTypeName.hasValue ()) {
1034+ auto mangledTypeName = optionalMangledTypeName.getValue ();
1035+ if (forMangledTypeName.hasValue ()) {
1036+ if (mangledTypeName != forMangledTypeName.getValue ())
1037+ continue ;
1038+ }
1039+
1040+ // For each associated type, gather its typealias name,
1041+ // the substituted type info, and if the substituted type is opaque -
1042+ // gather its protocol conformance requirements
1043+ std::vector<AssociatedType> associatedTypes;
1044+ for (const auto &associatedTypeRef : *descriptor.getLocalBuffer ()) {
1045+ auto associatedType = descriptor.getField (associatedTypeRef);
1046+ std::string typealiasTypeName =
1047+ getTypeRefString (
1048+ readTypeRef (associatedType, associatedType->Name ))
1049+ .str ();
1050+
1051+ std::string mangledSubstitutedTypeName =
1052+ std::string (associatedType->SubstitutedTypeName );
1053+ auto substitutedTypeRef = readTypeRef (
1054+ associatedType, associatedType->SubstitutedTypeName );
1055+ auto optionalMangledSubstitutedTypeName =
1056+ normalizeReflectionName (substitutedTypeRef);
1057+ if (optionalMangledSubstitutedTypeName.hasValue ()) {
1058+ mangledSubstitutedTypeName =
1059+ optionalMangledSubstitutedTypeName.getValue ();
1060+ }
1061+
1062+ // We intentionally do not want to resolve opaque type
1063+ // references, because if the substituted type is opaque, we
1064+ // would like to get at its OpaqueTypeDescriptor address, which
1065+ // is stored on the OpaqueTypeDescriptorSymbolicReference typeRef.
1066+ auto substitutedDemangleTree =
1067+ demangleTypeRef (substitutedTypeRef,
1068+ /* useOpaqueTypeSymbolicReferences */ true );
1069+
1070+ // If the substituted type is an opaque type, also gather info
1071+ // about which protocols it is required to conform to
1072+ std::vector<std::string> OpaqueTypeConformanceRequirements;
1073+ gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1074+ substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1075+
1076+ auto substitutedTypeName = nodeToString (substitutedDemangleTree);
1077+ std::stringstream OS;
1078+ dumpTypeRef (substitutedTypeRef, OS);
1079+ associatedTypes.emplace_back (
1080+ AssociatedType{typealiasTypeName, mangledSubstitutedTypeName,
1081+ substitutedTypeName, OS.str (),
1082+ OpaqueTypeConformanceRequirements});
1083+ }
1084+ result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
1085+ mangledTypeName, typeName, protocolName, associatedTypes});
1086+ }
1087+ }
1088+ }
1089+ return result;
1090+ }
1091+
1092+ template <template <typename Runtime> class ObjCInteropKind ,
1093+ unsigned PointerSize>
1094+ void gatherConformanceRequirementsIfOpaque (
1095+ Demangle::Node *substitutedTypeDemangleTree,
1096+ std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1097+ // With unresolved opaque symbolic references, the demangle tree we
1098+ // extract the opaque type descriptor's address from is of the form:
1099+ // kind=Type
1100+ // kind=OpaqueType
1101+ // kind=OpaqueTypeDescriptorSymbolicReference, index={{1-9+}}
1102+ // Where the `index` value is the descriptor's address
1103+ //
1104+ if (substitutedTypeDemangleTree->getKind () == Node::Kind::Type) {
1105+ auto childDemangleTree = substitutedTypeDemangleTree->getFirstChild ();
1106+ if (childDemangleTree->getKind () == Node::Kind::OpaqueType) {
1107+ auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
1108+ if (opaqueTypeChildDemangleTree->getKind () ==
1109+ Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1110+ OpaqueTypeConformanceRequirements =
1111+ collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1112+ opaqueTypeChildDemangleTree->getIndex ());
1113+ }
1114+ }
1115+ }
1116+ }
1117+
10141118private:
10151119 struct ContextNameInfo {
10161120 std::string name;
@@ -1142,7 +1246,6 @@ class TypeRefBuilder {
11421246 remote::RemoteAddress (protocolDescriptorAddress),
11431247 sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
11441248 if (!protocolContextDescriptorBytes.get ()) {
1145- // Error = "Failed to read context (protocol) descriptor.";
11461249 return llvm::None;
11471250 }
11481251 const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
@@ -1332,6 +1435,83 @@ class TypeRefBuilder {
13321435 }
13331436 };
13341437
1438+ template <template <typename Runtime> class ObjCInteropKind ,
1439+ unsigned PointerSize>
1440+ void dumpAssociatedTypeSection (std::ostream &stream) {
1441+ auto associatedTypeCollectionResult =
1442+ collectAssociatedTypes<ObjCInteropKind, PointerSize>(
1443+ llvm::Optional<std::string>());
1444+ for (const auto &info :
1445+ associatedTypeCollectionResult.AssociatedTypeInfos ) {
1446+ stream << " - " << info.FullyQualifiedName << " : "
1447+ << info.ProtocolFullyQualifiedName << " \n " ;
1448+ for (const auto &typeAlias : info.AssociatedTypes ) {
1449+ stream << " typealias " << typeAlias.TypeAliasName << " = "
1450+ << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1451+ stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1452+ if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1453+ stream << " opaque type conformance requirements: \n " ;
1454+ for (const auto &protocolName :
1455+ typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
1456+ stream << protocolName << " \n " ;
1457+ }
1458+ }
1459+ }
1460+ stream << " \n " ;
1461+ }
1462+ }
1463+
1464+ template <template <typename Runtime> class ObjCInteropKind ,
1465+ unsigned PointerSize>
1466+ std::vector<std::string>
1467+ collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1468+ std::vector<std::string> result;
1469+ auto opaqueTypeDescriptorBytes = OpaqueByteReader (
1470+ remote::RemoteAddress (opaqueTypeDescriptorAddress),
1471+ sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
1472+ if (!opaqueTypeDescriptorBytes.get ()) {
1473+ return result;
1474+ }
1475+ const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
1476+ *opaqueTypeDescriptor =
1477+ (const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
1478+ opaqueTypeDescriptorBytes.get ();
1479+
1480+ if (!opaqueTypeDescriptor) {
1481+ return result;
1482+ }
1483+
1484+ for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
1485+ if (req.getKind () == GenericRequirementKind::Protocol) {
1486+ // Compute the address of the protocol descriptor offset as:
1487+ // opaqueTypeDescriptorAddress + offset of the protocol descriptor
1488+ // offset in the descriptor
1489+ auto protocolDescriptorOffsetOffset = (uintptr_t )(&req) +
1490+ req.getProtocolOffset () -
1491+ (uintptr_t )opaqueTypeDescriptor;
1492+ auto protocolDescriptorOffsetAddress =
1493+ opaqueTypeDescriptorAddress + protocolDescriptorOffsetOffset;
1494+ auto protocolDescriptorOffsetValue = req.getUnresolvedProtocolAddress ();
1495+
1496+ // Compute the address of the protocol descriptor by following the
1497+ // offset
1498+ auto protocolDescriptorAddress = detail::applyRelativeOffset (
1499+ (const char *)protocolDescriptorOffsetAddress,
1500+ protocolDescriptorOffsetValue);
1501+
1502+ auto nameReader =
1503+ QualifiedContextNameReader<ObjCInteropKind, PointerSize>(
1504+ OpaqueByteReader, OpaqueStringReader, OpaquePointerReader,
1505+ OpaqueDynamicSymbolResolver);
1506+ auto conformanceRequirementProtocolName =
1507+ nameReader.readFullyQualifiedProtocolNameFromProtocolDescriptor (
1508+ protocolDescriptorAddress);
1509+ result.push_back (*conformanceRequirementProtocolName);
1510+ }
1511+ }
1512+ return result;
1513+ }
1514+
13351515 // /
13361516 // / Extraction of protocol conformances
13371517 // /
@@ -1687,7 +1867,7 @@ class TypeRefBuilder {
16871867 stream << " \n " ;
16881868 stream << " ASSOCIATED TYPES:\n " ;
16891869 stream << " =================\n " ;
1690- dumpAssociatedTypeSection (stream);
1870+ dumpAssociatedTypeSection<ObjCInteropKind, PointerSize> (stream);
16911871 stream << " \n " ;
16921872 stream << " BUILTIN TYPES:\n " ;
16931873 stream << " ==============\n " ;
0 commit comments