@@ -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
@@ -1170,18 +1175,21 @@ class TypeRefBuilder {
1170
1175
/* useOpaqueTypeSymbolicReferences */ true );
1171
1176
1172
1177
// If the substituted type is an opaque type, also gather info
1173
- // about which protocols it is required to conform to
1174
- std::vector<std::string> OpaqueTypeConformanceRequirements;
1175
- gatherConformanceRequirementsIfOpaque<ObjCInteropKind, PointerSize>(
1176
- substitutedDemangleTree, OpaqueTypeConformanceRequirements);
1178
+ // about which protocols it is required to conform to and the corresponding
1179
+ // same-type requirements
1180
+ std::vector<std::string> opaqueTypeConformanceRequirements;
1181
+ std::vector<TypeAliasInfo> sameTypeRequirements;
1182
+ gatherOpaqueTypeRequirements<ObjCInteropKind, PointerSize>(
1183
+ substitutedDemangleTree, opaqueTypeConformanceRequirements,
1184
+ sameTypeRequirements);
1177
1185
1178
1186
auto substitutedTypeName = nodeToString (substitutedDemangleTree);
1179
1187
std::stringstream OS;
1180
1188
dumpTypeRef (substitutedTypeRef, OS);
1181
- associatedTypes.emplace_back (
1182
- AssociatedType {typealiasTypeName, mangledSubstitutedTypeName,
1183
- substitutedTypeName, OS.str (),
1184
- OpaqueTypeConformanceRequirements });
1189
+ associatedTypes.emplace_back (AssociatedType{
1190
+ TypeAliasInfo {typealiasTypeName, mangledSubstitutedTypeName,
1191
+ substitutedTypeName, OS.str ()} ,
1192
+ opaqueTypeConformanceRequirements, sameTypeRequirements });
1185
1193
}
1186
1194
result.AssociatedTypeInfos .emplace_back (AssociatedTypeInfo{
1187
1195
mangledTypeName, typeName, protocolName, associatedTypes});
@@ -1193,9 +1201,10 @@ class TypeRefBuilder {
1193
1201
1194
1202
template <template <typename Runtime> class ObjCInteropKind ,
1195
1203
unsigned PointerSize>
1196
- void gatherConformanceRequirementsIfOpaque (
1204
+ void gatherOpaqueTypeRequirements (
1197
1205
Demangle::Node *substitutedTypeDemangleTree,
1198
- std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1206
+ std::vector<std::string> &opaqueTypeConformanceRequirements,
1207
+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
1199
1208
// With unresolved opaque symbolic references, the demangle tree we
1200
1209
// extract the opaque type descriptor's address from is of the form:
1201
1210
// kind=Type
@@ -1209,9 +1218,10 @@ class TypeRefBuilder {
1209
1218
auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild ();
1210
1219
if (opaqueTypeChildDemangleTree->getKind () ==
1211
1220
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1212
- OpaqueTypeConformanceRequirements =
1213
- collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1214
- opaqueTypeChildDemangleTree->getIndex ());
1221
+ extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
1222
+ opaqueTypeChildDemangleTree->getIndex (),
1223
+ opaqueTypeConformanceRequirements,
1224
+ sameTypeRequirements);
1215
1225
}
1216
1226
}
1217
1227
}
@@ -1628,41 +1638,71 @@ class TypeRefBuilder {
1628
1638
stream << " - " << info.FullyQualifiedName << " : "
1629
1639
<< info.ProtocolFullyQualifiedName << " \n " ;
1630
1640
for (const auto &typeAlias : info.AssociatedTypes ) {
1631
- stream << " typealias " << typeAlias.TypeAliasName << " = "
1632
- << typeAlias.SubstitutedTypeFullyQualifiedName << " \n " ;
1633
- stream << typeAlias.SubstitutedTypeDiagnosticPrintName ;
1641
+ stream << " typealias " << typeAlias.SubstitutionInfo . TypeAliasName << " = "
1642
+ << typeAlias.SubstitutionInfo . SubstitutedTypeFullyQualifiedName << " \n " ;
1643
+ stream << typeAlias.SubstitutionInfo . SubstitutedTypeDiagnosticPrintName ;
1634
1644
if (!typeAlias.OpaqueTypeProtocolConformanceRequirements .empty ()) {
1635
- stream << " opaque type conformance requirements: \n " ;
1645
+ stream << " -------------------------\n " ;
1646
+ stream << " conformance requirements: \n " ;
1636
1647
for (const auto &protocolName :
1637
1648
typeAlias.OpaqueTypeProtocolConformanceRequirements ) {
1638
1649
stream << protocolName << " \n " ;
1639
1650
}
1640
1651
}
1652
+ if (!typeAlias.OpaqueTypeSameTypeRequirements .empty ()) {
1653
+ stream << " -----------------------\n " ;
1654
+ stream << " same-type requirements: \n " ;
1655
+ for (const auto &sameTypeRequirementInfo :
1656
+ typeAlias.OpaqueTypeSameTypeRequirements ) {
1657
+ stream << sameTypeRequirementInfo.TypeAliasName << " = "
1658
+ << sameTypeRequirementInfo.SubstitutedTypeMangledName << " ("
1659
+ << sameTypeRequirementInfo.SubstitutedTypeFullyQualifiedName
1660
+ << " )\n " ;
1661
+ }
1662
+ }
1641
1663
}
1642
1664
stream << " \n " ;
1643
1665
}
1644
1666
}
1645
1667
1646
1668
template <template <typename Runtime> class ObjCInteropKind ,
1647
1669
unsigned PointerSize>
1648
- std::vector<std::string>
1649
- collectOpaqueTypeConformanceNames (uintptr_t opaqueTypeDescriptorAddress) {
1650
- std::vector<std::string> result;
1670
+ void extractOpaqueTypeProtocolRequirements (
1671
+ uintptr_t opaqueTypeDescriptorAddress,
1672
+ std::vector<std::string> &protocolRequirements,
1673
+ std::vector<TypeAliasInfo> &sameTypeRequirements) {
1651
1674
auto opaqueTypeDescriptorBytes = OpaqueByteReader (
1652
1675
remote::RemoteAddress (opaqueTypeDescriptorAddress),
1653
1676
sizeof (ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
1654
1677
if (!opaqueTypeDescriptorBytes.get ()) {
1655
- return result ;
1678
+ return ;
1656
1679
}
1657
1680
const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
1658
1681
*opaqueTypeDescriptor =
1659
1682
(const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
1660
1683
opaqueTypeDescriptorBytes.get ();
1661
1684
1662
1685
if (!opaqueTypeDescriptor) {
1663
- return result ;
1686
+ return ;
1664
1687
}
1665
1688
1689
+ // Given that at a given offset from the opaque type descriptor base there
1690
+ // is an offset to a TypeRef string, read it.
1691
+ auto readRequirementTypeRefAddress =
1692
+ [&](uintptr_t offsetFromOpaqueDescBase,
1693
+ uintptr_t requirementAddress) -> uint32_t {
1694
+ std::string typeRefString = " " ;
1695
+ auto fieldOffsetOffset = requirementAddress + offsetFromOpaqueDescBase -
1696
+ (uintptr_t )opaqueTypeDescriptor;
1697
+ auto fieldOffsetAddress = opaqueTypeDescriptorAddress + fieldOffsetOffset;
1698
+ auto fieldOffsetBytes = OpaqueByteReader (
1699
+ remote::RemoteAddress (fieldOffsetAddress), sizeof (uint32_t ));
1700
+ auto fieldOffset = (const int32_t *)fieldOffsetBytes.get ();
1701
+ auto fieldAddress = detail::applyRelativeOffset (
1702
+ (const char *)fieldOffsetAddress, *fieldOffset);
1703
+ return fieldAddress;
1704
+ };
1705
+
1666
1706
for (const auto &req : opaqueTypeDescriptor->getGenericRequirements ()) {
1667
1707
if (req.getKind () == GenericRequirementKind::Protocol) {
1668
1708
// Compute the address of the protocol descriptor offset as:
@@ -1688,10 +1728,32 @@ class TypeRefBuilder {
1688
1728
auto conformanceRequirementProtocolName =
1689
1729
nameReader.readFullyQualifiedProtocolName (
1690
1730
protocolDescriptorAddress);
1691
- result.push_back (*conformanceRequirementProtocolName);
1731
+ protocolRequirements.push_back (*conformanceRequirementProtocolName);
1732
+ }
1733
+ if (req.getKind () == GenericRequirementKind::SameType) {
1734
+ // Read Param Name
1735
+ auto paramAddress = readRequirementTypeRefAddress (req.getParamOffset (),
1736
+ (uintptr_t )(&req));
1737
+ std::string demangledParamName =
1738
+ nodeToString (demangleTypeRef (readTypeRef (paramAddress)));
1739
+
1740
+ // Read the substituted Type Name
1741
+ auto typeAddress = readRequirementTypeRefAddress (
1742
+ req.getSameTypeNameOffset (), (uintptr_t )(&req));
1743
+ auto typeTypeRef = readTypeRef (typeAddress);
1744
+ std::string demangledTypeName =
1745
+ nodeToString (demangleTypeRef (typeTypeRef));
1746
+ std::string mangledTypeName;
1747
+ auto typeMangling = Demangle::mangleNode (demangleTypeRef (typeTypeRef));
1748
+ if (!typeMangling.isSuccess ())
1749
+ mangledTypeName = " " ;
1750
+ else
1751
+ mangledTypeName = typeMangling.result ();
1752
+ sameTypeRequirements.push_back (TypeAliasInfo{
1753
+ demangledParamName, mangledTypeName, demangledTypeName, " " });
1692
1754
}
1693
1755
}
1694
- return result ;
1756
+ return ;
1695
1757
}
1696
1758
1697
1759
// /
@@ -1759,8 +1821,10 @@ class TypeRefBuilder {
1759
1821
(const char *)contextDescriptorFieldAddress,
1760
1822
*contextDescriptorOffset);
1761
1823
1762
- // Instead of a type descriptor this may just be a reference to an external, check that first
1763
- if (auto symbol = OpaqueDynamicSymbolResolver (remote::RemoteAddress (contextTypeDescriptorAddress))) {
1824
+ // Instead of a type descriptor this may just be a reference to an
1825
+ // external, check that first
1826
+ if (auto symbol = OpaqueDynamicSymbolResolver (
1827
+ remote::RemoteAddress (contextTypeDescriptorAddress))) {
1764
1828
if (!symbol->isResolved ()) {
1765
1829
Demangle::Context Ctx;
1766
1830
auto demangledRoot =
0 commit comments