Skip to content

[lldb] Change the type alias resolution algorithm #10036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 54 additions & 7 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,22 +1264,69 @@ TypeSystemSwiftTypeRef::Canonicalize(swift::Demangle::Demangler &dem,
// Hit the safeguard limit.
return node;
}
default:
break;
default: {
llvm::SmallVector<NodePointer, 2> children;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code meant to both be here and in GetCanonicalNode?

bool changed = false;
for (NodePointer child : *node) {
NodePointer transformed = GetCanonicalNode(dem, child, flavor);
changed |= (child != transformed);
children.push_back(transformed);
}
if (changed) {
// Create a new node with the transformed children.
auto kind = node->getKind();
if (node->hasText())
node = dem.createNodeWithAllocatedText(kind, node->getText());
else if (node->hasIndex())
node = dem.createNode(kind, node->getIndex());
else
node = dem.createNode(kind);
for (NodePointer transformed_child : children)
node->addChild(transformed_child, dem);
}
return node;
}
}
return node;
}

/// Iteratively resolve all type aliases in \p node by looking up their
/// desugared types in the debug info of module \p M.
swift::Demangle::NodePointer
TypeSystemSwiftTypeRef::GetCanonicalNode(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor) {
if (!node)
return nullptr;
// This is a pre-order traversal, which is necessary to resolve
// generic type aliases that bind other type aliases in one go,
// instead of first resolving the bound type aliases. Debug Info
// will have a record for SomeAlias<SomeOtherAlias> but not
// SomeAlias<WhatSomeOtherAliasResolvesTo> because it tries to
// preserve all sugar.
using namespace swift::Demangle;
return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) {
return Canonicalize(dem, node, flavor);
});
NodePointer transformed = Canonicalize(dem, node, flavor);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this block of code be in a separate function called TransformPreOrder?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only a single use, and it has shortcut in that it won't traverse the children of a transformed node, which is something a generic preorder transform maybe shouldn't do, so I decided to punt on that until we have a second use-case.

if (node != transformed)
return transformed;

llvm::SmallVector<NodePointer, 2> children;
bool changed = false;
for (NodePointer child : *node) {
NodePointer transformed_child = GetCanonicalNode(dem, child, flavor);
changed |= (child != transformed_child);
children.push_back(transformed_child);
}
if (changed) {
// Create a new node with the transformed children.
auto kind = node->getKind();
if (node->hasText())
node = dem.createNodeWithAllocatedText(kind, node->getText());
else if (node->hasIndex())
node = dem.createNode(kind, node->getIndex());
else
node = dem.createNode(kind);
for (NodePointer transformed_child : children)
node->addChild(transformed_child, dem);
}
return node;
}

/// Return the demangle tree representation of this type's canonical
Expand Down
33 changes: 15 additions & 18 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
AdjustTypeForOriginallyDefinedInModule(llvm::StringRef mangled_typename);

/// Return the canonicalized Demangle tree for a Swift mangled type name.
/// It resolves all type aliases and removes sugar.
swift::Demangle::NodePointer
GetCanonicalDemangleTree(swift::Demangle::Demangler &dem,
llvm::StringRef mangled_name);
Expand Down Expand Up @@ -460,13 +461,6 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
/// Cast \p opaque_type as a mangled name.
static const char *AsMangledName(lldb::opaque_compiler_type_t type);

/// Helper function that canonicalizes node, but doesn't look at its
/// children.
swift::Demangle::NodePointer
Canonicalize(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor);

/// Demangle the mangled name of the canonical type of \p type and
/// drill into the Global(TypeMangling(Type())).
///
Expand All @@ -484,6 +478,20 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
DemangleCanonicalOutermostType(swift::Demangle::Demangler &dem,
lldb::opaque_compiler_type_t type);

/// Desugar to this node and if it is a type alias resolve it by
/// looking up its type in the debug info.
swift::Demangle::NodePointer
Canonicalize(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor);

/// Iteratively desugar and resolve all type aliases in \p node by
/// looking up their types in the debug info.
swift::Demangle::NodePointer
GetCanonicalNode(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor);

/// If \p node is a Struct/Class/Typedef in the __C module, return a
/// Swiftified node by looking up the name in the corresponding APINotes and
/// optionally putting it into the correctly named module.
Expand Down Expand Up @@ -514,12 +522,6 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
CompilerType LookupClangForwardType(llvm::StringRef name,
llvm::ArrayRef<CompilerContext> decl_context);

/// Recursively resolves all type aliases.
swift::Demangle::NodePointer

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResolveAllTypeAliases is gone from the header but not implementation?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It never existed!

ResolveAllTypeAliases(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor);

/// Resolve a type alias node and return a demangle tree for the
/// resolved type. If the type alias resolves to a Clang type, return
/// a Clang CompilerType.
Expand All @@ -531,11 +533,6 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor, bool prefer_clang_types = false);

swift::Demangle::NodePointer
GetCanonicalNode(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor);

uint32_t CollectTypeInfo(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
swift::Mangle::ManglingFlavor flavor,
Expand Down
7 changes: 5 additions & 2 deletions lldb/test/API/lang/swift/typealias/TestSwiftTypeAlias.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ class TestSwiftTypeAlias(TestBase):
def test(self):
"""Test type aliases are only searched in the debug info once"""
self.build()
log = self.getBuildArtifact("dwarf.log")
self.expect("log enable dwarf lookups -f " + log)
if self.TraceOn():
log = self.getBuildArtifact("dwarf.log")
self.expect("log enable dwarf lookups -f " + log)

target, process, _, _ = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.swift"), extra_images=['Dylib'])
self.expect("target variable foo", substrs=["(Dylib.MyAlias)", "23"])
self.expect("target variable bar",
substrs=["(Dylib.MyGenericAlias<Dylib.MyAlias>)", "42"])
self.expect("target variable baz",
substrs=["(Dylib.MyGenericAlias<a.LocalAlias>)", "42"])
3 changes: 2 additions & 1 deletion lldb/test/API/lang/swift/typealias/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ typealias LocalAlias = Foo
let local = LocalAlias()
let foo = MyAlias()
let bar = MyGenericAlias<MyAlias>()
print("\(local), \(foo), \(bar)") // break here
let baz = MyGenericAlias<LocalAlias>()
print("\(local), \(foo), \(bar), \(baz)") // break here