@@ -312,12 +312,17 @@ struct ConformanceCollectionResult {
312
312
std::vector<std::string> Errors;
313
313
};
314
314
315
- struct AssociatedType {
315
+ struct TypeAliasInfo {
316
316
std::string TypeAliasName;
317
317
std::string SubstitutedTypeMangledName;
318
318
std::string SubstitutedTypeFullyQualifiedName;
319
319
std::string SubstitutedTypeDiagnosticPrintName;
320
+ };
321
+
322
+ struct AssociatedType {
323
+ TypeAliasInfo SubstitutionInfo;
320
324
std::vector<std::string> OpaqueTypeProtocolConformanceRequirements;
325
+ std::vector<TypeAliasInfo> OpaqueTypeSameTypeRequirements;
321
326
};
322
327
323
328
// / Info about all of a given type's associated types, as read out from an Image
@@ -1078,18 +1083,21 @@ class TypeRefBuilder {
1078
1083
/* useOpaqueTypeSymbolicReferences */ true );
1079
1084
1080
1085
// If the substituted type is an opaque type, also gather info
1081
- // about which protocols it is required to conform to
1082
- std::vector<std::string> OpaqueTypeConformanceRequirements;
1083
- gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1084
- substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1086
+ // about which protocols it is required to conform to and the corresponding
1087
+ // same-type requirements
1088
+ std::vector<std::string> opaqueTypeConformanceRequirements;
1089
+ std::vector<TypeAliasInfo> sameTypeRequirements;
1090
+ gatherOpaqueTypeRequirements<ObjCInteropKind, PointerSize>(
1091
+ substitutedDemangleTree, opaqueTypeConformanceRequirements,
1092
+ sameTypeRequirements);
1085
1093
1086
1094
auto substitutedTypeName = nodeToString (substitutedDemangleTree);
1087
1095
std::stringstream OS;
1088
1096
dumpTypeRef (substitutedTypeRef, OS);
1089
- associatedTypes.emplace_back (
1090
- AssociatedType {typealiasTypeName, mangledSubstitutedTypeName,
1091
- substitutedTypeName, OS.str (),
1092
- OpaqueTypeConformanceRequirements });
1097
+ associatedTypes.emplace_back (AssociatedType{
1098
+ TypeAliasInfo {typealiasTypeName, mangledSubstitutedTypeName,
1099
+ substitutedTypeName, OS.str ()} ,
1100
+ opaqueTypeConformanceRequirements, sameTypeRequirements });
1093
1101
}
1094
1102
result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
1095
1103
mangledTypeName, typeName, protocolName, associatedTypes});
@@ -1101,9 +1109,10 @@ class TypeRefBuilder {
1101
1109
1102
1110
template <template <typename Runtime> class ObjCInteropKind ,
1103
1111
unsigned PointerSize>
1104
- void gatherConformanceRequirementsIfOpaque (
1112
+ void gatherOpaqueTypeRequirements (
1105
1113
Demangle::Node *substitutedTypeDemangleTree,
1106
- std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1114
+ std::vector<std::string> &opaqueTypeConformanceRequirements,
1115
+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
1107
1116
// With unresolved opaque symbolic references, the demangle tree we
1108
1117
// extract the opaque type descriptor's address from is of the form:
1109
1118
// kind=Type
@@ -1117,9 +1126,10 @@ class TypeRefBuilder {
1117
1126
auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
1118
1127
if (opaqueTypeChildDemangleTree->getKind () ==
1119
1128
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1120
- OpaqueTypeConformanceRequirements =
1121
- collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1122
- opaqueTypeChildDemangleTree->getIndex ());
1129
+ extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
1130
+ opaqueTypeChildDemangleTree->getIndex (),
1131
+ opaqueTypeConformanceRequirements,
1132
+ sameTypeRequirements);
1123
1133
}
1124
1134
}
1125
1135
}
@@ -1536,41 +1546,71 @@ class TypeRefBuilder {
1536
1546
stream << " - " << info.FullyQualifiedName << " : "
1537
1547
<< info.ProtocolFullyQualifiedName << " \n " ;
1538
1548
for (const auto &typeAlias : info.AssociatedTypes ) {
1539
- stream << " typealias " << typeAlias.TypeAliasName << " = "
1540
- << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1541
- stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1549
+ stream << " typealias " << typeAlias.SubstitutionInfo . TypeAliasName << " = "
1550
+ << typeAlias.SubstitutionInfo . SubstitutedTypeFullyQualifiedName << " \n " ;
1551
+ stream << typeAlias.SubstitutionInfo . SubstitutedTypeDiagnosticPrintName ;
1542
1552
if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1543
- stream << " opaque type conformance requirements: \n " ;
1553
+ stream << " -------------------------\n " ;
1554
+ stream << " conformance requirements: \n " ;
1544
1555
for (const auto &protocolName :
1545
1556
typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
1546
1557
stream << protocolName << " \n " ;
1547
1558
}
1548
1559
}
1560
+ if (!typeAlias.OpaqueTypeSameTypeRequirements .empty ()) {
1561
+ stream << " -----------------------\n " ;
1562
+ stream << " same-type requirements: \n " ;
1563
+ for (const auto &sameTypeRequirementInfo :
1564
+ typeAlias.OpaqueTypeSameTypeRequirements ) {
1565
+ stream << sameTypeRequirementInfo.TypeAliasName << " = "
1566
+ << sameTypeRequirementInfo.SubstitutedTypeMangledName << " ("
1567
+ << sameTypeRequirementInfo.SubstitutedTypeFullyQualifiedName
1568
+ << " )\n " ;
1569
+ }
1570
+ }
1549
1571
}
1550
1572
stream << " \n " ;
1551
1573
}
1552
1574
}
1553
1575
1554
1576
template <template <typename Runtime> class ObjCInteropKind ,
1555
1577
unsigned PointerSize>
1556
- std::vector<std::string>
1557
- collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1558
- std::vector<std::string> result;
1578
+ void extractOpaqueTypeProtocolRequirements (
1579
+ uintptr_t opaqueTypeDescriptorAddress,
1580
+ std::vector<std::string> &protocolRequirements,
1581
+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
1559
1582
auto opaqueTypeDescriptorBytes = OpaqueByteReader (
1560
1583
remote::RemoteAddress (opaqueTypeDescriptorAddress),
1561
1584
sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
1562
1585
if (!opaqueTypeDescriptorBytes.get ()) {
1563
- return result ;
1586
+ return ;
1564
1587
}
1565
1588
const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
1566
1589
*opaqueTypeDescriptor =
1567
1590
(const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
1568
1591
opaqueTypeDescriptorBytes.get ();
1569
1592
1570
1593
if (!opaqueTypeDescriptor) {
1571
- return result ;
1594
+ return ;
1572
1595
}
1573
1596
1597
+ // Given that at a given offset from the opaque type descriptor base there
1598
+ // is an offset to a TypeRef string, read it.
1599
+ auto readRequirementTypeRefAddress =
1600
+ [&](uintptr_t offsetFromOpaqueDescBase,
1601
+ uintptr_t requirementAddress) -> uint32_t {
1602
+ std::string typeRefString = " " ;
1603
+ auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
1604
+ (uintptr_t )opaqueTypeDescriptor;
1605
+ auto fieldOffsetAddress = opaqueTypeDescriptorAddress + fieldOffsetOffset;
1606
+ auto fieldOffsetBytes = OpaqueByteReader (
1607
+ remote::RemoteAddress (fieldOffsetAddress), sizeof (uint32_t ));
1608
+ auto fieldOffset = (const int32_t *)fieldOffsetBytes.get ();
1609
+ auto fieldAddress = detail::applyRelativeOffset (
1610
+ (const char *)fieldOffsetAddress, *fieldOffset);
1611
+ return fieldAddress;
1612
+ };
1613
+
1574
1614
for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
1575
1615
if (req.getKind () == GenericRequirementKind::Protocol) {
1576
1616
// Compute the address of the protocol descriptor offset as:
@@ -1596,10 +1636,32 @@ class TypeRefBuilder {
1596
1636
auto conformanceRequirementProtocolName =
1597
1637
nameReader.readFullyQualifiedProtocolName (
1598
1638
protocolDescriptorAddress);
1599
- result.push_back (*conformanceRequirementProtocolName);
1639
+ protocolRequirements.push_back (*conformanceRequirementProtocolName);
1640
+ }
1641
+ if (req.getKind () == GenericRequirementKind::SameType) {
1642
+ // Read Param Name
1643
+ auto paramAddress = readRequirementTypeRefAddress (req.getParamOffset (),
1644
+ (uintptr_t )(&req));
1645
+ std::string demangledParamName =
1646
+ nodeToString (demangleTypeRef (readTypeRef (paramAddress)));
1647
+
1648
+ // Read the substituted Type Name
1649
+ auto typeAddress = readRequirementTypeRefAddress (
1650
+ req.getSameTypeNameOffset (), (uintptr_t )(&req));
1651
+ auto typeTypeRef = readTypeRef (typeAddress);
1652
+ std::string demangledTypeName =
1653
+ nodeToString (demangleTypeRef (typeTypeRef));
1654
+ std::string mangledTypeName;
1655
+ auto typeMangling = Demangle::mangleNode (demangleTypeRef (typeTypeRef));
1656
+ if (!typeMangling.isSuccess ())
1657
+ mangledTypeName = " " ;
1658
+ else
1659
+ mangledTypeName = typeMangling.result ();
1660
+ sameTypeRequirements.push_back (TypeAliasInfo{
1661
+ demangledParamName, mangledTypeName, demangledTypeName, " " });
1600
1662
}
1601
1663
}
1602
- return result ;
1664
+ return ;
1603
1665
}
1604
1666
1605
1667
// /
@@ -1667,8 +1729,10 @@ class TypeRefBuilder {
1667
1729
(const char *)contextDescriptorFieldAddress,
1668
1730
*contextDescriptorOffset);
1669
1731
1670
- // Instead of a type descriptor this may just be a reference to an external, check that first
1671
- if (auto symbol = OpaqueDynamicSymbolResolver (remote::RemoteAddress (contextTypeDescriptorAddress))) {
1732
+ // Instead of a type descriptor this may just be a reference to an
1733
+ // external, check that first
1734
+ if (auto symbol = OpaqueDynamicSymbolResolver (
1735
+ remote::RemoteAddress (contextTypeDescriptorAddress))) {
1672
1736
if (!symbol->isResolved ()) {
1673
1737
Demangle::Context Ctx;
1674
1738
auto demangledRoot =
0 commit comments