@@ -315,6 +315,7 @@ struct AssociatedType {
315
315
std::string SubstitutedTypeMangledName;
316
316
std::string SubstitutedTypeFullyQualifiedName;
317
317
std::string SubstitutedTypeDiagnosticPrintName;
318
+ std::vector<std::string> OpaqueTypeProtocolConformanceRequirements;
318
319
};
319
320
320
321
// / Info about all of a given type's associated types, as read out from an Image
@@ -523,10 +524,10 @@ class TypeRefBuilder {
523
524
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
524
525
auto underlyingTy = OpaqueUnderlyingTypeReader (
525
526
opaqueDescriptor->getIndex (), ordinal);
526
-
527
+
527
528
if (!underlyingTy)
528
529
return nullptr ;
529
-
530
+
530
531
GenericArgumentMap subs;
531
532
for (unsigned d = 0 , de = genericArgs.size (); d < de; ++d) {
532
533
auto argsForDepth = genericArgs[d];
@@ -1005,12 +1006,115 @@ class TypeRefBuilder {
1005
1006
bool printTypeName = false );
1006
1007
FieldTypeCollectionResult collectFieldTypes (llvm::Optional<std::string> forMangledTypeName);
1007
1008
void dumpFieldSection (std::ostream &stream);
1008
- AssociatedTypeCollectionResult collectAssociatedTypes (llvm::Optional<std::string> forMangledTypeName);
1009
- void dumpAssociatedTypeSection (std::ostream &stream);
1010
1009
void dumpBuiltinTypeSection (std::ostream &stream);
1011
1010
void dumpCaptureSection (std::ostream &stream);
1012
1011
void dumpMultiPayloadEnumSection (std::ostream &stream);
1013
1012
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
+
1014
1118
private:
1015
1119
struct ContextNameInfo {
1016
1120
std::string name;
@@ -1142,7 +1246,6 @@ class TypeRefBuilder {
1142
1246
remote::RemoteAddress (protocolDescriptorAddress),
1143
1247
sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1144
1248
if (!protocolContextDescriptorBytes.get ()) {
1145
- // Error = "Failed to read context (protocol) descriptor.";
1146
1249
return llvm::None;
1147
1250
}
1148
1251
const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
@@ -1332,6 +1435,83 @@ class TypeRefBuilder {
1332
1435
}
1333
1436
};
1334
1437
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
+
1335
1515
// /
1336
1516
// / Extraction of protocol conformances
1337
1517
// /
@@ -1687,7 +1867,7 @@ class TypeRefBuilder {
1687
1867
stream << " \n " ;
1688
1868
stream << " ASSOCIATED TYPES:\n " ;
1689
1869
stream << " =================\n " ;
1690
- dumpAssociatedTypeSection (stream);
1870
+ dumpAssociatedTypeSection<ObjCInteropKind, PointerSize> (stream);
1691
1871
stream << " \n " ;
1692
1872
stream << " BUILTIN TYPES:\n " ;
1693
1873
stream << " ==============\n " ;
0 commit comments