24
24
#include " swift/Reflection/TypeLowering.h"
25
25
#include " swift/Reflection/TypeRef.h"
26
26
#include " llvm/ADT/Optional.h"
27
+ #include " llvm/Support/Debug.h"
27
28
#include < iomanip>
28
29
#include < iostream>
29
30
#include < ostream>
31
+ #include < sstream>
30
32
#include < unordered_map>
31
33
#include < vector>
32
34
@@ -961,88 +963,111 @@ class TypeRefBuilder {
961
963
OpaqueStringReader (stringReader), OpaquePointerReader(pointerReader) {
962
964
}
963
965
964
- llvm::Optional<std::string>
965
- getParentContextName ( uintptr_t contextDescriptorAddress) {
966
- llvm::Optional<std::string> optionalParentContextName ;
967
- auto contextTypeDescriptorBytes = OpaqueByteReader (
968
- remote::RemoteAddress (contextDescriptorAddress),
969
- sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
970
- if (!contextTypeDescriptorBytes. get ()) {
971
- Error = " Failed to read context descriptor. " ;
972
- return llvm::None;
973
- }
974
- const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
975
- *contextDescriptor =
976
- ( const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
977
- contextTypeDescriptorBytes. get ();
966
+ struct ContextNameInfo {
967
+ std::string name;
968
+ uintptr_t descriptorAddress ;
969
+ bool isAnonymous;
970
+
971
+ ~ContextNameInfo () {}
972
+ };
973
+
974
+ bool isModuleDescriptor (
975
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
976
+ *contextDescriptor) {
977
+ return isa<ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
978
+ contextDescriptor);
979
+ }
978
980
981
+ uintptr_t getParentDescriptorAddress (
982
+ uintptr_t contextDescriptorAddress,
983
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
984
+ *contextDescriptor) {
979
985
auto parentOffsetAddress = detail::applyRelativeOffset (
980
986
(const char *)contextDescriptorAddress,
981
987
(int32_t )contextDescriptor->getParentOffset ());
982
988
auto parentOfsetBytes = OpaqueByteReader (
983
989
remote::RemoteAddress (parentOffsetAddress), sizeof (uint32_t ));
984
- if (!parentOfsetBytes.get ()) {
985
- Error = " Failed to parent offset in a type descriptor." ;
986
- return llvm::None;
987
- }
988
990
auto parentFieldOffset = (const int32_t *)parentOfsetBytes.get ();
989
991
auto parentTargetAddress = detail::applyRelativeOffset (
990
992
(const char *)parentOffsetAddress, *parentFieldOffset);
993
+ return parentTargetAddress;
994
+ }
995
+
996
+ llvm::Optional<ContextNameInfo>
997
+ getContextName (uintptr_t contextDescriptorAddress,
998
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
999
+ *contextDescriptor) {
1000
+ if (auto moduleDescriptor = dyn_cast<
1001
+ ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1002
+ contextDescriptor)) {
1003
+ auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1004
+ moduleDescriptor, contextDescriptorAddress);
1005
+ if (!moduleDescriptorName.hasValue ())
1006
+ return llvm::None;
1007
+ else
1008
+ return ContextNameInfo{moduleDescriptorName.getValue (),
1009
+ contextDescriptorAddress, false };
1010
+ } else if (auto typeDescriptor = dyn_cast<ExternalTypeContextDescriptor<
1011
+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1012
+ auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1013
+ typeDescriptor, contextDescriptorAddress);
1014
+ if (!typeDescriptorName.hasValue ())
1015
+ return llvm::None;
1016
+ else
1017
+ return ContextNameInfo{typeDescriptorName.getValue (),
1018
+ contextDescriptorAddress, false };
1019
+ } else if (auto anonymousDescriptor =
1020
+ dyn_cast<ExternalAnonymousContextDescriptor<
1021
+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1022
+ auto anonymousDescriptorName = readAnonymousNameFromAnonymousDescriptor (
1023
+ anonymousDescriptor, contextDescriptorAddress);
1024
+ if (!anonymousDescriptorName.hasValue ())
1025
+ return llvm::None;
1026
+ else
1027
+ return ContextNameInfo{anonymousDescriptorName.getValue (),
1028
+ contextDescriptorAddress, true };
1029
+ } else {
1030
+ Error = " Unexpected type of context descriptor." ;
1031
+ return llvm::None;
1032
+ }
1033
+ }
991
1034
992
- //
993
- auto readContextParentName =
994
- [&](uintptr_t descriptorAddress) -> llvm::Optional<std::string> {
995
- llvm::Optional<std::string> optionalParentName;
1035
+ void getParentContextChain (
1036
+ uintptr_t contextDescriptorAddress,
1037
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1038
+ *contextDescriptor,
1039
+ std::vector<ContextNameInfo> &chain) {
1040
+ const auto parentDescriptorAddress = getParentDescriptorAddress (
1041
+ contextDescriptorAddress, contextDescriptor);
1042
+
1043
+ auto addParentNameAndRecurse =
1044
+ [&](uintptr_t parentContextDescriptorAddress,
1045
+ std::vector<ContextNameInfo> &chain) -> void {
996
1046
auto parentContextDescriptorBytes = OpaqueByteReader (
997
- remote::RemoteAddress (descriptorAddress ),
1047
+ remote::RemoteAddress (parentContextDescriptorAddress ),
998
1048
sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
999
1049
if (!parentContextDescriptorBytes.get ()) {
1000
1050
Error = " Failed to read context descriptor." ;
1001
- return llvm::None ;
1051
+ return ;
1002
1052
}
1003
- const ExternalContextDescriptor<ObjCInteropKind,
1004
- PointerSize> *parentContextDescriptor =
1053
+ const auto parentDescriptor =
1005
1054
(const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1006
1055
parentContextDescriptorBytes.get ();
1007
-
1008
- if (auto moduleDescriptor = dyn_cast<
1009
- ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1010
- parentContextDescriptor)) {
1011
- auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1012
- moduleDescriptor, parentTargetAddress);
1013
- if (!moduleDescriptorName.hasValue ())
1014
- return llvm::None;
1015
- else
1016
- optionalParentName = moduleDescriptorName;
1017
- } else if (auto typeDescriptor =
1018
- dyn_cast<ExternalTypeContextDescriptor<ObjCInteropKind,
1019
- PointerSize>>(
1020
- parentContextDescriptor)) {
1021
- auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1022
- typeDescriptor, parentTargetAddress);
1023
- if (!typeDescriptorName.hasValue ())
1024
- return llvm::None;
1025
- else
1026
- optionalParentName = typeDescriptorName;
1027
- // Recurse to get this type's parent.
1028
- auto optionalParentParentName =
1029
- getParentContextName (descriptorAddress);
1030
- if (optionalParentParentName.hasValue ()) {
1031
- optionalParentName = optionalParentParentName.getValue () + " ." +
1032
- optionalParentName.getValue ();
1033
- }
1034
- } else {
1035
- Error = " Unexpected type of parent context descriptor." ;
1036
- return llvm::None;
1056
+ const auto parentNameInfo =
1057
+ getContextName (parentContextDescriptorAddress, parentDescriptor);
1058
+ if (!parentNameInfo.hasValue ()) {
1059
+ return ;
1060
+ }
1061
+ chain.push_back (parentNameInfo.getValue ());
1062
+ if (!isModuleDescriptor (parentDescriptor)) {
1063
+ getParentContextChain (parentContextDescriptorAddress,
1064
+ parentDescriptor, chain);
1037
1065
}
1038
-
1039
- return optionalParentName;
1040
1066
};
1041
1067
1042
- // Set low bit indicates that this is an indirect
1043
- // reference
1044
- if (parentTargetAddress & 0x1 ) {
1045
- auto adjustedParentTargetAddress = parentTargetAddress & ~0x1 ;
1068
+ // Set low bit indicates that this is an indirect reference
1069
+ if (parentDescriptorAddress & 0x1 ) {
1070
+ auto adjustedParentTargetAddress = parentDescriptorAddress & ~0x1 ;
1046
1071
if (auto symbol = OpaquePointerReader (
1047
1072
remote::RemoteAddress (adjustedParentTargetAddress),
1048
1073
PointerSize)) {
@@ -1051,20 +1076,21 @@ class TypeRefBuilder {
1051
1076
auto demangledRoot =
1052
1077
Ctx.demangleSymbolAsNode (symbol->getSymbol ().str ());
1053
1078
assert (demangledRoot->getKind () == Node::Kind::Global);
1054
- optionalParentContextName =
1079
+ std::string nodeName =
1055
1080
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1081
+ chain.push_back (
1082
+ ContextNameInfo{nodeName, adjustedParentTargetAddress, false });
1056
1083
} else {
1057
- optionalParentContextName =
1058
- readContextParentName (adjustedParentTargetAddress);
1084
+ addParentNameAndRecurse (adjustedParentTargetAddress, chain);
1059
1085
}
1060
1086
} else {
1061
1087
Error = " Error reading external symbol address." ;
1062
- return llvm::None ;
1088
+ return ;
1063
1089
}
1064
1090
} else {
1065
- optionalParentContextName = readContextParentName (parentTargetAddress );
1091
+ addParentNameAndRecurse (parentDescriptorAddress, chain );
1066
1092
}
1067
- return optionalParentContextName ;
1093
+ return ;
1068
1094
}
1069
1095
1070
1096
llvm::Optional<std::string> readTypeNameFromTypeDescriptor (
@@ -1109,6 +1135,70 @@ class TypeRefBuilder {
1109
1135
return parentName;
1110
1136
}
1111
1137
1138
+ llvm::Optional<std::string> readAnonymousNameFromAnonymousDescriptor (
1139
+ const ExternalAnonymousContextDescriptor<ObjCInteropKind, PointerSize>
1140
+ *anonymousDescriptor,
1141
+ uintptr_t anonymousDescriptorAddress) {
1142
+ if (!anonymousDescriptor->hasMangledName ()) {
1143
+ std::stringstream stream;
1144
+ stream << " (unknown context at $" << std::hex
1145
+ << anonymousDescriptorAddress << " )" ;
1146
+ return stream.str ();
1147
+ }
1148
+ return llvm::None;
1149
+ }
1150
+
1151
+ std::string constructFullyQualifiedNameFromContextChain (
1152
+ const std::vector<ContextNameInfo> &contextNameChain) {
1153
+ std::string newQualifiedTypeName = " " ;
1154
+ std::vector<std::string> reversedQualifiedTypeNameMembers;
1155
+
1156
+ // Traverse the context chain, adding up context names.
1157
+ // Anonymous contexts require special handling: when a type is nested in
1158
+ // an anonymous context, its qualified name is printed as `(type_name in
1159
+ // $hex_val)` where hex_val is the address of the descriptor of the
1160
+ // anonymous parent context.
1161
+ bool skipNext = false ;
1162
+ for (size_t i = 0 ; i < contextNameChain.size (); ++i) {
1163
+ if (skipNext) {
1164
+ skipNext = false ;
1165
+ continue ;
1166
+ }
1167
+ const auto &contextNameInfo = contextNameChain[i];
1168
+ bool lastContext = (i == contextNameChain.size () - 1 );
1169
+ bool currentContextIsAnonymous = contextNameInfo.isAnonymous ;
1170
+ bool nextContextIsAnonymous =
1171
+ lastContext ? false : contextNameChain[i + 1 ].isAnonymous ;
1172
+ if (nextContextIsAnonymous && !currentContextIsAnonymous) {
1173
+ std::stringstream stream;
1174
+ stream << " (" << contextNameInfo.name << " in $" << std::hex
1175
+ << contextNameChain[i + 1 ].descriptorAddress << " )" ;
1176
+ reversedQualifiedTypeNameMembers.push_back (stream.str ());
1177
+ skipNext = true ;
1178
+ } else if (nextContextIsAnonymous && currentContextIsAnonymous) {
1179
+
1180
+ } else if (!nextContextIsAnonymous && !currentContextIsAnonymous) {
1181
+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1182
+ } else if (!nextContextIsAnonymous && currentContextIsAnonymous) {
1183
+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1184
+ } else {
1185
+ llvm_unreachable (" Exhausted possibilities." );
1186
+ }
1187
+ }
1188
+
1189
+ // Combine the individual context name reps into a single fully-qualified
1190
+ // name string
1191
+ for (auto it = reversedQualifiedTypeNameMembers.rbegin ();
1192
+ it != reversedQualifiedTypeNameMembers.rend (); ++it) {
1193
+ newQualifiedTypeName.append (*it);
1194
+ if (std::next (it) != reversedQualifiedTypeNameMembers.rend ()) {
1195
+ newQualifiedTypeName.append (" ." );
1196
+ }
1197
+ }
1198
+
1199
+ return newQualifiedTypeName;
1200
+ }
1201
+
1112
1202
llvm::Optional<std::string> readProtocolNameFromProtocolDescriptor (
1113
1203
uintptr_t protocolDescriptorAddress) {
1114
1204
std::string protocolName;
@@ -1206,14 +1296,14 @@ class TypeRefBuilder {
1206
1296
else
1207
1297
typeName = optionalTypeName.getValue ();
1208
1298
1209
- // Prepend the parent context name
1210
- auto optionalParentName =
1211
- getParentContextName ( contextTypeDescriptorAddress);
1212
- if (optionalParentName. hasValue ()) {
1213
- typeName = optionalParentName. getValue () + " . " + typeName ;
1214
- }
1215
-
1216
- return typeName ;
1299
+ std::vector<ContextNameInfo> contextNameChain;
1300
+ contextNameChain. push_back (
1301
+ ContextNameInfo{typeName, contextTypeDescriptorAddress, false } );
1302
+ getParentContextChain (contextTypeDescriptorAddress, contextDescriptor,
1303
+ contextNameChain) ;
1304
+ std::string fullyQualifiedName =
1305
+ constructFullyQualifiedNameFromContextChain (contextNameChain);
1306
+ return fullyQualifiedName ;
1217
1307
}
1218
1308
1219
1309
// / Extract protocol name from a Conformance Descriptor
@@ -1241,6 +1331,33 @@ class TypeRefBuilder {
1241
1331
(const char *)protocolDescriptorFieldAddress,
1242
1332
(int32_t )*protocolDescriptorOffset);
1243
1333
1334
+ auto constructFullyQualifiedProtocolName =
1335
+ [&](uintptr_t protocolDescriptorAddress)
1336
+ -> llvm::Optional<std::string> {
1337
+ auto protocolName =
1338
+ readProtocolNameFromProtocolDescriptor (protocolDescriptorAddress);
1339
+
1340
+ // Read the protocol conformance descriptor itself
1341
+ auto protocolContextDescriptorBytes = OpaqueByteReader (
1342
+ remote::RemoteAddress (protocolDescriptorAddress),
1343
+ sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1344
+ if (!protocolContextDescriptorBytes.get ()) {
1345
+ Error = " Failed to read context (protocol) descriptor." ;
1346
+ return llvm::None;
1347
+ }
1348
+ const ExternalContextDescriptor<ObjCInteropKind,
1349
+ PointerSize> *protocolDescriptor =
1350
+ (const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1351
+ protocolContextDescriptorBytes.get ();
1352
+
1353
+ std::vector<ContextNameInfo> contextNameChain;
1354
+ contextNameChain.push_back (ContextNameInfo{
1355
+ protocolName.getValue (), protocolDescriptorAddress, false });
1356
+ getParentContextChain (protocolDescriptorAddress, protocolDescriptor,
1357
+ contextNameChain);
1358
+ return constructFullyQualifiedNameFromContextChain (contextNameChain);
1359
+ };
1360
+
1244
1361
// Set low bit indicates that this is an indirect
1245
1362
// reference
1246
1363
if (protocolDescriptorTarget & 0x1 ) {
@@ -1259,16 +1376,9 @@ class TypeRefBuilder {
1259
1376
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1260
1377
} else {
1261
1378
// This is an absolute address of a protocol descriptor
1262
- auto protocolDescriptorAddress = symbol->getOffset ();
1263
- protocolName = readProtocolNameFromProtocolDescriptor (
1264
- protocolDescriptorAddress);
1265
- // Prepend the parent context name
1266
- auto optionalParentName =
1267
- getParentContextName (protocolDescriptorAddress);
1268
- if (optionalParentName.hasValue ()) {
1269
- protocolName =
1270
- optionalParentName.getValue () + " ." + *protocolName;
1271
- }
1379
+ auto protocolDescriptorAddress = (uintptr_t )symbol->getOffset ();
1380
+ protocolName =
1381
+ constructFullyQualifiedProtocolName (protocolDescriptorAddress);
1272
1382
}
1273
1383
} else {
1274
1384
Error = " Error reading external protocol address." ;
@@ -1278,13 +1388,7 @@ class TypeRefBuilder {
1278
1388
// If this is a direct reference, get symbol name from the protocol
1279
1389
// descriptor.
1280
1390
protocolName =
1281
- readProtocolNameFromProtocolDescriptor (protocolDescriptorTarget);
1282
- // Prepend the parent context name
1283
- auto optionalParentName =
1284
- getParentContextName (protocolDescriptorTarget);
1285
- if (optionalParentName.hasValue ()) {
1286
- protocolName = optionalParentName.getValue () + " ." + *protocolName;
1287
- }
1391
+ constructFullyQualifiedProtocolName (protocolDescriptorTarget);
1288
1392
}
1289
1393
1290
1394
return protocolName;
0 commit comments