@@ -92,7 +92,7 @@ class ReflectionContext
92
92
using super = remote::MetadataReader<Runtime, TypeRefBuilder>;
93
93
using super::readMetadata;
94
94
using super::readObjCClassName;
95
-
95
+ using super::readResolvedPointerValue;
96
96
std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
97
97
98
98
// / All buffers we need to keep around long term. This will automatically free them
@@ -789,6 +789,52 @@ class ReflectionContext
789
789
}
790
790
}
791
791
792
+ llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
793
+ getDynamicTypeAndAddressClassExistential (RemoteAddress ExistentialAddress) {
794
+ auto PointerValue =
795
+ readResolvedPointerValue (ExistentialAddress.getAddressData ());
796
+ if (!PointerValue)
797
+ return {};
798
+ auto Result = readMetadataFromInstance (*PointerValue);
799
+ if (!Result)
800
+ return {};
801
+ auto TypeResult = readTypeFromMetadata (Result.getValue ());
802
+ if (!TypeResult)
803
+ return {};
804
+ return {{std::move (TypeResult), RemoteAddress (*PointerValue)}};
805
+ }
806
+
807
+ llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
808
+ getDynamicTypeAndAddressErrorExistential (RemoteAddress ExistentialAddress,
809
+ bool *IsBridgedError = nullptr ) {
810
+ auto Result = readMetadataAndValueErrorExistential (ExistentialAddress);
811
+ if (!Result)
812
+ return {};
813
+
814
+ auto TypeResult =
815
+ readTypeFromMetadata (Result->MetadataAddress .getAddressData ());
816
+ if (!TypeResult)
817
+ return {};
818
+
819
+ if (IsBridgedError)
820
+ *IsBridgedError = Result->IsBridgedError ;
821
+
822
+ return {{TypeResult, Result->PayloadAddress }};
823
+ }
824
+
825
+ llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
826
+ getDynamicTypeAndAddressOpaqueExistential (RemoteAddress ExistentialAddress) {
827
+ auto Result = readMetadataAndValueOpaqueExistential (ExistentialAddress);
828
+ if (!Result)
829
+ return {};
830
+
831
+ auto TypeResult =
832
+ readTypeFromMetadata (Result->MetadataAddress .getAddressData ());
833
+ if (!TypeResult)
834
+ return {};
835
+ return {{std::move (TypeResult), Result->PayloadAddress }};
836
+ }
837
+
792
838
bool projectExistential (RemoteAddress ExistentialAddress,
793
839
const TypeRef *ExistentialTR,
794
840
const TypeRef **OutInstanceTR,
@@ -850,6 +896,75 @@ class ReflectionContext
850
896
return false ;
851
897
}
852
898
}
899
+ // / A version of `projectExistential` tailored for LLDB.
900
+ // / This version dereferences the resulting TypeRef if it wraps
901
+ // / a class type, it also dereferences the input `ExistentialAddress` before
902
+ // / attempting to find its dynamic type and address when dealing with error
903
+ // / existentials.
904
+ llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
905
+ projectExistentialAndUnwrapClass (RemoteAddress ExistentialAddress,
906
+ const TypeRef &ExistentialTR) {
907
+ auto IsClass = [](const TypeRef *TypeResult) {
908
+ // When the existential wraps a class type, LLDB expects that the
909
+ // address returned is the class instance itself and not the address
910
+ // of the reference.
911
+ bool IsClass = TypeResult->getKind () == TypeRefKind::ForeignClass ||
912
+ TypeResult->getKind () == TypeRefKind::ObjCClass;
913
+ if (auto *nominal = llvm::dyn_cast<NominalTypeRef>(TypeResult))
914
+ IsClass = nominal->isClass ();
915
+ else if (auto *boundGeneric =
916
+ llvm::dyn_cast<BoundGenericTypeRef>(TypeResult))
917
+ IsClass = boundGeneric->isClass ();
918
+ return IsClass;
919
+ };
920
+
921
+ auto DereferenceAndSet = [&](RemoteAddress &Address) {
922
+ auto PointerValue = readResolvedPointerValue (Address.getAddressData ());
923
+ if (!PointerValue)
924
+ return false ;
925
+ Address = RemoteAddress (*PointerValue);
926
+ return true ;
927
+ };
928
+
929
+ auto ExistentialRecordTI = getRecordTypeInfo (&ExistentialTR, nullptr );
930
+ if (!ExistentialRecordTI)
931
+ return {};
932
+
933
+ switch (ExistentialRecordTI->getRecordKind ()) {
934
+ case RecordKind::ClassExistential:
935
+ return getDynamicTypeAndAddressClassExistential (ExistentialAddress);
936
+ case RecordKind::ErrorExistential: {
937
+ // LLDB stores the address of the error pointer.
938
+ if (!DereferenceAndSet (ExistentialAddress))
939
+ return {};
940
+
941
+ bool IsBridgedError = false ;
942
+ auto Pair = getDynamicTypeAndAddressErrorExistential (ExistentialAddress,
943
+ &IsBridgedError);
944
+ if (!Pair)
945
+ return {};
946
+
947
+ if (!IsBridgedError && IsClass (std::get<const TypeRef *>(*Pair)))
948
+ if (!DereferenceAndSet (std::get<RemoteAddress>(*Pair)))
949
+ return {};
950
+
951
+ return Pair;
952
+ }
953
+ case RecordKind::OpaqueExistential: {
954
+ auto Pair = getDynamicTypeAndAddressOpaqueExistential (ExistentialAddress);
955
+ if (!Pair)
956
+ return {};
957
+
958
+ if (IsClass (std::get<const TypeRef *>(*Pair)))
959
+ if (!DereferenceAndSet (std::get<RemoteAddress>(*Pair)))
960
+ return {};
961
+
962
+ return Pair;
963
+ }
964
+ default :
965
+ return {};
966
+ }
967
+ }
853
968
854
969
// / Projects the value of an enum.
855
970
// /
@@ -889,6 +1004,12 @@ class ReflectionContext
889
1004
}
890
1005
}
891
1006
1007
+ const RecordTypeInfo *getRecordTypeInfo (const TypeRef *TR,
1008
+ remote::TypeInfoProvider *ExternalTypeInfo) {
1009
+ auto *TypeInfo = getTypeInfo (TR, ExternalTypeInfo);
1010
+ return dyn_cast_or_null<const RecordTypeInfo>(TypeInfo);
1011
+ }
1012
+
892
1013
// / Iterate the protocol conformance cache tree rooted at NodePtr, calling
893
1014
// / Call with the type and protocol in each node.
894
1015
void iterateConformanceTree (StoredPointer NodePtr,
0 commit comments