Skip to content

Commit 36ae2b9

Browse files
authored
Merge pull request #59977 from artemcm/57_ssm_opaque_same_type_requirements
[5.7] Gather opaque type same-type requirements when scanning associated type infos from a binary
2 parents ac60dde + 0c60820 commit 36ae2b9

File tree

7 files changed

+174
-48
lines changed

7 files changed

+174
-48
lines changed

include/swift-c/StaticMirror/BinaryScan.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/// SWIFTSTATICMIRROR_VERSION_MINOR should increase when there are API additions.
2626
/// SWIFTSTATICMIRROR_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
2727
#define SWIFTSTATICMIRROR_VERSION_MAJOR 0
28-
#define SWIFTSTATICMIRROR_VERSION_MINOR 4 // Added opaque associated type's protocol requirements
28+
#define SWIFTSTATICMIRROR_VERSION_MINOR 5 // Added opaque associated type's same-type requirements
2929

3030
SWIFTSTATICMIRROR_BEGIN_DECLS
3131

@@ -116,7 +116,10 @@ SWIFTSTATICMIRROR_PUBLIC swift_static_mirror_string_ref_t
116116
swift_static_mirror_type_alias_get_substituted_type_mangled_name(
117117
swift_static_mirror_type_alias_t);
118118
SWIFTSTATICMIRROR_PUBLIC swiftscan_string_set_t *
119-
swift_static_mirror_type_alias_get_opaque_type_requirements(
119+
swift_static_mirror_type_alias_get_opaque_type_protocol_requirements(
120+
swift_static_mirror_type_alias_t);
121+
SWIFTSTATICMIRROR_PUBLIC swift_static_mirror_type_alias_set_t *
122+
swift_static_mirror_type_alias_get_opaque_type_same_type_requirements(
120123
swift_static_mirror_type_alias_t);
121124

122125
// swift_static_mirror_associated_type_info query methods

include/swift/ABI/GenericContext.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ class TargetGenericRequirementDescriptor {
157157
return offsetof(typename std::remove_reference<decltype(*this)>::type, Protocol);
158158
}
159159

160+
/// Retreive the offset to the Type field
161+
constexpr inline auto
162+
getSameTypeNameOffset() const -> typename Runtime::StoredSize {
163+
return offsetof(typename std::remove_reference<decltype(*this)>::type, Type);
164+
}
165+
166+
/// Retreive the offset to the Type field
167+
constexpr inline auto
168+
getParamOffset() const -> typename Runtime::StoredSize {
169+
return offsetof(typename std::remove_reference<decltype(*this)>::type, Param);
170+
}
171+
160172
/// Retrieve the right-hand type for a SameType or BaseClass requirement.
161173
llvm::StringRef getMangledTypeName() const {
162174
assert(getKind() == GenericRequirementKind::SameType ||

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,17 @@ struct ConformanceCollectionResult {
312312
std::vector<std::string> Errors;
313313
};
314314

315-
struct AssociatedType {
315+
struct TypeAliasInfo {
316316
std::string TypeAliasName;
317317
std::string SubstitutedTypeMangledName;
318318
std::string SubstitutedTypeFullyQualifiedName;
319319
std::string SubstitutedTypeDiagnosticPrintName;
320+
};
321+
322+
struct AssociatedType {
323+
TypeAliasInfo SubstitutionInfo;
320324
std::vector<std::string> OpaqueTypeProtocolConformanceRequirements;
325+
std::vector<TypeAliasInfo> OpaqueTypeSameTypeRequirements;
321326
};
322327

323328
/// Info about all of a given type's associated types, as read out from an Image
@@ -1078,18 +1083,21 @@ class TypeRefBuilder {
10781083
/* useOpaqueTypeSymbolicReferences */ true);
10791084

10801085
// 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);
10851093

10861094
auto substitutedTypeName = nodeToString(substitutedDemangleTree);
10871095
std::stringstream OS;
10881096
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});
10931101
}
10941102
result.AssociatedTypeInfos.emplace_back(AssociatedTypeInfo{
10951103
mangledTypeName, typeName, protocolName, associatedTypes});
@@ -1101,9 +1109,10 @@ class TypeRefBuilder {
11011109

11021110
template <template <typename Runtime> class ObjCInteropKind,
11031111
unsigned PointerSize>
1104-
void gatherConformanceRequirementsIfOpaque(
1112+
void gatherOpaqueTypeRequirements(
11051113
Demangle::Node *substitutedTypeDemangleTree,
1106-
std::vector<std::string> &OpaqueTypeConformanceRequirements) {
1114+
std::vector<std::string> &opaqueTypeConformanceRequirements,
1115+
std::vector<TypeAliasInfo> &sameTypeRequirements) {
11071116
// With unresolved opaque symbolic references, the demangle tree we
11081117
// extract the opaque type descriptor's address from is of the form:
11091118
// kind=Type
@@ -1117,9 +1126,10 @@ class TypeRefBuilder {
11171126
auto opaqueTypeChildDemangleTree = childDemangleTree->getFirstChild();
11181127
if (opaqueTypeChildDemangleTree->getKind() ==
11191128
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
1120-
OpaqueTypeConformanceRequirements =
1121-
collectOpaqueTypeConformanceNames<ObjCInteropKind, PointerSize>(
1122-
opaqueTypeChildDemangleTree->getIndex());
1129+
extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
1130+
opaqueTypeChildDemangleTree->getIndex(),
1131+
opaqueTypeConformanceRequirements,
1132+
sameTypeRequirements);
11231133
}
11241134
}
11251135
}
@@ -1536,41 +1546,71 @@ class TypeRefBuilder {
15361546
stream << "- " << info.FullyQualifiedName << " : "
15371547
<< info.ProtocolFullyQualifiedName << "\n";
15381548
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;
15421552
if (!typeAlias.OpaqueTypeProtocolConformanceRequirements.empty()) {
1543-
stream << "opaque type conformance requirements: \n";
1553+
stream << "-------------------------\n";
1554+
stream << "conformance requirements: \n";
15441555
for (const auto &protocolName :
15451556
typeAlias.OpaqueTypeProtocolConformanceRequirements) {
15461557
stream << protocolName << "\n";
15471558
}
15481559
}
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+
}
15491571
}
15501572
stream << "\n";
15511573
}
15521574
}
15531575

15541576
template <template <typename Runtime> class ObjCInteropKind,
15551577
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) {
15591582
auto opaqueTypeDescriptorBytes = OpaqueByteReader(
15601583
remote::RemoteAddress(opaqueTypeDescriptorAddress),
15611584
sizeof(ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>));
15621585
if (!opaqueTypeDescriptorBytes.get()) {
1563-
return result;
1586+
return;
15641587
}
15651588
const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize>
15661589
*opaqueTypeDescriptor =
15671590
(const ExternalOpaqueTypeDescriptor<ObjCInteropKind, PointerSize> *)
15681591
opaqueTypeDescriptorBytes.get();
15691592

15701593
if (!opaqueTypeDescriptor) {
1571-
return result;
1594+
return;
15721595
}
15731596

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+
15741614
for (const auto &req : opaqueTypeDescriptor->getGenericRequirements()) {
15751615
if (req.getKind() == GenericRequirementKind::Protocol) {
15761616
// Compute the address of the protocol descriptor offset as:
@@ -1596,10 +1636,32 @@ class TypeRefBuilder {
15961636
auto conformanceRequirementProtocolName =
15971637
nameReader.readFullyQualifiedProtocolName(
15981638
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, ""});
16001662
}
16011663
}
1602-
return result;
1664+
return;
16031665
}
16041666

16051667
///
@@ -1667,8 +1729,10 @@ class TypeRefBuilder {
16671729
(const char *)contextDescriptorFieldAddress,
16681730
*contextDescriptorOffset);
16691731

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))) {
16721736
if (!symbol->isResolved()) {
16731737
Demangle::Context Ctx;
16741738
auto demangledRoot =

include/swift/StaticMirror/BinaryScanImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ struct swift_static_mirror_type_alias_s {
3434
swift_static_mirror_string_ref_t type_alias_name;
3535
swift_static_mirror_string_ref_t substituted_type_name;
3636
swift_static_mirror_string_ref_t substituted_type_mangled_name;
37-
swift_static_mirror_string_set_t *opaque_requirements_set;
37+
swift_static_mirror_string_set_t *opaque_protocol_requirements_set;
38+
swift_static_mirror_type_alias_set_t *opaque_same_type_requirements_set;
3839
};
3940

4041
struct swift_static_mirror_associated_type_info_s {

test/Reflection/opaque_associated_type_requirements.swift

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,40 @@
1010
// RUN: %target-swift-reflection-dump -binary-filename %t/AssociatedTypeRequirements | %FileCheck %s
1111

1212
// CHECK: ASSOCIATED TYPES:
13-
// CHECK-NEXT: =============
14-
// CHECK-NEXT: - AssociatedTypeRequirements.Foo : AssociatedTypeRequirements.myProto
13+
// CHECK: - AssociatedTypeRequirements.Foo : AssociatedTypeRequirements.myProto
1514
// CHECK-NEXT: typealias PerformReturn = opaque type symbolic reference
1615
// CHECK-NEXT: opaque type symbolic reference
17-
// CHECK-NEXT: (struct AssociatedTypeRequirements.Bar)
16+
// CHECK-NEXT: (bound_generic_struct AssociatedTypeRequirements.Bar
1817

19-
// CHECK: opaque type conformance requirements:
18+
// CHECK: conformance requirements:
2019
// CHECK-NEXT: AssociatedTypeRequirements.protoA
2120
// CHECK-NEXT: AssociatedTypeRequirements.protoB
2221
// CHECK-NEXT: testModB.testModBProtocol
2322

23+
// CHECK: same-type requirements:
24+
// CHECK-NEXT: A.AssociatedTypeRequirements.protoB.K = Sf (Swift.Float)
25+
// CHECK-NEXT: A.AssociatedTypeRequirements.protoA.T = 8testModB0aB7BStructV (testModB.testModBStruct)
26+
2427
import testModB
2528

2629
public protocol myProto {
2730
associatedtype PerformReturn
2831
func perform() -> PerformReturn
2932
}
30-
public protocol protoA {}
31-
public protocol protoB {}
33+
public protocol protoA<T> {
34+
associatedtype T
35+
}
36+
public protocol protoB<K> {
37+
associatedtype K
38+
}
3239

33-
public struct Bar : protoA, protoB, testModBProtocol {}
40+
public struct Bar<M, N> : protoA, protoB, testModBProtocol {
41+
public typealias T = M
42+
public typealias K = N
43+
}
3444

3545
public struct Foo : myProto {
36-
public func perform() -> some protoA & protoB & testModBProtocol { return baz() }
46+
public func perform() -> some protoA<testModBStruct> & protoB<Float> & testModBProtocol { return baz() }
3747
}
3848

39-
private func baz() -> some protoA & protoB & testModBProtocol { return Bar() }
49+
private func baz() -> some protoA<testModBStruct> & protoB<Float> & testModBProtocol { return Bar<testModBStruct, Float>() }

tools/libStaticMirror/libStaticMirror.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,48 @@ convertAssociatedTypeQueryResult(
176176
swift_static_mirror_type_alias_s *typeAliasDetails =
177177
new swift_static_mirror_type_alias_s;
178178
typeAliasDetails->type_alias_name = swift::c_string_utils::create_clone(
179-
typeAliasInfo.TypeAliasName.c_str());
179+
typeAliasInfo.SubstitutionInfo.TypeAliasName.c_str());
180180
typeAliasDetails->substituted_type_name =
181181
swift::c_string_utils::create_clone(
182-
typeAliasInfo.SubstitutedTypeFullyQualifiedName.c_str());
182+
typeAliasInfo.SubstitutionInfo.SubstitutedTypeFullyQualifiedName.c_str());
183183
typeAliasDetails->substituted_type_mangled_name =
184184
swift::c_string_utils::create_clone(
185-
typeAliasInfo.SubstitutedTypeMangledName.c_str());
186-
info->type_alias_set->type_aliases[typealiasIndex] = typeAliasDetails;
187-
typealiasIndex += 1;
188-
typeAliasDetails->opaque_requirements_set =
185+
typeAliasInfo.SubstitutionInfo.SubstitutedTypeMangledName.c_str());
186+
187+
// Opaque type's protocol conformance requirements
188+
typeAliasDetails->opaque_protocol_requirements_set =
189189
swift::c_string_utils::create_set(
190190
typeAliasInfo.OpaqueTypeProtocolConformanceRequirements);
191+
192+
// Opaque type's same-type requirements
193+
typeAliasDetails->opaque_same_type_requirements_set =
194+
new swift_static_mirror_type_alias_set_t;
195+
typeAliasDetails->opaque_same_type_requirements_set->count =
196+
typeAliasInfo.OpaqueTypeSameTypeRequirements.size();
197+
typeAliasDetails->opaque_same_type_requirements_set->type_aliases =
198+
new swift_static_mirror_type_alias_t
199+
[typeAliasInfo.OpaqueTypeSameTypeRequirements.size()];
200+
int sameTypeReqIndex = 0;
201+
for (const auto &sameTypeReq :
202+
typeAliasInfo.OpaqueTypeSameTypeRequirements) {
203+
swift_static_mirror_type_alias_s *sameTypeReqDetails =
204+
new swift_static_mirror_type_alias_s;
205+
sameTypeReqDetails->type_alias_name =
206+
swift::c_string_utils::create_clone(
207+
sameTypeReq.TypeAliasName.c_str());
208+
sameTypeReqDetails->substituted_type_mangled_name =
209+
swift::c_string_utils::create_clone(
210+
sameTypeReq.SubstitutedTypeMangledName.c_str());
211+
sameTypeReqDetails->substituted_type_name =
212+
swift::c_string_utils::create_clone(
213+
sameTypeReq.SubstitutedTypeFullyQualifiedName.c_str());
214+
typeAliasDetails->opaque_same_type_requirements_set
215+
->type_aliases[sameTypeReqIndex] = sameTypeReqDetails;
216+
sameTypeReqIndex += 1;
217+
}
218+
219+
info->type_alias_set->type_aliases[typealiasIndex] = typeAliasDetails;
220+
typealiasIndex += 1;
191221
}
192222
result->associated_type_infos[associatedTypeInfoIndex] = info;
193223
associatedTypeInfoIndex += 1;
@@ -282,9 +312,14 @@ swift_static_mirror_type_alias_get_substituted_type_mangled_name(
282312
return type_alias->substituted_type_mangled_name;
283313
}
284314
swiftscan_string_set_t *
285-
swift_static_mirror_type_alias_get_opaque_type_requirements(
315+
swift_static_mirror_type_alias_get_opaque_type_protocol_requirements(
316+
swift_static_mirror_type_alias_t type_alias) {
317+
return type_alias->opaque_protocol_requirements_set;
318+
}
319+
swift_static_mirror_type_alias_set_t *
320+
swift_static_mirror_type_alias_get_opaque_type_same_type_requirements(
286321
swift_static_mirror_type_alias_t type_alias) {
287-
return type_alias->opaque_requirements_set;
322+
return type_alias->opaque_same_type_requirements_set;
288323
}
289324

290325
// swift_static_mirror_associated_type_info query methods

tools/libStaticMirror/libStaticMirror.exports

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ swift_static_mirror_conformance_info_get_mangled_type_name
77
swift_static_mirror_type_alias_get_type_alias_name
88
swift_static_mirror_type_alias_get_substituted_type_name
99
swift_static_mirror_type_alias_get_substituted_type_mangled_name
10-
swift_static_mirror_type_alias_get_opaque_type_requirements
10+
swift_static_mirror_type_alias_get_opaque_type_protocol_requirements
11+
swift_static_mirror_type_alias_get_opaque_type_same_type_requirements
1112
swift_static_mirror_associated_type_info_get_mangled_type_name
1213
swift_static_mirror_associated_type_info_get_type_alias_set
1314
swift_static_mirror_associated_type_info_set_create

0 commit comments

Comments
 (0)