Skip to content

[lldb] Improve performance of TypeSystemSwiftTypeRef via lazy canonic… #9808

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
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
157 changes: 93 additions & 64 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type,
TupleElement result;
using namespace swift::Demangle;
Demangler dem;
NodePointer node = TypeSystemSwiftTypeRef::DemangleCanonicalType(dem, type);
NodePointer node = TypeSystemSwiftTypeRef::DemangleCanonicalOutermostType(dem, type);
if (!node || node->getKind() != Node::Kind::Tuple)
return {};
if (node->getNumChildren() < idx)
Expand Down Expand Up @@ -1170,60 +1170,66 @@ Desugar(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node,
return desugared;
}

swift::Demangle::NodePointer
TypeSystemSwiftTypeRef::Canonicalize(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node) {
assert(node);
auto kind = node->getKind();
switch (kind) {
case Node::Kind::SugaredOptional:
// FIXME: Factor these three cases out.
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericEnum, Node::Kind::Enum,
"Optional");
case Node::Kind::SugaredArray: {
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
Node::Kind::Structure, "Array");
}
case Node::Kind::SugaredDictionary:
// FIXME: This isnt covered by any test.
assert(node->getNumChildren() == 2);
if (node->getNumChildren() != 2)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
Node::Kind::Structure, "Dictionary");
case Node::Kind::SugaredParen:
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return node->getFirstChild();

case Node::Kind::BoundGenericTypeAlias:
case Node::Kind::TypeAlias: {
auto node_clangtype = ResolveTypeAlias(dem, node);
if (CompilerType clang_type = node_clangtype.second) {
if (auto result = GetClangTypeNode(clang_type, dem))
return result;
else
return node;
}
if (node_clangtype.first)
return node_clangtype.first;
return node;
}
default:
break;
}
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) {
using namespace swift::Demangle;
return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) {
auto kind = node->getKind();
switch (kind) {
case Node::Kind::SugaredOptional:
// FIXME: Factor these three cases out.
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericEnum, Node::Kind::Enum,
"Optional");
case Node::Kind::SugaredArray: {
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
Node::Kind::Structure, "Array");
}
case Node::Kind::SugaredDictionary:
// FIXME: This isnt covered by any test.
assert(node->getNumChildren() == 2);
if (node->getNumChildren() != 2)
return node;
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
Node::Kind::Structure, "Dictionary");
case Node::Kind::SugaredParen:
assert(node->getNumChildren() == 1);
if (node->getNumChildren() != 1)
return node;
return node->getFirstChild();

case Node::Kind::BoundGenericTypeAlias:
case Node::Kind::TypeAlias: {
auto node_clangtype = ResolveTypeAlias(dem, node);
if (CompilerType clang_type = node_clangtype.second) {
if (auto result = GetClangTypeNode(clang_type, dem))
return result;
else
return node;
}
if (node_clangtype.first)
return node_clangtype.first;
return node;
}
default:
break;
}
return node;
});
return TypeSystemSwiftTypeRef::Transform(
dem, node, [&](NodePointer node) { return Canonicalize(dem, node); });
}

/// Return the demangle tree representation of this type's canonical
Expand Down Expand Up @@ -2427,6 +2433,7 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
ast_ctx->ReconstructType(l.GetMangledTypeName()))
.value_or(nullptr)) == r.GetOpaqueQualType())
return true;

ConstString lhs = l.GetMangledTypeName();
ConstString rhs = r.GetMangledTypeName();
if (lhs == ConstString("$sSiD") && rhs == ConstString("$sSuD"))
Expand All @@ -2442,6 +2449,7 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node));
auto r_mangling = swift::Demangle::mangleNode(
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node));

if (!l_mangling.isSuccess() || !r_mangling.isSuccess()) {
llvm::dbgs() << "TypeSystemSwiftTypeRef diverges from SwiftASTContext "
"(mangle error): "
Expand Down Expand Up @@ -2705,6 +2713,25 @@ swift::Demangle::NodePointer TypeSystemSwiftTypeRef::DemangleCanonicalType(
return GetDemangledType(dem, type.GetMangledTypeName().GetStringRef());
}

swift::Demangle::NodePointer
TypeSystemSwiftTypeRef::DemangleCanonicalOutermostType(
swift::Demangle::Demangler &dem, lldb::opaque_compiler_type_t type) {
using namespace swift::Demangle;
NodePointer node = GetDemangledType(dem, AsMangledName(type));
if (!node)
return nullptr;
NodePointer canonical = Canonicalize(dem, node);
if (canonical &&
canonical->getKind() == swift::Demangle::Node::Kind::TypeAlias) {
// If this is a typealias defined in the expression evaluator,
// then we don't have debug info to resolve it from.
CompilerType ast_type =
ReconstructType({weak_from_this(), type}, nullptr).GetCanonicalType();
return GetDemangledType(dem, ast_type.GetMangledTypeName());
}
return canonical;
}

CompilerType
TypeSystemSwiftTypeRef::CreateGenericTypeParamType(unsigned int depth,
unsigned int index) {
Expand All @@ -2730,7 +2757,7 @@ bool TypeSystemSwiftTypeRef::IsArrayType(opaque_compiler_type_t type,
auto impl = [&]() {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || node->getNumChildren() != 2 ||
node->getKind() != Node::Kind::BoundGenericStructure)
return false;
Expand All @@ -2756,7 +2783,9 @@ bool TypeSystemSwiftTypeRef::IsArrayType(opaque_compiler_type_t type,
return false;
elem_node = elem_node->getFirstChild();
if (element_type)
*element_type = RemangleAsType(dem, elem_node);
// FIXME: This expensive canonicalization is only there for
// SwiftASTContext compatibility.
*element_type = RemangleAsType(dem, elem_node).GetCanonicalType();

if (is_incomplete)
*is_incomplete = true;
Expand All @@ -2773,7 +2802,7 @@ bool TypeSystemSwiftTypeRef::IsAggregateType(opaque_compiler_type_t type) {
auto impl = [&]() -> bool {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);

if (!node)
return false;
Expand Down Expand Up @@ -2811,7 +2840,7 @@ bool TypeSystemSwiftTypeRef::IsFunctionType(opaque_compiler_type_t type) {
auto impl = [&]() -> bool {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
// Note: There are a number of other candidates, and this list may need
// updating. Ex: `NoEscapeFunctionType`, `ThinFunctionType`, etc.
return node && (node->getKind() == Node::Kind::FunctionType ||
Expand All @@ -2826,7 +2855,7 @@ size_t TypeSystemSwiftTypeRef::GetNumberOfFunctionArguments(
auto impl = [&]() -> size_t {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || (node->getKind() != Node::Kind::FunctionType &&
node->getKind() != Node::Kind::NoEscapeFunctionType &&
node->getKind() != Node::Kind::ImplFunctionType))
Expand Down Expand Up @@ -2856,7 +2885,7 @@ TypeSystemSwiftTypeRef::GetFunctionArgumentAtIndex(opaque_compiler_type_t type,
auto impl = [&]() -> CompilerType {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || (node->getKind() != Node::Kind::FunctionType &&
node->getKind() != Node::Kind::NoEscapeFunctionType &&
node->getKind() != Node::Kind::ImplFunctionType))
Expand Down Expand Up @@ -2982,7 +3011,7 @@ bool TypeSystemSwiftTypeRef::IsPointerType(opaque_compiler_type_t type,
auto impl = [&]() {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || node->getKind() != Node::Kind::BuiltinTypeName ||
!node->hasText())
return false;
Expand All @@ -2998,7 +3027,7 @@ bool TypeSystemSwiftTypeRef::IsVoidType(opaque_compiler_type_t type) {
auto impl = [&]() {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
return node && node->getNumChildren() == 0 &&
node->getKind() == Node::Kind::Tuple;
};
Expand Down Expand Up @@ -3176,7 +3205,7 @@ TypeSystemSwiftTypeRef::GetFunctionReturnType(opaque_compiler_type_t type) {
auto impl = [&]() -> CompilerType {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || (node->getKind() != Node::Kind::FunctionType &&
node->getKind() != Node::Kind::NoEscapeFunctionType &&
node->getKind() != Node::Kind::ImplFunctionType))
Expand Down Expand Up @@ -3407,7 +3436,7 @@ lldb::Encoding TypeSystemSwiftTypeRef::GetEncoding(opaque_compiler_type_t type,

using namespace swift::Demangle;
Demangler dem;
auto *node = DemangleCanonicalType(dem, type);
auto *node = DemangleCanonicalOutermostType(dem, type);
if (!node)
return lldb::eEncodingInvalid;
auto kind = node->getKind();
Expand Down Expand Up @@ -3983,7 +4012,7 @@ TypeSystemSwiftTypeRef::GetNumTemplateArguments(opaque_compiler_type_t type,
auto impl = [&]() -> size_t {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);

if (!node)
return 0;
Expand Down Expand Up @@ -4121,7 +4150,7 @@ bool TypeSystemSwiftTypeRef::IsExistentialType(
lldb::opaque_compiler_type_t type) {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || node->getNumChildren() != 1)
return false;
switch (node->getKind()) {
Expand All @@ -4148,7 +4177,7 @@ bool TypeSystemSwiftTypeRef::IsErrorType(opaque_compiler_type_t type) {
auto impl = [&]() -> bool {
using namespace swift::Demangle;
Demangler dem;
NodePointer protocol_list = DemangleCanonicalType(dem, type);
NodePointer protocol_list = DemangleCanonicalOutermostType(dem, type);
if (protocol_list && protocol_list->getKind() == Node::Kind::ProtocolList)
for (auto type_list : *protocol_list)
if (type_list && type_list->getKind() == Node::Kind::TypeList)
Expand Down Expand Up @@ -4918,7 +4947,7 @@ bool TypeSystemSwiftTypeRef::IsReferenceType(opaque_compiler_type_t type,
auto impl = [&]() {
using namespace swift::Demangle;
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || node->getNumChildren() != 1 ||
node->getKind() != Node::Kind::InOut)
return false;
Expand All @@ -4945,7 +4974,7 @@ TypeSystemSwiftTypeRef::GetGenericArgumentType(opaque_compiler_type_t type,
size_t idx) {
auto impl = [&]() -> CompilerType {
Demangler dem;
NodePointer node = DemangleCanonicalType(dem, type);
NodePointer node = DemangleCanonicalOutermostType(dem, type);
if (!node || node->getNumChildren() != 2)
return {};

Expand Down
13 changes: 13 additions & 0 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ 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);

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

/// Demangle the mangled name of \p type after canonicalizing its
/// outermost type node and drill into the
/// Global(TypeMangling(Type())).
///
/// \return the child of Type or a nullptr.
swift::Demangle::NodePointer
DemangleCanonicalOutermostType(swift::Demangle::Demangler &dem,
lldb::opaque_compiler_type_t type);

/// 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