Skip to content

Commit ca25ed6

Browse files
authored
Merge pull request #3204 from augusto2112/remove-remoteast-from-GetDynamicTypeAndAddress_Class
[lldb] Use reflection to get the dynamic type of a class
2 parents 3672975 + 824e91c commit ca25ed6

File tree

7 files changed

+103
-56
lines changed

7 files changed

+103
-56
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -471,18 +471,17 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
471471
}
472472
}
473473

474-
if (m_options.GetGenerateDebugInfo()) {
475-
StreamString jit_module_name;
476-
jit_module_name.Printf("%s%u", FunctionName(),
477-
m_options.GetExpressionNumber());
478-
auto module = m_execution_unit_sp->CreateJITModule(jit_module_name.GetString().data());
479-
480-
auto *swift_runtime = SwiftLanguageRuntime::Get(process);
481-
if (module && swift_runtime) {
482-
ModuleList modules;
483-
modules.Append(module, false);
484-
swift_runtime->ModulesDidLoad(modules);
485-
}
474+
StreamString jit_module_name;
475+
jit_module_name.Printf("%s%u", FunctionName(),
476+
m_options.GetExpressionNumber());
477+
auto module =
478+
m_execution_unit_sp->CreateJITModule(jit_module_name.GetString().data());
479+
480+
auto *swift_runtime = SwiftLanguageRuntime::Get(process);
481+
if (module && swift_runtime) {
482+
ModuleList modules;
483+
modules.Append(module, false);
484+
swift_runtime->ModulesDidLoad(modules);
486485
}
487486

488487
if (jit_error.Success()) {

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

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,23 +1575,6 @@ bool SwiftLanguageRuntimeImpl::ForEachSuperClassType(
15751575
return false;
15761576

15771577
lldb::addr_t pointer = instance.GetPointerValue();
1578-
// Maybe this belongs into GetPointerValue, but on the other hand it
1579-
// is also nice to not hide the existence of reference storage
1580-
// types. Perhaps they should even be modelled in the ValueObject
1581-
// hierarchy. This also partially papers over the fact that
1582-
// libReflection cannot tell up how many bits to strip from
1583-
// multi-payload enum values.
1584-
auto addr_deref =
1585-
FixupPointerValue(pointer, instance_type);
1586-
pointer = addr_deref.first;
1587-
if (addr_deref.second) {
1588-
// This is a reference storage object.
1589-
if (!reflection_ctx->getReader().readInteger(
1590-
swift::reflection::RemoteAddress(addr_deref.first),
1591-
&pointer))
1592-
return false;
1593-
}
1594-
15951578
auto md_ptr = reflection_ctx->readMetadataFromInstance(pointer);
15961579
if (!md_ptr)
15971580
return false;
@@ -1670,6 +1653,21 @@ static bool IsScratchContextLocked(TargetSP target) {
16701653
return target ? IsScratchContextLocked(*target) : true;
16711654
}
16721655

1656+
static bool IsPrivateNSClass(NodePointer node) {
1657+
if (!node || node->getKind() != Node::Kind::Type ||
1658+
node->getNumChildren() == 0)
1659+
return false;
1660+
NodePointer classNode = node->getFirstChild();
1661+
if (!classNode || classNode->getKind() != Node::Kind::Class ||
1662+
classNode->getNumChildren() < 2)
1663+
return false;
1664+
for (NodePointer child : *classNode)
1665+
if (child->getKind() == Node::Kind::Identifier && child->hasText())
1666+
return child->getText().startswith("__NS") ||
1667+
child->getText().startswith("NSTaggedPointer");
1668+
return false;
1669+
}
1670+
16731671
bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
16741672
ValueObject &in_value, SwiftASTContextForExpressions &scratch_ctx,
16751673
lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name,
@@ -1678,37 +1676,86 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
16781676
lldb::addr_t class_metadata_ptr = in_value.GetPointerValue(&address_type);
16791677
if (class_metadata_ptr == LLDB_INVALID_ADDRESS || class_metadata_ptr == 0)
16801678
return false;
1681-
address.SetRawAddress(class_metadata_ptr);
16821679

1680+
CompilerType static_type = in_value.GetCompilerType();
1681+
auto *tss =
1682+
llvm::dyn_cast_or_null<TypeSystemSwift>(static_type.GetTypeSystem());
1683+
if (!tss)
1684+
return false;
1685+
address.SetRawAddress(class_metadata_ptr);
1686+
auto &ts = tss->GetTypeSystemSwiftTypeRef();
1687+
// Ask the Objective-C runtime about Objective-C types.
1688+
if (tss->IsImportedType(static_type.GetOpaqueQualType(), nullptr))
1689+
if (auto *objc_runtime = SwiftLanguageRuntime::GetObjCRuntime(m_process)) {
1690+
Value::ValueType value_type;
1691+
if (objc_runtime->GetDynamicTypeAndAddress(
1692+
in_value, use_dynamic, class_type_or_name, address, value_type)) {
1693+
bool found = false;
1694+
// Return the most specific class which we can get the typeref.
1695+
ForEachSuperClassType(in_value, [&](SuperClassType sc) -> bool {
1696+
if (auto *tr = sc.get_typeref()) {
1697+
swift::Demangle::Demangler dem;
1698+
swift::Demangle::NodePointer node = tr->getDemangling(dem);
1699+
// Skip private Foundation types since it's unlikely that would be
1700+
// useful to users.
1701+
if (IsPrivateNSClass(node))
1702+
return false;
1703+
class_type_or_name.SetCompilerType(ts.RemangleAsType(dem, node));
1704+
found = true;
1705+
return true;
1706+
}
1707+
return false;
1708+
});
1709+
return found;
1710+
}
1711+
return false;
1712+
}
16831713
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
1684-
auto &remote_ast = GetRemoteASTContext(scratch_ctx);
1714+
auto *reflection_ctx = GetReflectionContext();
16851715
swift::remote::RemoteAddress instance_address(class_metadata_ptr);
1686-
auto metadata_address = remote_ast.getHeapMetadataForObject(instance_address);
1716+
auto metadata_address =
1717+
reflection_ctx->readMetadataFromInstance(class_metadata_ptr);
16871718
if (!metadata_address) {
1688-
if (log) {
1689-
log->Printf("could not read heap metadata for object at %llu: %s\n",
1690-
class_metadata_ptr,
1691-
metadata_address.getFailure().render().c_str());
1692-
}
1693-
1719+
if (log)
1720+
log->Printf("could not read heap metadata for object at %llu\n",
1721+
class_metadata_ptr);
16941722
return false;
16951723
}
16961724

1697-
auto instance_type =
1698-
remote_ast.getTypeForRemoteTypeMetadata(metadata_address.getValue(),
1699-
/*skipArtificial=*/true);
1700-
if (!instance_type) {
1701-
if (log) {
1702-
log->Printf("could not get type metadata from address %" PRIu64 " : %s\n",
1703-
metadata_address.getValue().getAddressData(),
1704-
instance_type.getFailure().render().c_str());
1705-
}
1725+
const auto *typeref =
1726+
reflection_ctx->readTypeFromMetadata(*metadata_address,
1727+
/*skipArtificial=*/false);
1728+
if (!typeref)
17061729
return false;
1730+
swift::Demangle::Demangler dem;
1731+
swift::Demangle::NodePointer node = typeref->getDemangling(dem);
1732+
class_type_or_name.SetCompilerType(ts.RemangleAsType(dem, node));
1733+
1734+
#ifndef NDEBUG
1735+
auto &remote_ast = GetRemoteASTContext(scratch_ctx);
1736+
auto remote_ast_metadata_address =
1737+
remote_ast.getHeapMetadataForObject(instance_address);
1738+
if (remote_ast_metadata_address) {
1739+
auto instance_type = remote_ast.getTypeForRemoteTypeMetadata(
1740+
remote_ast_metadata_address.getValue(),
1741+
/*skipArtificial=*/true);
1742+
if (instance_type) {
1743+
auto ref_type = ToCompilerType(instance_type.getValue());
1744+
ConstString a = ref_type.GetMangledTypeName();
1745+
ConstString b = class_type_or_name.GetCompilerType().GetMangledTypeName();
1746+
if (a != b)
1747+
llvm::dbgs() << "RemoteAST and runtime diverge " << a << " != " << b
1748+
<< "\n";
1749+
} else {
1750+
if (log) {
1751+
log->Printf(
1752+
"could not get type metadata from address %" PRIu64 " : %s\n",
1753+
*metadata_address, instance_type.getFailure().render().c_str());
1754+
}
1755+
}
17071756
}
17081757

1709-
// The read lock must have been acquired by the caller.
1710-
class_type_or_name.SetCompilerType(
1711-
{&scratch_ctx, instance_type.getValue().getPointer()});
1758+
#endif
17121759
return true;
17131760
}
17141761

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,6 +2597,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
25972597
if (suffix.consume_front("__ObjC."))
25982598
ast_child_name = suffix.str();
25992599
assert((llvm::StringRef(child_name).contains('.') ||
2600+
llvm::StringRef(ast_child_name).contains('.') ||
26002601
Equivalent(child_name, ast_child_name)));
26012602
assert(ast_language_flags ||
26022603
(Equivalent(llvm::Optional<uint64_t>(child_byte_size),

lldb/test/API/lang/swift/dwarfimporter/objc-header/TestSwiftDWARFImporter-Swift.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ def test(self):
5151
elif found == 2 and response == 1 and 'SwiftDWARFImporterDelegate' in line:
5252
self.assertTrue('types collected' in line, line)
5353
response += 1
54-
self.assertEqual(found, 3)
54+
self.assertEqual(found, 1)
5555
self.assertEqual(response, 1)

lldb/test/API/lang/swift/dynamic_value/TestSwiftDynamicValue.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def dynamic_val_commands(self):
5454
"z = ",
5555
"Derived<Int>) aBase = 0x",
5656
"Base<Int>)",
57-
".Base = {",
57+
".Base<Swift.Int> = {",
5858
"v = 449493530",
5959
"q = 3735928559"])
6060
self.runCmd("continue")
@@ -76,6 +76,6 @@ def dynamic_val_commands(self):
7676
"z = ",
7777
"Derived<Int>) aBase = 0x",
7878
"Base<Int>)",
79-
".Base = {",
79+
".Base<Swift.Int> = {",
8080
"v = 449493530",
8181
"q = 3735928559"])

lldb/test/API/lang/swift/generics/TestSwiftGenericsResolution.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def genericresolution_commands(self):
4141
substrs=[
4242
"(Int) x = 123",
4343
"(a.OtherClass<Int>) self = 0x",
44-
"a.AClass = {}",
44+
"a.AClass<Swift.Int> = {}",
4545
"v = 1234567"])
4646
self.runCmd("continue")
4747
self.expect(
@@ -76,7 +76,7 @@ def genericresolution_commands(self):
7676
"(Int) x = 5",
7777
'(String) y = "hello world"',
7878
"(a.OtherClass<Int>) self = 0x",
79-
"a.AClass = {}",
79+
"a.AClass<Swift.Int> = {}",
8080
"v = 1234567"])
8181
self.runCmd("continue")
8282
self.expect(

lldb/test/Shell/SwiftREPL/OptionalWithDynamicType.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// REQUIRES: system-darwin
55
// REQUIRES: swift
66

7-
// RUN: %lldb --repl < %s 2>&1 | FileCheck %s
7+
// RUN: %lldb --repl < %s | FileCheck %s
88

99
import Foundation
1010

0 commit comments

Comments
 (0)