@@ -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];
@@ -1011,12 +1012,115 @@ class TypeRefBuilder {
1011
1012
bool printTypeName = false );
1012
1013
FieldTypeCollectionResult collectFieldTypes (llvm::Optional<std::string> forMangledTypeName);
1013
1014
void dumpFieldSection (std::ostream &stream);
1014
- AssociatedTypeCollectionResult collectAssociatedTypes (llvm::Optional<std::string> forMangledTypeName);
1015
- void dumpAssociatedTypeSection (std::ostream &stream);
1016
1015
void dumpBuiltinTypeSection (std::ostream &stream);
1017
1016
void dumpCaptureSection (std::ostream &stream);
1018
1017
void dumpMultiPayloadEnumSection (std::ostream &stream);
1019
1018
1019
+ // /
1020
+ // / Extraction of associated types
1021
+ // /
1022
+ public:
1023
+ template <template <typename Runtime> class ObjCInteropKind ,
1024
+ unsigned PointerSize>
1025
+ AssociatedTypeCollectionResult
1026
+ collectAssociatedTypes (llvm::Optional<std::string> forMangledTypeName) {
1027
+ AssociatedTypeCollectionResult result;
1028
+ for (const auto §ions : ReflectionInfos) {
1029
+ for (auto descriptor : sections.AssociatedType ) {
1030
+ // Read out the relevant info from the associated type descriptor:
1031
+ // The type's name and which protocol conformance it corresponds to
1032
+ auto typeRef = readTypeRef (descriptor, descriptor->ConformingTypeName );
1033
+ auto typeName = nodeToString (demangleTypeRef (typeRef));
1034
+ auto optionalMangledTypeName = normalizeReflectionName (typeRef);
1035
+ auto protocolNode = demangleTypeRef (
1036
+ readTypeRef (descriptor, descriptor->ProtocolTypeName ));
1037
+ auto protocolName = nodeToString (protocolNode);
1038
+ clearNodeFactory ();
1039
+ if (optionalMangledTypeName.hasValue ()) {
1040
+ auto mangledTypeName = optionalMangledTypeName.getValue ();
1041
+ if (forMangledTypeName.hasValue ()) {
1042
+ if (mangledTypeName != forMangledTypeName.getValue ())
1043
+ continue ;
1044
+ }
1045
+
1046
+ // For each associated type, gather its typealias name,
1047
+ // the substituted type info, and if the substituted type is opaque -
1048
+ // gather its protocol conformance requirements
1049
+ std::vector<AssociatedType> associatedTypes;
1050
+ for (const auto &associatedTypeRef : *descriptor.getLocalBuffer ()) {
1051
+ auto associatedType = descriptor.getField (associatedTypeRef);
1052
+ std::string typealiasTypeName =
1053
+ getTypeRefString (
1054
+ readTypeRef (associatedType, associatedType->Name ))
1055
+ .str ();
1056
+
1057
+ std::string mangledSubstitutedTypeName =
1058
+ std::string (associatedType->SubstitutedTypeName );
1059
+ auto substitutedTypeRef = readTypeRef (
1060
+ associatedType, associatedType->SubstitutedTypeName );
1061
+ auto optionalMangledSubstitutedTypeName =
1062
+ normalizeReflectionName (substitutedTypeRef);
1063
+ if (optionalMangledSubstitutedTypeName.hasValue ()) {
1064
+ mangledSubstitutedTypeName =
1065
+ optionalMangledSubstitutedTypeName.getValue ();
1066
+ }
1067
+
1068
+ // We intentionally do not want to resolve opaque type
1069
+ // references, because if the substituted type is opaque, we
1070
+ // would like to get at its OpaqueTypeDescriptor address, which
1071
+ // is stored on the OpaqueTypeDescriptorSymbolicReference typeRef.
1072
+ auto substitutedDemangleTree =
1073
+ demangleTypeRef (substitutedTypeRef,
1074
+ /* useOpaqueTypeSymbolicReferences */ true );
1075
+
1076
+ // If the substituted type is an opaque type, also gather info
1077
+ // about which protocols it is required to conform to
1078
+ std::vector<std::string> OpaqueTypeConformanceRequirements;
1079
+ gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1080
+ substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1081
+
1082
+ auto substitutedTypeName = nodeToString (substitutedDemangleTree);
1083
+ std::stringstream OS;
1084
+ dumpTypeRef (substitutedTypeRef, OS);
1085
+ associatedTypes.emplace_back (
1086
+ AssociatedType{typealiasTypeName, mangledSubstitutedTypeName,
1087
+ substitutedTypeName, OS.str (),
1088
+ OpaqueTypeConformanceRequirements});
1089
+ }
1090
+ result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
1091
+ mangledTypeName, typeName, protocolName, associatedTypes});
1092
+ }
1093
+ }
1094
+ }
1095
+ return result;
1096
+ }
1097
+
1098
+ template <template <typename Runtime> class ObjCInteropKind ,
1099
+ unsigned PointerSize>
1100
+ void gatherConformanceRequirementsIfOpaque (
1101
+ Demangle::Node *substitutedTypeDemangleTree,
1102
+ std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1103
+ // With unresolved opaque symbolic references, the demangle tree we
1104
+ // extract the opaque type descriptor's address from is of the form:
1105
+ // kind=Type
1106
+ // kind=OpaqueType
1107
+ // kind=OpaqueTypeDescriptorSymbolicReference, index={{1-9+}}
1108
+ // Where the `index` value is the descriptor's address
1109
+ //
1110
+ if (substitutedTypeDemangleTree->getKind () == Node::Kind::Type) {
1111
+ auto childDemangleTree = substitutedTypeDemangleTree->getFirstChild ();
1112
+ if (childDemangleTree->getKind () == Node::Kind::OpaqueType) {
1113
+ auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
1114
+ if (opaqueTypeChildDemangleTree->getKind () ==
1115
+ Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1116
+ OpaqueTypeConformanceRequirements =
1117
+ collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1118
+ opaqueTypeChildDemangleTree->getIndex ());
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+
1020
1124
private:
1021
1125
struct ContextNameInfo {
1022
1126
std::string name;
@@ -1148,7 +1252,6 @@ class TypeRefBuilder {
1148
1252
remote::RemoteAddress (protocolDescriptorAddress),
1149
1253
sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1150
1254
if (!protocolContextDescriptorBytes.get ()) {
1151
- // Error = "Failed to read context (protocol) descriptor.";
1152
1255
return llvm::None;
1153
1256
}
1154
1257
const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
@@ -1338,6 +1441,83 @@ class TypeRefBuilder {
1338
1441
}
1339
1442
};
1340
1443
1444
+ template <template <typename Runtime> class ObjCInteropKind ,
1445
+ unsigned PointerSize>
1446
+ void dumpAssociatedTypeSection (std::ostream &stream) {
1447
+ auto associatedTypeCollectionResult =
1448
+ collectAssociatedTypes<ObjCInteropKind, PointerSize>(
1449
+ llvm::Optional<std::string>());
1450
+ for (const auto &info :
1451
+ associatedTypeCollectionResult.AssociatedTypeInfos ) {
1452
+ stream << " - " << info.FullyQualifiedName << " : "
1453
+ << info.ProtocolFullyQualifiedName << " \n " ;
1454
+ for (const auto &typeAlias : info.AssociatedTypes ) {
1455
+ stream << " typealias " << typeAlias.TypeAliasName << " = "
1456
+ << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1457
+ stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1458
+ if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1459
+ stream << " opaque type conformance requirements: \n " ;
1460
+ for (const auto &protocolName :
1461
+ typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
1462
+ stream << protocolName << " \n " ;
1463
+ }
1464
+ }
1465
+ }
1466
+ stream << " \n " ;
1467
+ }
1468
+ }
1469
+
1470
+ template <template <typename Runtime> class ObjCInteropKind ,
1471
+ unsigned PointerSize>
1472
+ std::vector<std::string>
1473
+ collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1474
+ std::vector<std::string> result;
1475
+ auto opaqueTypeDescriptorBytes = OpaqueByteReader (
1476
+ remote::RemoteAddress (opaqueTypeDescriptorAddress),
1477
+ sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
1478
+ if (!opaqueTypeDescriptorBytes.get ()) {
1479
+ return result;
1480
+ }
1481
+ const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
1482
+ *opaqueTypeDescriptor =
1483
+ (const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
1484
+ opaqueTypeDescriptorBytes.get ();
1485
+
1486
+ if (!opaqueTypeDescriptor) {
1487
+ return result;
1488
+ }
1489
+
1490
+ for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
1491
+ if (req.getKind () == GenericRequirementKind::Protocol) {
1492
+ // Compute the address of the protocol descriptor offset as:
1493
+ // opaqueTypeDescriptorAddress + offset of the protocol descriptor
1494
+ // offset in the descriptor
1495
+ auto protocolDescriptorOffsetOffset = (uintptr_t )(&req) +
1496
+ req.getProtocolOffset () -
1497
+ (uintptr_t )opaqueTypeDescriptor;
1498
+ auto protocolDescriptorOffsetAddress =
1499
+ opaqueTypeDescriptorAddress + protocolDescriptorOffsetOffset;
1500
+ auto protocolDescriptorOffsetValue = req.getUnresolvedProtocolAddress ();
1501
+
1502
+ // Compute the address of the protocol descriptor by following the
1503
+ // offset
1504
+ auto protocolDescriptorAddress = detail::applyRelativeOffset (
1505
+ (const char *)protocolDescriptorOffsetAddress,
1506
+ protocolDescriptorOffsetValue);
1507
+
1508
+ auto nameReader =
1509
+ QualifiedContextNameReader<ObjCInteropKind, PointerSize>(
1510
+ OpaqueByteReader, OpaqueStringReader, OpaquePointerReader,
1511
+ OpaqueDynamicSymbolResolver);
1512
+ auto conformanceRequirementProtocolName =
1513
+ nameReader.readFullyQualifiedProtocolNameFromProtocolDescriptor (
1514
+ protocolDescriptorAddress);
1515
+ result.push_back (*conformanceRequirementProtocolName);
1516
+ }
1517
+ }
1518
+ return result;
1519
+ }
1520
+
1341
1521
// /
1342
1522
// / Extraction of protocol conformances
1343
1523
// /
@@ -1701,7 +1881,7 @@ class TypeRefBuilder {
1701
1881
stream << " \n " ;
1702
1882
stream << " ASSOCIATED TYPES:\n " ;
1703
1883
stream << " =================\n " ;
1704
- dumpAssociatedTypeSection (stream);
1884
+ dumpAssociatedTypeSection<ObjCInteropKind, PointerSize> (stream);
1705
1885
stream << " \n " ;
1706
1886
stream << " BUILTIN TYPES:\n " ;
1707
1887
stream << " ==============\n " ;
0 commit comments