Skip to content

Commit 072a092

Browse files
committed
[LLDB] Add ObjC object typeref support to SwiftRuntimeTypeVisitor
This patch moves the disjunct implementations for TypeSystemTypeRef::GetNumFields and GetIndexOfChildMemberWithName into the TypeRef visitor, so they behave consistently. rdar://154450536
1 parent 03bec58 commit 072a092

File tree

18 files changed

+291
-243
lines changed

18 files changed

+291
-243
lines changed

lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,17 +1018,23 @@ SwiftLanguage::GetHardcodedSynthetics() {
10181018
struct IsEligible {
10191019
static bool Check(ValueObject &valobj, const CompilerType &type) {
10201020
bool is_imported = false;
1021-
1022-
if (type.IsValid()) {
1023-
auto swift_ast_ctx =
1024-
type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
1025-
if (swift_ast_ctx && swift_ast_ctx->IsImportedType(
1026-
type.GetOpaqueQualType(), nullptr))
1027-
is_imported = true;
1028-
}
1029-
1030-
ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1031-
if (is_imported && type.GetNumFields(&exe_ctx) == 0)
1021+
CompilerType clang_type;
1022+
if (!type.IsValid())
1023+
return false;
1024+
auto ts =
1025+
type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
1026+
if (ts &&
1027+
ts->IsImportedType(type.GetOpaqueQualType(), &clang_type))
1028+
is_imported = true;
1029+
1030+
// Could be an Objective-C object with no debug info; we
1031+
// can get ivars from the runtime.
1032+
if (is_imported && !clang_type)
1033+
return true;
1034+
if (clang_type && Flags(clang_type.GetTypeClass())
1035+
.AnySet(eTypeClassObjCInterface |
1036+
eTypeClassObjCObjectPointer |
1037+
eTypeClassObjCObject))
10321038
return true;
10331039
if (valobj.IsBaseClass() && type.IsRuntimeGeneratedType()) {
10341040
auto parent(valobj.GetParent());

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ class SwiftLanguageRuntime : public LanguageRuntime {
402402
llvm::Expected<uint32_t> GetNumChildren(CompilerType type,
403403
ExecutionContextScope *exe_scope,
404404
bool include_superclass = true,
405-
bool include_clang_types = true);
405+
bool omit_empty_base_classes = true);
406406

407407
/// Determine the enum case name for the \p data value of the enum \p type.
408408
/// This is performed using Swift reflection.
@@ -435,11 +435,10 @@ class SwiftLanguageRuntime : public LanguageRuntime {
435435
/// don't have an index.
436436
///
437437
/// \returns {true, {num_idexes}} on success.
438-
std::pair<LookupResult, std::optional<size_t>>
439-
GetIndexOfChildMemberWithName(CompilerType type, llvm::StringRef name,
440-
ExecutionContext *exe_ctx,
441-
bool omit_empty_base_classes,
442-
std::vector<uint32_t> &child_indexes);
438+
std::pair<LookupResult, std::optional<size_t>> GetIndexOfChildMemberWithName(
439+
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
440+
bool omit_empty_base_classes, bool include_clang_types,
441+
std::vector<uint32_t> &child_indexes);
443442

444443
/// Ask Remote Mirrors about a child of a composite type.
445444
llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 150 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "LLDBMemoryReader.h"
14+
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
1415
#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h"
1516
#include "ReflectionContextInterface.h"
1617
#include "SwiftLanguageRuntime.h"
@@ -33,7 +34,9 @@
3334
#include "lldb/ValueObject/ValueObjectMemory.h"
3435
#include "llvm/ADT/STLExtras.h"
3536
#include "llvm/Support/Casting.h"
37+
#include "llvm/Support/Error.h"
3638

39+
#include "lldb/lldb-enumerations.h"
3740
#include "swift/AST/ASTContext.h"
3841
#include "swift/AST/ASTMangler.h"
3942
#include "swift/AST/ASTWalker.h"
@@ -728,7 +731,7 @@ class SwiftRuntimeTypeVisitor {
728731
CompilerType m_type;
729732
ValueObject *m_valobj = nullptr;
730733
bool m_hide_superclass = false;
731-
bool m_include_clang_types = false;
734+
bool m_omit_empty_base_classes = true;
732735
bool m_visit_superclass = false;
733736

734737
void SetFlavor() {
@@ -757,26 +760,27 @@ class SwiftRuntimeTypeVisitor {
757760
using VisitCallback = std::function<llvm::Error(
758761
CompilerType, unsigned, GetChildNameClosure, GetChildInfoClosure)>;
759762
SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type,
760-
ValueObject *valobj)
761-
: m_runtime(runtime), m_type(type), m_valobj(valobj) {
763+
ValueObject *valobj, bool omit_empty_base_classes)
764+
: m_runtime(runtime), m_type(type), m_valobj(valobj),
765+
m_omit_empty_base_classes(omit_empty_base_classes) {
762766
if (valobj)
763767
m_exe_ctx = valobj->GetExecutionContextRef();
764768
SetFlavor();
765769
}
766770
SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type,
767771
ExecutionContextScope *exe_scope,
768-
bool hide_superclass, bool include_clang_types)
772+
bool hide_superclass, bool omit_empty_base_classes)
769773
: m_runtime(runtime), m_type(type), m_hide_superclass(hide_superclass),
770-
m_include_clang_types(include_clang_types) {
774+
m_omit_empty_base_classes(omit_empty_base_classes) {
771775
if (exe_scope)
772776
exe_scope->CalculateExecutionContext(m_exe_ctx);
773777
SetFlavor();
774778
}
775779
SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type,
776780
ExecutionContext *exe_ctx, bool hide_superclass,
777-
bool include_clang_types, bool visit_superclass)
781+
bool omit_empty_base_classes, bool visit_superclass)
778782
: m_runtime(runtime), m_type(type), m_hide_superclass(hide_superclass),
779-
m_include_clang_types(include_clang_types),
783+
m_omit_empty_base_classes(omit_empty_base_classes),
780784
m_visit_superclass(visit_superclass) {
781785
if (exe_ctx)
782786
m_exe_ctx = *exe_ctx;
@@ -800,9 +804,7 @@ class SwiftRuntimeTypeVisitor {
800804

801805
llvm::Expected<unsigned>
802806
SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
803-
VisitCallback visit_callback)
804-
805-
{
807+
VisitCallback visit_callback) {
806808
if (!m_type)
807809
return llvm::createStringError("invalid type");
808810

@@ -854,19 +856,91 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
854856
return success;
855857
}
856858

857-
// FIXME: Remove this entire mode.
858-
assert(!m_include_clang_types || (m_include_clang_types && count_only));
859-
if (m_include_clang_types && count_only) {
859+
auto visit_clang_type =
860+
[&](CompilerType clang_type) -> llvm::Expected<unsigned> {
861+
auto swiftify = [&](CompilerType type) {
862+
if (!type.GetTypeSystem().isa_and_nonnull<TypeSystemClang>())
863+
return type;
864+
CompilerType swift_type = ts.ConvertClangTypeToSwiftType(type);
865+
return swift_type ?: type;
866+
};
867+
unsigned depth = 0;
868+
auto n_or_err =
869+
clang_type.GetNumChildren(m_omit_empty_base_classes, &m_exe_ctx);
870+
if (!n_or_err)
871+
return n_or_err.takeError();
872+
unsigned n = *n_or_err;
873+
bool is_signed, is_enum = clang_type.IsEnumerationType(is_signed);
874+
if (count_only)
875+
return is_enum ? 1 : n;
876+
if (is_enum) {
877+
auto get_name = [&]() -> std::string { return "rawValue"; };
878+
auto get_info = [&]() -> llvm::Expected<ChildInfo> {
879+
auto ts =
880+
clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
881+
882+
if (!ts)
883+
return llvm::createStringError("no clang type system");
884+
clang::EnumDecl *enum_decl = ts->GetAsEnumDecl(clang_type);
885+
if (!enum_decl)
886+
return llvm::createStringError("no enum decl");
887+
swift::Demangle::Demangler dem;
888+
CompilerType raw_value =
889+
CompilerType(ts, enum_decl->getIntegerType().getAsOpaquePtr());
890+
891+
auto bit_size =
892+
raw_value.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
893+
if (!bit_size)
894+
return bit_size.takeError();
895+
ChildInfo child;
896+
child.byte_size = *bit_size / 8;
897+
child.byte_offset = 0;
898+
child.bitfield_bit_size = 0;
899+
child.bitfield_bit_offset = 0;
900+
child.is_base_class = false;
901+
child.is_deref_of_parent = false;
902+
child.language_flags = 0;
903+
return child;
904+
};
905+
return visit_callback(clang_type, depth, get_name, get_info);
906+
}
907+
for (unsigned i = 0; i < n; ++i)
908+
if (!visit_only || *visit_only == i) {
909+
bool transparent_pointers = false;
910+
bool ignore_array_bounds = false;
911+
std::string child_name;
912+
ChildInfo child;
913+
auto child_type_or_err = clang_type.GetChildCompilerTypeAtIndex(
914+
&m_exe_ctx, i, transparent_pointers, m_omit_empty_base_classes,
915+
ignore_array_bounds, child_name, child.byte_size, child.byte_offset,
916+
child.bitfield_bit_size, child.bitfield_bit_offset,
917+
child.is_base_class, child.is_deref_of_parent, nullptr,
918+
child.language_flags);
919+
if (!child_type_or_err)
920+
return child_type_or_err.takeError();
921+
CompilerType type = swiftify(*child_type_or_err);
922+
auto get_name = [&]() -> std::string { return child_name; };
923+
auto get_info = [&]() -> llvm::Expected<ChildInfo> { return child; };
924+
if (auto err = visit_callback(type, depth, get_name, get_info))
925+
return err;
926+
}
927+
return success;
928+
};
929+
930+
{
860931
CompilerType clang_type = m_runtime.LookupAnonymousClangType(
861932
m_type.GetMangledTypeName().AsCString());
862933
if (!clang_type)
863934
ts.IsImportedType(m_type.GetOpaqueQualType(), &clang_type);
864935
if (clang_type) {
865936
clang_type = GetTypedefedTypeRecursive(clang_type);
866-
bool is_signed;
867-
if (clang_type.IsEnumerationType(is_signed))
868-
return 1;
869-
return clang_type.GetNumChildren(true, &m_exe_ctx);
937+
auto result = visit_clang_type(clang_type);
938+
if (result)
939+
return result;
940+
// FIXME: It would be nice not to fall through here. CFStringRef
941+
// needs this path right now.
942+
LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), result.takeError(),
943+
"could not resolve as clang type: {0}");
870944
}
871945
}
872946

@@ -1113,6 +1187,57 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional<unsigned> visit_only,
11131187
if (ts.IsBuiltinType(m_type))
11141188
return 0;
11151189

1190+
// Resolve ObjC references via the ObjC runtime.
1191+
auto visit_objcclass = [&](const swift::reflection::ObjCClassTypeRef &tr)
1192+
-> llvm::Expected<unsigned> {
1193+
const std::string &name = tr.getName();
1194+
auto *process = m_exe_ctx.GetProcessPtr();
1195+
if (!process)
1196+
return llvm::createStringError(
1197+
"cannot resolve objc type without process");
1198+
auto objc_runtime = SwiftLanguageRuntime::GetObjCRuntime(*process);
1199+
if (!process)
1200+
return llvm::createStringError("no Objective-C runtime");
1201+
AppleObjCRuntime::ObjCISA isa = objc_runtime->GetISA(ConstString(name));
1202+
if (!isa)
1203+
return llvm::createStringError("no Objective-C class " + name);
1204+
AppleObjCRuntime::ClassDescriptorSP desc_sp =
1205+
objc_runtime->GetClassDescriptorFromISA(isa);
1206+
if (!desc_sp)
1207+
return llvm::createStringError("no class descriptor for " + name);
1208+
bool has_super = !m_hide_superclass && desc_sp->GetSuperclass();
1209+
unsigned n = 0;
1210+
if (count_only)
1211+
return has_super ? n + 1 : n;
1212+
1213+
unsigned depth = 0;
1214+
if (has_super)
1215+
if (!visit_only || *visit_only == i) {
1216+
if (AppleObjCRuntime::ClassDescriptorSP superclass_desc_sp =
1217+
desc_sp->GetSuperclass()) {
1218+
auto get_name = [&]() -> std::string {
1219+
return superclass_desc_sp->GetClassName().GetString();
1220+
};
1221+
auto get_info = [&]() -> llvm::Expected<ChildInfo> {
1222+
return ChildInfo();
1223+
};
1224+
CompilerType type;
1225+
if (TypeSP type_sp = superclass_desc_sp->GetType())
1226+
type = type_sp->GetForwardCompilerType();
1227+
if (auto err = visit_callback(type, depth, get_name, get_info))
1228+
return err;
1229+
if (visit_only)
1230+
return success;
1231+
}
1232+
}
1233+
// We could query the runtime for the children here but that
1234+
// would be inconsistent with SwiftASTContext.
1235+
return success;
1236+
};
1237+
if (auto *obj_tr =
1238+
llvm::dyn_cast_or_null<swift::reflection::ObjCClassTypeRef>(tr))
1239+
return visit_objcclass(*obj_tr);
1240+
11161241
LLDBTypeInfoProvider tip(m_runtime, ts);
11171242
auto cti_or_err = reflection_ctx->GetClassInstanceTypeInfo(
11181243
*tr, &tip, ts.GetDescriptorFinder());
@@ -1452,9 +1577,9 @@ SwiftLanguageRuntime::GetNumFields(CompilerType type,
14521577

14531578
llvm::Expected<uint32_t> SwiftLanguageRuntime::GetNumChildren(
14541579
CompilerType type, ExecutionContextScope *exe_scope,
1455-
bool include_superclass, bool include_clang_types) {
1580+
bool include_superclass, bool omit_empty_base_classes) {
14561581
SwiftRuntimeTypeVisitor visitor(*this, type, exe_scope, !include_superclass,
1457-
include_clang_types);
1582+
omit_empty_base_classes);
14581583
return visitor.CountChildren();
14591584
}
14601585

@@ -1622,8 +1747,10 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) {
16221747
std::pair<SwiftLanguageRuntime::LookupResult, std::optional<size_t>>
16231748
SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
16241749
CompilerType type, llvm::StringRef name, ExecutionContext *exe_ctx,
1625-
bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
1626-
SwiftRuntimeTypeVisitor visitor(*this, type, exe_ctx, false, false, true);
1750+
bool omit_empty_base_classes, bool include_clang_types,
1751+
std::vector<uint32_t> &child_indexes) {
1752+
SwiftRuntimeTypeVisitor visitor(*this, type, exe_ctx, false,
1753+
include_clang_types, true);
16271754
bool found = false;
16281755
unsigned i = 0, last_depth = 0;
16291756
llvm::Error error = visitor.VisitAllChildren(
@@ -1640,7 +1767,7 @@ SwiftLanguageRuntime::GetIndexOfChildMemberWithName(
16401767
return info_or_err.takeError();
16411768
// All enum children are index 0.
16421769
if (info_or_err->is_enum || name == get_child_name()) {
1643-
// The only access paths supperted are into base classes,
1770+
// The only access paths supported are into base classes,
16441771
// which are always at index 0.
16451772
for (unsigned j = 0; j < depth; ++j)
16461773
child_indexes.push_back(0);
@@ -1670,7 +1797,7 @@ llvm::Expected<CompilerType> SwiftLanguageRuntime::GetChildCompilerTypeAtIndex(
16701797
uint64_t &language_flags) {
16711798
CompilerType child_type;
16721799
bool found = false;
1673-
SwiftRuntimeTypeVisitor visitor(*this, type, valobj);
1800+
SwiftRuntimeTypeVisitor visitor(*this, type, valobj, omit_empty_base_classes);
16741801
llvm::Error error = visitor.VisitChildAtIndex(
16751802
idx,
16761803
[&](CompilerType type, unsigned depth, auto get_child_name,

0 commit comments

Comments
 (0)