Skip to content

Commit 22609b3

Browse files
authored
Merge pull request #3024 from augusto2112/remove-remoteast-from-GetDynamicTypeAndAddress_Protocol
[lldb] Replace usage of remote AST with reflection on GetDynamicTypeAndAddress_Protocol.
2 parents ab3414a + 245972a commit 22609b3

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
@@ -1805,18 +1805,128 @@ bool SwiftLanguageRuntimeImpl::IsValidErrorValue(ValueObject &in_value) {
18051805

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

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

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

18211931
lldb::addr_t existential_address;
18221932
bool use_local_buffer = false;
@@ -1841,29 +1951,65 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol(
18411951
if (log)
18421952
log->Printf("existential address is 0x%llx", existential_address);
18431953

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

18471972
if (use_local_buffer)
18481973
PushLocalBuffer(existential_address, in_value.GetByteSize().getValueOr(0));
18491974

18501975
swift::remote::RemoteAddress remote_existential(existential_address);
1851-
auto result = remote_ast.getDynamicTypeAndAddressForExistential(
1852-
remote_existential, GetSwiftType(protocol_type));
18531976

1977+
auto *reflection_ctx = GetReflectionContext();
1978+
auto pair = reflection_ctx->projectExistentialAndUnwrapClass(
1979+
remote_existential, *protocol_typeref);
18541980
if (use_local_buffer)
18551981
PopLocalBuffer();
18561982

1857-
if (!result.isSuccess()) {
1983+
if (!pair) {
18581984
if (log)
1859-
log->Printf("RemoteAST failed to get dynamic type of existential");
1985+
log->Printf("Runtime failed to get dynamic type of existential");
18601986
return false;
18611987
}
18621988

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

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)