Skip to content

Commit 245972a

Browse files
committed
[lldb] Replace usage of remote AST with reflection on GetDynamicTypeAndAddress_Protocol.
1 parent bf4bea8 commit 245972a

File tree

6 files changed

+165
-14
lines changed

6 files changed

+165
-14
lines changed

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

Lines changed: 156 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,18 +1808,128 @@ bool SwiftLanguageRuntimeImpl::IsValidErrorValue(ValueObject &in_value) {
18081808

18091809
return true;
18101810
}
1811+
/// Digs into the protocols inside a protocol composition and checks if
1812+
/// any of them belong to the LLDB module.
1813+
static bool
1814+
IsDeclaredInLLDBExpr(const swift::reflection::TypeRef *typeref) {
1815+
using swift::Demangle::Node;
1816+
1817+
const auto *protocol_typeref = llvm::dyn_cast_or_null<
1818+
const swift::reflection::ProtocolCompositionTypeRef>(typeref);
1819+
1820+
if (!protocol_typeref)
1821+
return false;
1822+
1823+
swift::Demangle::Demangler dem;
1824+
1825+
NodePointer type = protocol_typeref->getDemangling(dem);
1826+
if (!type || type->getKind() != Node::Kind::Type ||
1827+
type->getNumChildren() == 0)
1828+
return false;
1829+
1830+
NodePointer maybe_protocol_list = type->getFirstChild();
1831+
NodePointer protocol_list;
1832+
1833+
if (!maybe_protocol_list)
1834+
return false;
1835+
1836+
switch (maybe_protocol_list->getKind()) {
1837+
case Node::Kind::ProtocolList:
1838+
protocol_list = maybe_protocol_list;
1839+
break;
1840+
case Node::Kind::ProtocolListWithAnyObject:
1841+
case Node::Kind::ProtocolListWithClass:
1842+
if (maybe_protocol_list->getNumChildren() == 0)
1843+
return false;
1844+
protocol_list = maybe_protocol_list->getFirstChild();
1845+
break;
1846+
default:
1847+
return false;
1848+
}
1849+
1850+
if (!protocol_list || protocol_list->getKind() != Node::Kind::ProtocolList ||
1851+
protocol_list->getNumChildren() == 0)
1852+
return false;
1853+
1854+
NodePointer type_list = protocol_list->getFirstChild();
1855+
if (!type_list || type_list->getKind() != Node::Kind::TypeList)
1856+
return false;
1857+
1858+
for (NodePointer internal_type : *type_list) {
1859+
if (!internal_type || internal_type->getKind() != Node::Kind::Type ||
1860+
internal_type->getNumChildren() == 0)
1861+
continue;
1862+
1863+
NodePointer protocol = internal_type->getFirstChild();
1864+
if (!protocol || protocol->getKind() != Node::Kind::Protocol ||
1865+
protocol->getNumChildren() == 0)
1866+
continue;
1867+
1868+
NodePointer module = protocol->getFirstChild();
1869+
if (!module || module->getKind() != Node::Kind::Module ||
1870+
!module->hasText())
1871+
continue;
1872+
1873+
if (module->getText().startswith("__lldb_expr_"))
1874+
return true;
1875+
}
1876+
return false;
1877+
}
18111878

18121879
bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol(
18131880
ValueObject &in_value, CompilerType protocol_type,
18141881
SwiftASTContextForExpressions &scratch_ctx,
18151882
lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name,
18161883
Address &address) {
1884+
auto remote_ast_impl = [&](bool use_local_buffer,
1885+
lldb::addr_t existential_address)
1886+
-> llvm::Optional<std::pair<CompilerType, Address>> {
1887+
swift::remote::RemoteAddress remote_existential(existential_address);
1888+
auto &remote_ast = GetRemoteASTContext(scratch_ctx);
1889+
auto swift_type = GetSwiftType(protocol_type);
1890+
if (!swift_type)
1891+
return {};
1892+
if (use_local_buffer)
1893+
PushLocalBuffer(existential_address,
1894+
in_value.GetByteSize().getValueOr(0));
1895+
1896+
auto result = remote_ast.getDynamicTypeAndAddressForExistential(
1897+
remote_existential, swift_type);
1898+
if (use_local_buffer)
1899+
PopLocalBuffer();
1900+
1901+
if (!result.isSuccess())
1902+
return {};
1903+
1904+
auto type_and_address = result.getValue();
1905+
1906+
CompilerType type = ToCompilerType(type_and_address.InstanceType);
1907+
Address address;
1908+
address.SetRawAddress(type_and_address.PayloadAddress.getAddressData());
1909+
return {{type, address}};
1910+
};
1911+
18171912
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
18181913

18191914
auto &target = m_process.GetTarget();
18201915
assert(IsScratchContextLocked(target) &&
18211916
"Swift scratch context not locked ahead");
1822-
auto &remote_ast = GetRemoteASTContext(scratch_ctx);
1917+
1918+
auto *tss =
1919+
llvm::dyn_cast_or_null<TypeSystemSwift>(protocol_type.GetTypeSystem());
1920+
if (!tss) {
1921+
if (log)
1922+
log->Printf("Could not get type system swift");
1923+
return false;
1924+
}
1925+
1926+
const swift::reflection::TypeRef *protocol_typeref =
1927+
GetTypeRef(protocol_type, tss->GetSwiftASTContext());
1928+
if (!protocol_typeref) {
1929+
if (log)
1930+
log->Printf("Could not get protocol typeref");
1931+
return false;
1932+
}
18231933

18241934
lldb::addr_t existential_address;
18251935
bool use_local_buffer = false;
@@ -1844,29 +1954,65 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol(
18441954
if (log)
18451955
log->Printf("existential address is 0x%llx", existential_address);
18461956

1847-
if (!existential_address || existential_address == LLDB_INVALID_ADDRESS)
1957+
if (!existential_address || existential_address == LLDB_INVALID_ADDRESS) {
1958+
if (log)
1959+
log->Printf("Existential address is invalid");
18481960
return false;
1961+
}
1962+
1963+
// If the protocol list contains any types declared in LLDB,
1964+
// we use the remote AST implementation since we currently
1965+
// don't register the metadata generated by LLDB.
1966+
if (IsDeclaredInLLDBExpr(protocol_typeref)) {
1967+
auto pair = remote_ast_impl(use_local_buffer, existential_address);
1968+
if (!pair)
1969+
return false;
1970+
class_type_or_name.SetCompilerType(std::get<CompilerType>(*pair));
1971+
address = std::get<Address>(*pair);
1972+
return true;
1973+
}
18491974

18501975
if (use_local_buffer)
18511976
PushLocalBuffer(existential_address, in_value.GetByteSize().getValueOr(0));
18521977

18531978
swift::remote::RemoteAddress remote_existential(existential_address);
1854-
auto result = remote_ast.getDynamicTypeAndAddressForExistential(
1855-
remote_existential, GetSwiftType(protocol_type));
18561979

1980+
auto *reflection_ctx = GetReflectionContext();
1981+
auto pair = reflection_ctx->projectExistentialAndUnwrapClass(
1982+
remote_existential, *protocol_typeref);
18571983
if (use_local_buffer)
18581984
PopLocalBuffer();
18591985

1860-
if (!result.isSuccess()) {
1986+
if (!pair) {
18611987
if (log)
1862-
log->Printf("RemoteAST failed to get dynamic type of existential");
1988+
log->Printf("Runtime failed to get dynamic type of existential");
18631989
return false;
18641990
}
18651991

1866-
auto type_and_address = result.getValue();
1867-
class_type_or_name.SetCompilerType(
1868-
ToCompilerType(type_and_address.InstanceType));
1869-
address.SetRawAddress(type_and_address.PayloadAddress.getAddressData());
1992+
const swift::reflection::TypeRef *typeref;
1993+
swift::remote::RemoteAddress out_address(nullptr);
1994+
std::tie(typeref, out_address) = *pair;
1995+
auto &ts = tss->GetTypeSystemSwiftTypeRef();
1996+
swift::Demangle::Demangler dem;
1997+
swift::Demangle::NodePointer node = typeref->getDemangling(dem);
1998+
class_type_or_name.SetCompilerType(ts.RemangleAsType(dem, node));
1999+
address.SetRawAddress(out_address.getAddressData());
2000+
2001+
#ifndef NDEBUG
2002+
auto reference_pair = remote_ast_impl(use_local_buffer, existential_address);
2003+
assert(pair.hasValue() >= reference_pair.hasValue() &&
2004+
"RemoteAST and runtime diverge");
2005+
2006+
if (reference_pair) {
2007+
CompilerType ref_type = std::get<CompilerType>(*reference_pair);
2008+
Address ref_address = std::get<Address>(*reference_pair);
2009+
ConstString a = class_type_or_name.GetCompilerType().GetMangledTypeName();
2010+
ConstString b = ref_type.GetMangledTypeName();
2011+
if (a != b)
2012+
llvm::dbgs() << "RemoteAST and runtime diverge " << a << " != " << b
2013+
<< "\n";
2014+
}
2015+
#endif
18702016
return true;
18712017
}
18722018

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ class SwiftASTContext : public TypeSystemSwift {
166166
Target *target = nullptr);
167167

168168
SwiftASTContext(const SwiftASTContext &rhs) = delete;
169+
170+
TypeSystemSwiftTypeRef &GetTypeSystemSwiftTypeRef() override {
171+
return m_typeref_typesystem;
172+
}
169173

170174
~SwiftASTContext();
171175

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Decl;
2828
namespace lldb_private {
2929
class TypeSystemClang;
3030
class SwiftASTContext;
31-
31+
class TypeSystemSwiftTypeRef;
3232
/// The implementation of lldb::Type's m_payload field for TypeSystemSwift.
3333
class TypePayloadSwift {
3434
/// Layout: bit 1 ... IsFixedValueBuffer.
@@ -109,6 +109,7 @@ class TypeSystemSwift : public TypeSystem {
109109

110110
static LanguageSet GetSupportedLanguagesForTypes();
111111
virtual SwiftASTContext *GetSwiftASTContext() = 0;
112+
virtual TypeSystemSwiftTypeRef &GetTypeSystemSwiftTypeRef() = 0;
112113
virtual Module *GetModule() const = 0;
113114
virtual lldb::TypeSP GetCachedType(ConstString mangled) = 0;
114115
virtual void SetCachedType(ConstString mangled,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
5050

5151
TypeSystemSwiftTypeRef(SwiftASTContext *swift_ast_context);
5252
SwiftASTContext *GetSwiftASTContext() override { return m_swift_ast_context; }
53+
TypeSystemSwiftTypeRef &GetTypeSystemSwiftTypeRef() override { return *this; }
5354

5455
Module *GetModule() const override;
5556
swift::CanType GetCanonicalSwiftType(CompilerType compiler_type);

lldb/test/API/lang/swift/clangimporter/dynamic_type_resolution_import_conflict/TestSwiftDynamicTypeResolutionImportConflict.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ def test(self):
6969
self.expect("fr v -d run-target -- input",
7070
substrs=['(Dylib.LibraryProtocol) input'])
7171
self.expect("expr -d run-target -- input",
72-
substrs=['(Dylib.LibraryProtocol)'])
72+
substrs=['(a.FromMainModule)'])

lldb/test/API/lang/swift/private_import/TestSwiftPrivateImport.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def test_private_import(self):
3333
lldbutil.run_to_source_breakpoint(
3434
self, 'break here', lldb.SBFileSpec('main.swift'),
3535
extra_images=['Library'])
36-
# We should not be able to resolve the types.
37-
self.expect("fr var -d run -- x", substrs=["(Any)"])
36+
self.expect("fr var -d run -- x", substrs=["(Invisible.InvisibleStruct)"])
3837
# FIXME: This crashes LLDB with a Swift DESERIALIZATION FAILURE.
3938
# self.expect("fr var -d run -- y", substrs=["(Any)"])

0 commit comments

Comments
 (0)