Skip to content

Commit 9c840dc

Browse files
committed
[lldb] Unify implementation of GetNumChildren and GetNumFields
These functions had incredibly similar implementations, but GetNumFields was missing some of the edge cases implemented in GetNumChildren. rdar://147771956
1 parent 73daaea commit 9c840dc

File tree

8 files changed

+67
-96
lines changed

8 files changed

+67
-96
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,9 @@ class SwiftLanguageRuntime : public LanguageRuntime {
376376

377377
/// Ask Remote Mirrors about the children of a composite type.
378378
llvm::Expected<uint32_t> GetNumChildren(CompilerType type,
379-
ExecutionContextScope *exe_scope);
379+
ExecutionContextScope *exe_scope,
380+
bool include_superclass = true,
381+
bool include_clang_types = true);
380382

381383
/// Determine the enum case name for the \p data value of the enum \p type.
382384
/// This is performed using Swift reflection.
@@ -422,7 +424,7 @@ class SwiftLanguageRuntime : public LanguageRuntime {
422424
uint64_t &language_flags);
423425

424426
/// Ask Remote Mirrors about the fields of a composite type.
425-
std::optional<unsigned> GetNumFields(CompilerType type,
427+
llvm::Expected<unsigned> GetNumFields(CompilerType type,
426428
ExecutionContext *exe_ctx);
427429

428430
/// Ask Remote Mirrors for the size of a Swift type.

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

Lines changed: 15 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,17 @@ CompilerType GetTypedefedTypeRecursive(CompilerType type) {
709709
} // namespace
710710

711711
llvm::Expected<uint32_t>
712-
SwiftLanguageRuntime::GetNumChildren(CompilerType type,
713-
ExecutionContextScope *exe_scope) {
712+
SwiftLanguageRuntime::GetNumFields(CompilerType type,
713+
ExecutionContext *exe_ctx) {
714+
if (exe_ctx)
715+
return GetNumChildren(type, exe_ctx->GetBestExecutionContextScope(), false,
716+
false);
717+
return llvm::createStringError("no execution context");
718+
}
719+
720+
llvm::Expected<uint32_t> SwiftLanguageRuntime::GetNumChildren(
721+
CompilerType type, ExecutionContextScope *exe_scope,
722+
bool include_superclass, bool include_clang_types) {
714723
LLDB_SCOPED_TIMER();
715724

716725
auto ts_sp = type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
@@ -726,7 +735,7 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
726735
return pack_type->count;
727736

728737
// Deal with Clang types.
729-
{
738+
if (include_clang_types) {
730739
CompilerType clang_type =
731740
LookupAnonymousClangType(type.GetMangledTypeName().AsCString());
732741
if (!clang_type)
@@ -806,7 +815,7 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
806815
if (GetWeakReferent(ts, type))
807816
return 1;
808817
break;
809-
default:
818+
case swift::reflection::ReferenceKind::Strong:
810819
break;
811820
}
812821

@@ -838,7 +847,8 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
838847
type.GetMangledTypeName(), rti->getNumFields());
839848

840849
// The superclass, if any, is an extra child.
841-
if (reflection_ctx->LookupSuperclass(*tr, ts.GetDescriptorFinder()))
850+
if (include_superclass &&
851+
reflection_ctx->LookupSuperclass(*tr, ts.GetDescriptorFinder()))
842852
return rti->getNumFields() + 1;
843853
return rti->getNumFields();
844854
}
@@ -867,91 +877,6 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
867877
type.GetMangledTypeName().GetString());
868878
}
869879

870-
std::optional<unsigned>
871-
SwiftLanguageRuntime::GetNumFields(CompilerType type,
872-
ExecutionContext *exe_ctx) {
873-
auto ts_sp = type.GetTypeSystem().dyn_cast_or_null<TypeSystemSwiftTypeRef>();
874-
if (!ts_sp)
875-
return {};
876-
auto &ts = *ts_sp;
877-
878-
using namespace swift::reflection;
879-
// Try the static type metadata.
880-
const TypeRef *tr = nullptr;
881-
auto ti_or_err = GetSwiftRuntimeTypeInfo(
882-
type, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr, &tr);
883-
if (!ti_or_err) {
884-
LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), ti_or_err.takeError(), "{0}");
885-
return {};
886-
}
887-
auto *ti = &*ti_or_err;
888-
889-
// Structs and Tuples.
890-
switch (ti->getKind()) {
891-
case TypeInfoKind::Record: {
892-
// Structs and Tuples.
893-
auto *rti = llvm::cast<RecordTypeInfo>(ti);
894-
switch (rti->getRecordKind()) {
895-
case RecordKind::ExistentialMetatype:
896-
case RecordKind::ThickFunction:
897-
// There are two fields, `function` and `context`, but they're not exposed
898-
// by lldb.
899-
return 0;
900-
case RecordKind::OpaqueExistential:
901-
// `OpaqueExistential` is documented as:
902-
// An existential is a three-word buffer followed by value metadata...
903-
// The buffer is exposed as fields named `payload_data_{0,1,2}`, and
904-
// the number of fields are increased to match.
905-
return rti->getNumFields() + 3;
906-
default:
907-
return rti->getNumFields();
908-
}
909-
}
910-
case TypeInfoKind::Builtin: {
911-
// Clang types without debug info may present themselves like this.
912-
return {};
913-
}
914-
case TypeInfoKind::Enum: {
915-
auto *eti = llvm::cast<EnumTypeInfo>(ti);
916-
return eti->getNumPayloadCases();
917-
}
918-
case TypeInfoKind::Reference: {
919-
// Objects.
920-
auto *rti = llvm::cast<ReferenceTypeInfo>(ti);
921-
switch (rti->getReferenceKind()) {
922-
case ReferenceKind::Weak:
923-
case ReferenceKind::Unowned:
924-
case ReferenceKind::Unmanaged:
925-
if (auto referent = GetWeakReferent(ts, type))
926-
return referent.GetNumFields(exe_ctx);
927-
return 0;
928-
case ReferenceKind::Strong:
929-
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
930-
if (!reflection_ctx)
931-
return {};
932-
if (!tr)
933-
return {};
934-
935-
LLDBTypeInfoProvider tip(*this, ts);
936-
auto cti_or_err = reflection_ctx->GetClassInstanceTypeInfo(
937-
*tr, &tip, ts.GetDescriptorFinder());
938-
if (!cti_or_err) {
939-
LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), cti_or_err.takeError(),
940-
"GetNumFields failed: {0}");
941-
return {};
942-
}
943-
if (auto *rti = llvm::dyn_cast_or_null<RecordTypeInfo>(&*cti_or_err))
944-
return rti->getNumFields();
945-
946-
return {};
947-
}
948-
}
949-
default:
950-
LogUnimplementedTypeKind(__FUNCTION__, type);
951-
return {};
952-
}
953-
}
954-
955880
static std::pair<SwiftLanguageRuntime::LookupResult, std::optional<size_t>>
956881
findFieldWithName(const std::vector<swift::reflection::FieldInfo> &fields,
957882
const swift::reflection::TypeRef *tr, llvm::StringRef name,

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3782,10 +3782,15 @@ uint32_t TypeSystemSwiftTypeRef::GetNumFields(opaque_compiler_type_t type,
37823782
LLDB_SCOPED_TIMER();
37833783
auto impl = [&]() -> std::optional<uint32_t> {
37843784
if (exe_ctx)
3785-
if (auto *runtime = SwiftLanguageRuntime::Get(exe_ctx->GetProcessSP()))
3786-
if (auto num_fields =
3787-
runtime->GetNumFields(GetCanonicalType(type), exe_ctx))
3788-
return num_fields;
3785+
if (auto *runtime = SwiftLanguageRuntime::Get(exe_ctx->GetProcessSP())) {
3786+
auto num_fields_or_err =
3787+
runtime->GetNumFields(GetCanonicalType(type), exe_ctx);
3788+
if (num_fields_or_err)
3789+
return *num_fields_or_err;
3790+
LLDB_LOG_ERROR(GetLog(LLDBLog::Types), num_fields_or_err.takeError(),
3791+
"GetNumFields failed for type {1}: {0}",
3792+
AsMangledName(type));
3793+
}
37893794

37903795
bool is_imported = false;
37913796
if (auto clang_type = GetAsClangTypeOrNull(type, &is_imported)) {
@@ -4983,6 +4988,8 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
49834988
is_base_class);
49844989
return false;
49854990
}
4991+
case Node::Kind::ProtocolList:
4992+
return false;
49864993
default:
49874994
assert(false && "Unhandled node kind");
49884995
LLDB_LOGF(GetLog(LLDBLog::Types),
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS = -Xcc -I$(SRCDIR)
3+
4+
include Makefile.rules
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@protocol P
2+
@end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
6+
class TestSwiftObjCProtocol(TestBase):
7+
@skipUnlessDarwin
8+
@swiftTest
9+
def test(self):
10+
"""Test printing an Objective-C protocol existential member."""
11+
self.build()
12+
lldbutil.run_to_source_breakpoint(
13+
self, 'break here', lldb.SBFileSpec('main.swift')
14+
)
15+
16+
self.expect("v self", substrs=["obj", "0x"])
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import P
2+
3+
class ImplementsP : P {}
4+
5+
class C {
6+
init(p: P) { x = p }
7+
weak var x : P?
8+
9+
func f() {
10+
print("break here")
11+
}
12+
}
13+
14+
C(p: ImplementsP()).f()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module P { header "P.h" }

0 commit comments

Comments
 (0)