@@ -92,7 +92,7 @@ class ReflectionContext
9292 using super = remote::MetadataReader<Runtime, TypeRefBuilder>;
9393 using super::readMetadata;
9494 using super::readObjCClassName;
95-
95+ using super::readResolvedPointerValue;
9696 std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
9797
9898 // / All buffers we need to keep around long term. This will automatically free them
@@ -789,6 +789,52 @@ class ReflectionContext
789789 }
790790 }
791791
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+
792838 bool projectExistential (RemoteAddress ExistentialAddress,
793839 const TypeRef *ExistentialTR,
794840 const TypeRef **OutInstanceTR,
@@ -850,6 +896,75 @@ class ReflectionContext
850896 return false ;
851897 }
852898 }
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+ }
853968
854969 // / Projects the value of an enum.
855970 // /
@@ -889,6 +1004,12 @@ class ReflectionContext
8891004 }
8901005 }
8911006
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+
8921013 // / Iterate the protocol conformance cache tree rooted at NodePtr, calling
8931014 // / Call with the type and protocol in each node.
8941015 void iterateConformanceTree (StoredPointer NodePtr,
0 commit comments