diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 277a4967fcc8d..3470975d4033f 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "LLDBMemoryReader.h" +#include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" #include "ReflectionContextInterface.h" #include "SwiftLanguageRuntime.h" #include "SwiftMetadataCache.h" @@ -607,13 +608,14 @@ std::optional SwiftLanguageRuntime::GetMemberVariableOffset( namespace { CompilerType GetTypeFromTypeRef(TypeSystemSwiftTypeRef &ts, - const swift::reflection::TypeRef *type_ref) { + const swift::reflection::TypeRef *type_ref, + swift::Mangle::ManglingFlavor flavor) { if (!type_ref) return {}; swift::Demangle::Demangler dem; swift::Demangle::NodePointer node = type_ref->getDemangling(dem); // TODO: the mangling flavor should come from the TypeRef. - return ts.RemangleAsType(dem, node, ts.GetManglingFlavor()); + return ts.RemangleAsType(dem, node, flavor); } struct ExistentialSyntheticChild { @@ -627,7 +629,8 @@ struct ExistentialSyntheticChild { llvm::SmallVector GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, const swift::reflection::TypeRef *tr, - const swift::reflection::TypeInfo *ti) { + const swift::reflection::TypeInfo *ti, + swift::Mangle::ManglingFlavor flavor) { llvm::SmallVector children; auto *protocol_composition_tr = llvm::dyn_cast(tr); @@ -641,7 +644,8 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, children.push_back({"object", [=]() { if (auto *super_class_tr = protocol_composition_tr->getSuperclass()) - return GetTypeFromTypeRef(*ts_sp, super_class_tr); + return GetTypeFromTypeRef(*ts_sp, super_class_tr, + flavor); else return rti ? ts_sp->GetBuiltinUnknownObjectType() : ts_sp->GetBuiltinRawPointerType(); @@ -652,9 +656,9 @@ GetExistentialSyntheticChildren(TypeSystemSwiftTypeRef &ts, for (unsigned i = 1; i < fields.size(); ++i) { TypeSystemSwiftTypeRefSP ts_sp = ts.GetTypeSystemSwiftTypeRef(); auto *type_ref = fields[i].TR; - children.push_back({fields[i].Name, [=]() { - return GetTypeFromTypeRef(*ts_sp, type_ref); - }}); + children.push_back( + {fields[i].Name, + [=]() { return GetTypeFromTypeRef(*ts_sp, type_ref, flavor); }}); } } } @@ -702,12 +706,20 @@ CompilerType GetTypedefedTypeRecursive(CompilerType type) { class SwiftRuntimeTypeVisitor { SwiftLanguageRuntime &m_runtime; ExecutionContext m_exe_ctx; + swift::Mangle::ManglingFlavor m_flavor = + swift::Mangle::ManglingFlavor::Default; CompilerType m_type; ValueObject *m_valobj = nullptr; bool m_hide_superclass = false; bool m_include_clang_types = false; bool m_visit_superclass = false; + void SetFlavor() { + if (auto ts_sp = + m_type.GetTypeSystem().dyn_cast_or_null()) + m_flavor = ts_sp->GetManglingFlavor(&m_exe_ctx); + } + public: struct ChildInfo { uint32_t byte_size = 0; @@ -732,6 +744,7 @@ class SwiftRuntimeTypeVisitor { : m_runtime(runtime), m_type(type), m_valobj(valobj) { if (valobj) m_exe_ctx = valobj->GetExecutionContextRef(); + SetFlavor(); } SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type, ExecutionContextScope *exe_scope, @@ -740,6 +753,7 @@ class SwiftRuntimeTypeVisitor { m_include_clang_types(include_clang_types) { if (exe_scope) exe_scope->CalculateExecutionContext(m_exe_ctx); + SetFlavor(); } SwiftRuntimeTypeVisitor(SwiftLanguageRuntime &runtime, CompilerType type, ExecutionContext *exe_ctx, bool hide_superclass, @@ -749,6 +763,7 @@ class SwiftRuntimeTypeVisitor { m_visit_superclass(visit_superclass) { if (exe_ctx) m_exe_ctx = *exe_ctx; + SetFlavor(); } llvm::Error VisitAllChildren(VisitCallback callback) { return VisitImpl({}, callback).takeError(); @@ -871,7 +886,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, field_type = tuple->element_type; else { if (!field_type) - field_type = GetTypeFromTypeRef(ts, field.TR); + field_type = GetTypeFromTypeRef(ts, field.TR, m_flavor); } auto get_info = [&]() -> llvm::Expected { ChildInfo child; @@ -968,7 +983,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, if (rti->getRecordKind() == swift::reflection::RecordKind::ClassExistential) { // Compatibility with SwiftASTContext. - auto children = GetExistentialSyntheticChildren(ts, tr, ti); + auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor); if (count_only) return children.size(); auto visit_existential = [&](ExistentialSyntheticChild c, unsigned idx) { @@ -1019,7 +1034,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, llvm::dyn_cast_or_null(ti)) { // Is this an Existential? unsigned i = 0; - auto children = GetExistentialSyntheticChildren(ts, tr, ti); + auto children = GetExistentialSyntheticChildren(ts, tr, ti, m_flavor); if (children.size()) { if (count_only) return children.size(); @@ -1109,7 +1124,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, if (auto *super_tr = reflection_ctx->LookupSuperclass( *tr, ts.GetDescriptorFinder())) if (auto error = visit_callback( - GetTypeFromTypeRef(ts, super_tr), depth, + GetTypeFromTypeRef(ts, super_tr, m_flavor), depth, []() -> std::string { return ""; }, []() -> llvm::Expected { return ChildInfo(); @@ -1143,8 +1158,9 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, return ChildInfo(); }; - if (auto error = visit_callback(GetTypeFromTypeRef(ts, super_tr), 0, - get_name, get_info)) + if (auto error = + visit_callback(GetTypeFromTypeRef(ts, super_tr, m_flavor), 0, + get_name, get_info)) return error; } @@ -1263,7 +1279,7 @@ SwiftRuntimeTypeVisitor::VisitImpl(std::optional visit_only, return success; } - CompilerType super_type = GetTypeFromTypeRef(ts, type_ref); + CompilerType super_type = GetTypeFromTypeRef(ts, type_ref, m_flavor); auto get_name = [&]() -> std::string { auto child_name = super_type.GetTypeName().GetStringRef().str(); // FIXME: This should be fixed in GetDisplayTypeName instead! @@ -1471,6 +1487,8 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { if (!ti_or_err) return ti_or_err.takeError(); auto *ti = &*ti_or_err; + auto flavor = + SwiftLanguageRuntime::GetManglingFlavor(enum_type.GetMangledTypeName()); auto project_indirect_enum = [&](uint64_t offset, std::string name) -> llvm::Expected { @@ -1496,13 +1514,14 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { auto &field = rti->getFields()[0]; auto *type_ref = field.TR; payload += field.Offset; - payload_type = GetTypeFromTypeRef(ts, type_ref); + payload_type = GetTypeFromTypeRef(ts, type_ref, flavor); break; } case swift::reflection::RecordKind::Tuple: { std::vector elts; for (auto &field : rti->getFields()) - elts.emplace_back(ConstString(), GetTypeFromTypeRef(ts, field.TR)); + elts.emplace_back(ConstString(), + GetTypeFromTypeRef(ts, field.TR, flavor)); payload_type = ts.CreateTupleType(elts); break; } @@ -1570,7 +1589,7 @@ SwiftLanguageRuntime::ProjectEnum(ValueObject &valobj) { if (is_indirect_enum) return project_indirect_enum(field_info.Offset, field_info.Name); - CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR); + CompilerType projected_type = GetTypeFromTypeRef(ts, field_info.TR, flavor); if (field_info.Offset != 0) { assert(false); return llvm::createStringError("enum with unexpected offset"); @@ -1678,7 +1697,9 @@ CompilerType SwiftLanguageRuntime::GetBaseClass(CompilerType class_ty) { } auto *super_tr = reflection_ctx->LookupSuperclass( *type_ref_or_err, tr_ts->GetDescriptorFinder()); - return GetTypeFromTypeRef(*tr_ts, super_tr); + auto flavor = + SwiftLanguageRuntime::GetManglingFlavor(class_ty.GetMangledTypeName()); + return GetTypeFromTypeRef(*tr_ts, super_tr, flavor); } bool SwiftLanguageRuntime::ForEachSuperClassType( @@ -3393,9 +3414,9 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( // Resolve all generic type parameters in the type for the current // frame. Generic parameter binding has to happen in the scratch // context. + ExecutionContext exe_ctx; if (exe_scope) if (StackFrame *frame = exe_scope->CalculateStackFrame().get()) { - ExecutionContext exe_ctx; frame->CalculateExecutionContext(exe_ctx); auto bound_type_or_err = BindGenericTypeParameters(*frame, type); if (!bound_type_or_err) @@ -3417,6 +3438,30 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( if (!reflection_ctx) return llvm::createStringError("no reflection context"); + // The TypeSystemSwiftTypeRefForExpressions doesn't ve a SymbolFile, + // so any DWARF lookups for Embedded Swift fail. + // + // FIXME: It's unclear whether this is safe to do in a non-LTO Swift program. + if (llvm::isa(tr_ts.get()) && + tr_ts->GetManglingFlavor(&exe_ctx) == + swift::Mangle::ManglingFlavor::Embedded) { + if (auto frame_sp = exe_ctx.GetFrameSP()) { + auto &sc = frame_sp->GetSymbolContext(eSymbolContextModule); + if (sc.module_sp) { + auto ts_or_err = + sc.module_sp->GetTypeSystemForLanguage(eLanguageTypeSwift); + if (!ts_or_err) + return ts_or_err.takeError(); + if (auto *tr_ts = llvm::dyn_cast_or_null( + ts_or_err->get())) { + LLDBTypeInfoProvider provider(*this, *tr_ts); + return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, + tr_ts->GetDescriptorFinder()); + } + } + } + } + LLDBTypeInfoProvider provider(*this, ts); return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, tr_ts->GetDescriptorFinder()); @@ -3555,7 +3600,7 @@ SwiftLanguageRuntime::ResolveTypeAlias(CompilerType alias) { type_ref = &*type_ref_or_err; } - CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref); + CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref, flavor); LLDB_LOG(GetLog(LLDBLog::Types), "Resolved type alias {0} = {1} using reflection metadata.", alias.GetMangledTypeName(), resolved.GetMangledTypeName()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp index 9d576340420eb..3a146cd06375f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp @@ -184,10 +184,9 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc, if (TypeSP desugared_type = get_type(die)) { // For a typedef, store the once desugared type as the name. CompilerType type = desugared_type->GetForwardCompilerType(); - if (auto swift_ast_ctx = + if (auto ts = type.GetTypeSystem().dyn_cast_or_null()) - preferred_name = - swift_ast_ctx->GetMangledTypeName(type.GetOpaqueQualType()); + preferred_name = ts->GetMangledTypeName(type.GetOpaqueQualType()); } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h index 03f7f73c19444..ff6abf12e52c4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.h @@ -37,6 +37,8 @@ class DWARFASTParserSwift : public lldb_private::plugin::dwarf::DWARFASTParser, virtual ~DWARFASTParserSwift(); + static std::pair + ResolveTypeAlias(lldb_private::CompilerType alias); lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, bool *type_is_new_ptr) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp index dc9e73d2137b2..d6e69d0f56149 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwiftDescriptorFinder.cpp @@ -55,6 +55,87 @@ findUnsubstitutedGenericTypeAndDIE(TypeSystemSwiftTypeRef &ts, ts.GetTypeFromMangledTypename(ConstString(mangled_name)); return {{unsubstituted_type, unsubstituted_die}}; } + +lldb_private::CompilerType static MapTypeIntoContext( + TypeSystemSwiftTypeRef &ts, lldb_private::CompilerType context, + lldb_private::CompilerType type) { + return ts.ApplySubstitutions( + type.GetOpaqueQualType(), + ts.GetSubstitutions(context.GetOpaqueQualType())); +} + +std::pair +DWARFASTParserSwift::ResolveTypeAlias(lldb_private::CompilerType alias) { + if (!alias) + return {}; + auto ts_sp = alias.GetTypeSystem().dyn_cast_or_null(); + if (!ts_sp) + return {}; + auto &ts = *ts_sp; + auto *dwarf = llvm::dyn_cast_or_null(ts.GetSymbolFile()); + if (!dwarf) + return {}; + + // Type aliases are (for LLVM implementation reasons) using the + // DW_AT_name as linkage name, so they can't be looked up by base + // name. This should be fixed. + // Meanwhile, instead find them inside their parent type. + CompilerType parent_ctx = ts.GetParentType(alias.GetOpaqueQualType()); + if (!parent_ctx) + return {}; + + DWARFDIE parent_die; + if (TypeSP parent_type = + ts.FindTypeInModule(parent_ctx.GetOpaqueQualType())) { + parent_die = dwarf->GetDIE(parent_type->GetID()); + auto unsubstituted_pair = + findUnsubstitutedGenericTypeAndDIE(ts, parent_die); + if (unsubstituted_pair) + parent_die = unsubstituted_pair->second; + } + if (!parent_die) + return {}; + std::string alias_name = ts.GetBaseName(alias.GetOpaqueQualType()); + for (DWARFDIE child_die : parent_die.children()) { + auto tag = child_die.Tag(); + if (tag == llvm::dwarf::DW_TAG_member) + continue; + std::string base_name; + const auto *name = + child_die.GetAttributeValueAsString(llvm::dwarf::DW_AT_name, ""); + if (name && *name == '$') { + CompilerType candidate = ts.GetTypeFromMangledTypename(ConstString(name)); + base_name = ts.GetBaseName(candidate.GetOpaqueQualType()); + } else { + base_name = name; + } + if (base_name != alias_name) + continue; + + // Follow the typedef. + auto *dwarf_parser = ts.GetDWARFParser(); + if (!dwarf_parser) + return {}; + Type *t = dwarf_parser->GetTypeForDIE(child_die); + if (!t) + return {}; + CompilerType cty = t->GetForwardCompilerType(); + if (ts.IsMeaninglessWithoutDynamicResolution(cty.GetOpaqueQualType())) { + // Substitute the parameters in the LHS of the BGTAT. + if (ts.IsBoundGenericAliasType(alias.GetOpaqueQualType())) { + auto subs = ts.GetSubstitutions(alias.GetOpaqueQualType()); + while (subs.size() > 1) + subs.erase(subs.begin()); + cty = ts.ApplySubstitutions(cty.GetOpaqueQualType(), subs); + } + // Substitute the parameters of the RHS of the (BGT)AT. + return {t->shared_from_this(), MapTypeIntoContext(ts, parent_ctx, cty)}; + } + return {t->shared_from_this(), cty}; + } + return {}; +} + /// Given a type system and a typeref, return the compiler type and die of the /// type that matches that mangled name, looking up the in the type system's /// module's debug information. @@ -78,10 +159,17 @@ getTypeAndDie(TypeSystemSwiftTypeRef &ts, auto *dwarf = llvm::cast_or_null(ts.GetSymbolFile()); if (!dwarf) return {}; - auto lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType()); + TypeSP lldb_type = ts.FindTypeInModule(type.GetOpaqueQualType()); + if (!lldb_type) { + std::tie(lldb_type, type) = DWARFASTParserSwift::ResolveTypeAlias(type); + if (lldb_type) { + auto die = dwarf->GetDIE(lldb_type->GetID()); + return {{type, die}}; + } + } if (!lldb_type) { - // TODO: for embedded Swift this is fine but consult other modules here for - // general case? + // TODO: for embedded Swift this is fine but consult other modules + // here for general case? LLDB_LOGV(GetLog(LLDBLog::Types), "Could not find type {0} in module", type.GetMangledTypeName()); return {}; @@ -374,7 +462,6 @@ DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) { lldb_private::AutoBool::False && "Full DWARF debugging for Swift is disabled!"); - auto pair = getTypeAndDie(m_swift_typesystem, TR); if (!pair) return nullptr; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 37a7c5ab694a5..410085bb33ab9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -387,7 +387,7 @@ Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const { static CompilerContext GetContextEntry(DWARFDIE die, bool derive_template_names) { - auto ctx = [die](CompilerContextKind kind) { + auto ctx = [&](CompilerContextKind kind) { return CompilerContext(kind, ConstString(die.GetName())); }; diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 01c6afeb3db67..2b66ef417742d 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -38,6 +38,7 @@ #include "lldb/Utility/Timer.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-types.h" #include "swift/../../lib/ClangImporter/ClangAdapter.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/Demangling/Demangle.h" @@ -366,6 +367,14 @@ TypeSystemSwiftTypeRef::GetBaseName(swift::Demangle::NodePointer node) { } return {}; } + case Node::Kind::TypeAlias: { + if (node->getNumChildren() != 2) + return {}; + NodePointer ident = node->getChild(1); + if (ident && ident->hasText()) + return ident->getText(); + return {}; + } default: // Visit the child nodes. for (NodePointer child : *node) @@ -374,6 +383,15 @@ TypeSystemSwiftTypeRef::GetBaseName(swift::Demangle::NodePointer node) { } } +std::string +TypeSystemSwiftTypeRef::GetBaseName(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, AsMangledName(type)); + return GetBaseName(node).str(); +} + CompilerType TypeSystemSwiftTypeRef::GetTypeFromTypeMetadataNode( llvm::StringRef mangled_name) { Demangler dem; @@ -1022,6 +1040,16 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, }; TypeResults results; + + + std::vector decl_context; + BuildDeclContext(node, decl_context); + if (decl_context.size() && + decl_context[0].kind == CompilerContextKind::Module && + decl_context[0].name.GetStringRef().starts_with("__lldb")) + decl_context.erase(decl_context.begin()); + + // TypeQuery query(decl_context, TypeQueryOptions::e_find_one); TypeQuery query(mangled.GetStringRef(), TypeQueryOptions::e_find_one); if (!prefer_clang_types) { // First check if this type has already been parsed from DWARF. @@ -1041,7 +1069,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, "Could not resolve type alias {0}: {1}", mangled.AsCString()); } - // Do an even more expensive global search. target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results); @@ -1053,7 +1080,22 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, } } - if (prefer_clang_types || !results.Done(query)) { + TypeSP type; + if (results.Done(query)) + type = results.GetFirstType(); + + // Find the type by declcontext (-gdwarf-types). + if (!type && flavor == swift::Mangle::ManglingFlavor::Embedded) { + auto resolved = DWARFASTParserSwift::ResolveTypeAlias( + GetTypeFromMangledTypename(mangled)); + if (resolved.second) { + NodePointer n = + GetDemangledType(dem, resolved.second.GetMangledTypeName()); + return {n, {}}; + } + } + + if (prefer_clang_types || !type) { // No Swift type found -- this could be a Clang typedef. This // check is not done earlier because a Clang typedef that points // to a builtin type, e.g., "typedef unsigned uint32_t", could @@ -1066,7 +1108,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, return {{}, clang_type}; } - TypeSP type = results.GetFirstType(); if (!type) { LLDB_LOGF(GetLog(LLDBLog::Types), "Found empty type alias %s", mangled.AsCString()); @@ -1097,6 +1138,151 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem, return {n, {}}; } +static swift::Demangle::NodePointer +GetParentNode(swift::Demangle::NodePointer node) { + if (!node || !node->hasChildren()) + return {}; + if (node->getKind() == Node::Kind::Type) + node = node->getChild(0); + if (!node || !node->hasChildren()) + return {}; + NodePointer parent_node = nullptr; + switch (node->getKind()) { + case Node::Kind::Class: + case Node::Kind::Enum: + case Node::Kind::Structure: + case Node::Kind::TypeAlias: + parent_node = node->getChild(0); + break; + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: { + NodePointer ty = swift_demangle::ChildAtPath(node, {Node::Kind::Type}); + if (!ty || ty->getNumChildren() != 1) + return {}; + + NodePointer inner = ty->getChild(0); + if (!inner || !inner->hasChildren()) + return {}; + parent_node = inner->getChild(0); + break; + } + default: + break; + } + return parent_node; +} + +CompilerType +TypeSystemSwiftTypeRef::GetParentType(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + NodePointer parent_node = GetParentNode(node); + if (!parent_node) { + LLDB_LOGF(GetLog(LLDBLog::Types), "Could not determine declcontext of %s.", + mangled_typename); + return {}; + } + if (parent_node->getKind() == Node::Kind::Module) + return {}; + NodePointer type_node = dem.createNode(Node::Kind::Type); + type_node->addChild(parent_node, dem); + return RemangleAsType(dem, type_node, flavor); +} + +std::vector> +TypeSystemSwiftTypeRef::GetSubstitutions(lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + + std::vector> all_subs; + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer type_node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!type_node || type_node->getKind() != Node::Kind::Type || + !type_node->hasChildren()) + return all_subs; + + for (NodePointer node = type_node->getChild(0); node; + node = GetParentNode(node)) { + switch (node->getKind()) { + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: { + auto &subs = all_subs.emplace_back(); + if (node->getNumChildren() == 2) { + if (NodePointer params = node->getChild(1)) + for (NodePointer t : *params) { + subs.push_back(RemangleAsType(dem, t, flavor)); + } + } + break; + } + default: + break; + } + } + std::reverse(all_subs.begin(), all_subs.end()); + return all_subs; +} + +CompilerType TypeSystemSwiftTypeRef::ApplySubstitutions( + lldb::opaque_compiler_type_t type, + std::vector> subs) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + auto flavor = SwiftLanguageRuntime::GetManglingFlavor(mangled_typename); + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + + node = Transform(dem, node, [&](NodePointer node) { + if (!node || node->getKind() != Node::Kind::DependentGenericParamType || + node->getNumChildren() != 2) + return node; + NodePointer depth_node = node->getChild(0); + NodePointer index_node = node->getChild(1); + if (!depth_node->hasIndex() || !index_node->hasIndex()) + return node; + unsigned depth = depth_node->getIndex(); + unsigned index = index_node->getIndex(); + if (depth >= subs.size()) + return node; + if (index >= subs[depth].size()) + return node; + CompilerType sub = subs[depth][index]; + return swift_demangle::GetDemangledTypeMangling(dem, + sub.GetMangledTypeName()); + }); + + NodePointer type_node = dem.createNode(Node::Kind::Type); + type_node->addChild(node, dem); + return RemangleAsType(dem, type_node, flavor); +} + +bool TypeSystemSwiftTypeRef::IsBoundGenericAliasType( + lldb::opaque_compiler_type_t type) { + using namespace swift::Demangle; + Demangler dem; + const char *mangled_typename = AsMangledName(type); + + NodePointer node = + swift_demangle::GetDemangledTypeMangling(dem, mangled_typename); + if (!node || node->getKind() != Node::Kind::Type || !node->hasChildren()) + return false; + node = node->getChild(0); + if (!node) + return false; + return node->getKind() == Node::Kind::BoundGenericTypeAlias; +} + std::optional TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type, size_t idx) { @@ -4282,8 +4468,7 @@ size_t TypeSystemSwiftTypeRef::GetIndexOfChildMemberWithName( } LLDB_LOGF(GetLog(LLDBLog::Types), - "Using SwiftASTContext::GetIndexOfChildMemberWithName fallback for " - "type %s", + "GetIndexOfChildMemberWithName failed for type %s", AsMangledName(type)); // Runtime failed, fallback to SwiftASTContext. @@ -5473,7 +5658,7 @@ TypeSystemSwiftTypeRef::GetDependentGenericParamListForType( } swift::Mangle::ManglingFlavor -TypeSystemSwiftTypeRef::GetManglingFlavor(ExecutionContext *exe_ctx) { +TypeSystemSwiftTypeRef::GetManglingFlavor(const ExecutionContext *exe_ctx) { auto sc = GetSymbolContext(exe_ctx); auto *cu = sc.comp_unit; // Cache the result for the last recently used CU. diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index 9263983f3f158..091e50dcd8f1c 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -19,6 +19,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/ThreadSafeDenseMap.h" #include "lldb/Utility/ThreadSafeStringMap.h" +#include "lldb/lldb-types.h" #include "swift/Demangling/ManglingFlavor.h" // FIXME: needed only for the DenseMap. @@ -137,6 +138,12 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { return false; } + CompilerType GetParentType(lldb::opaque_compiler_type_t type); + std::vector> + GetSubstitutions(lldb::opaque_compiler_type_t type); + CompilerType ApplySubstitutions(lldb::opaque_compiler_type_t type, + std::vector> subs); + Module *GetModule() const { return m_module; } /// Return a key for the SwiftASTContext map. If there is debug info it's the @@ -358,6 +365,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { CompilerType GetRawPointerType(); /// Determine whether \p type is a protocol. bool IsExistentialType(lldb::opaque_compiler_type_t type); + bool IsBoundGenericAliasType(lldb::opaque_compiler_type_t type); /// Recursively transform the demangle tree starting a \p node by /// doing a post-order traversal and replacing each node with @@ -416,6 +424,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { llvm::StringRef mangled_name); /// Return the base name of the topmost nominal type. static llvm::StringRef GetBaseName(swift::Demangle::NodePointer node); + static std::string GetBaseName(lldb::opaque_compiler_type_t type); /// Given a mangled name that mangles a "type metadata for Type", return a /// CompilerType with that Type. @@ -457,7 +466,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { /// Returns the mangling flavor associated with the ASTContext corresponding /// with this TypeSystem. swift::Mangle::ManglingFlavor - GetManglingFlavor(ExecutionContext *exe_ctx = nullptr); + GetManglingFlavor(const ExecutionContext *exe_ctx = nullptr); protected: /// Determine whether the fallback is enabled via setting. diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py index f241831d999e1..5eb1e3f8443b9 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py +++ b/lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py @@ -5,6 +5,7 @@ @skipIf(bugnumber = "rdar://159531308") class TestSwiftEmbeddedFrameVariable(TestBase): + @skipUnlessDarwin @swiftTest def test(self): @@ -21,17 +22,54 @@ def test_without_ast(self): def implementation(self, ast): self.runCmd("setting set symbols.swift-enable-full-dwarf-debugging true") - # FIXME: "$s1a1BVD" cannot be found. - self.runCmd("settings set symbols.swift-typesystem-compiler-fallback true") - self.runCmd("settings set symbols.swift-validate-typesystem false") target, process, thread, _ = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.swift") ) frame = thread.frames[0] self.assertTrue(frame, "Frame 0 is valid.") + if self.TraceOn(): + self.expect("log enable lldb types") self.expect("frame variable") + + alias1 = frame.FindVariable("alias1") + field = alias1.GetChildMemberWithName("t") + lldbutil.check_variable(self, field, False, value='1') + + alias2 = frame.FindVariable("alias2") + a3 = alias2.GetChildMemberWithName("a3") + lldbutil.check_variable(self, a3.GetChildAtIndex(0), False, value='3') + a4 = alias2.GetChildMemberWithName("a4") + lldbutil.check_variable(self, a4.GetChildAtIndex(0), False, value='4') + a5 = alias2.GetChildMemberWithName("a5") + a5t = a5.GetChildAtIndex(0) + lldbutil.check_variable(self, a5t.GetChildAtIndex(0), False, value='5') + lldbutil.check_variable(self, a5t.GetChildAtIndex(1), False, value='6') + + alias3 = frame.FindVariable("alias3") + r = alias3.GetChildMemberWithName("r") + a3 = r.GetChildMemberWithName("a3") + lldbutil.check_variable(self, a3.GetChildAtIndex(0), False, value='3') + a4 = r.GetChildMemberWithName("a4") + lldbutil.check_variable(self, a4.GetChildAtIndex(0), False, value='4') + a5 = r.GetChildMemberWithName("a5") + a5t = a5.GetChildAtIndex(0) + lldbutil.check_variable(self, a5t.GetChildAtIndex(0), False, value='5') + lldbutil.check_variable(self, a5t.GetChildAtIndex(1), False, value='6') + q1 = alias3.GetChildMemberWithName("q1") + lldbutil.check_variable(self, q1.GetChildAtIndex(0), False, value='11') + q2 = alias3.GetChildMemberWithName("q2") + q2t = q2.GetChildAtIndex(0) + lldbutil.check_variable(self, q2t.GetChildAtIndex(0), False, value='12') + lldbutil.check_variable(self, q2t.GetChildAtIndex(1), False, value='13') + + + array = frame.FindVariable("array") + lldbutil.check_variable(self, array, False, num_children=4) + for i in range(4): + lldbutil.check_variable(self, array.GetChildAtIndex(i), + False, value=str(i+1)) varB = frame.FindVariable("varB") field = varB.GetChildMemberWithName("a").GetChildMemberWithName("field") @@ -59,55 +97,53 @@ def implementation(self, ast): singlePayload = frame.FindVariable("singlePayload") payload = singlePayload.GetChildMemberWithName("payload") field = payload.GetChildMemberWithName("a").GetChildMemberWithName("field") - # FIXME: - if str(payload.GetError()) != 'error: Cannot compute size of type $s1a1BVD using static debug info.': - lldbutil.check_variable(self, field, False, value="4.5") - b = payload.GetChildMemberWithName("b") - lldbutil.check_variable(self, b, False, value="123456") - - emptySinglePayload = frame.FindVariable("emptySinglePayload") - lldbutil.check_variable(self, emptySinglePayload, False, value="nonPayloadTwo") - - smallMultipayloadEnum1 = frame.FindVariable("smallMultipayloadEnum1") - one = smallMultipayloadEnum1.GetChildMemberWithName("one") - if not ast: # FIXME! - lldbutil.check_variable(self, one, False, value="two") - - smallMultipayloadEnum2 = frame.FindVariable("smallMultipayloadEnum2") - two = smallMultipayloadEnum2.GetChildMemberWithName("two") - if not ast: # FIXME! - lldbutil.check_variable(self, two, False, value="one") - - bigMultipayloadEnum1 = frame.FindVariable("bigMultipayloadEnum1") - one = bigMultipayloadEnum1.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0).GetChildMemberWithName("supField") - second = one.GetChildAtIndex(1).GetChildMemberWithName("supField") - third = one.GetChildAtIndex(2).GetChildMemberWithName("supField") - lldbutil.check_variable(self, first, False, value="42") - lldbutil.check_variable(self, second, False, value="43") - lldbutil.check_variable(self, third, False, value="44") - - fullMultipayloadEnum1 = frame.FindVariable("fullMultipayloadEnum1") - one = fullMultipayloadEnum1.GetChildMemberWithName("one") - lldbutil.check_variable(self, one, False, value="120") - - fullMultipayloadEnum2 = frame.FindVariable("fullMultipayloadEnum2") - two = fullMultipayloadEnum2.GetChildMemberWithName("two") - lldbutil.check_variable(self, two, False, value="9.5") - - bigFullMultipayloadEnum1 = frame.FindVariable("bigFullMultipayloadEnum1") - one = bigFullMultipayloadEnum1.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0) - second = one.GetChildAtIndex(1) - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - - bigFullMultipayloadEnum2 = frame.FindVariable("bigFullMultipayloadEnum2") - two = bigFullMultipayloadEnum2.GetChildMemberWithName("two") - first = two.GetChildAtIndex(0) - second = two.GetChildAtIndex(1) - lldbutil.check_variable(self, first, False, value="452.5") - lldbutil.check_variable(self, second, False, value="753.5") + lldbutil.check_variable(self, field, False, value="4.5") + b = payload.GetChildMemberWithName("b") + lldbutil.check_variable(self, b, False, value="123456") + + emptySinglePayload = frame.FindVariable("emptySinglePayload") + lldbutil.check_variable(self, emptySinglePayload, False, value="nonPayloadTwo") + + smallMultipayloadEnum1 = frame.FindVariable("smallMultipayloadEnum1") + one = smallMultipayloadEnum1.GetChildMemberWithName("one") + lldbutil.check_variable(self, one, False, value="two") + + smallMultipayloadEnum2 = frame.FindVariable("smallMultipayloadEnum2") + two = smallMultipayloadEnum2.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="one") + + bigMultipayloadEnum1 = frame.FindVariable("bigMultipayloadEnum1") + one = bigMultipayloadEnum1.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0).GetChildMemberWithName("supField") + second = one.GetChildAtIndex(1).GetChildMemberWithName("supField") + third = one.GetChildAtIndex(2).GetChildMemberWithName("supField") + + if False: # FIXME! + lldbutil.check_variable(self, first, False, value="42") + lldbutil.check_variable(self, second, False, value="43") + lldbutil.check_variable(self, third, False, value="44") + + fullMultipayloadEnum1 = frame.FindVariable("fullMultipayloadEnum1") + one = fullMultipayloadEnum1.GetChildMemberWithName("one") + lldbutil.check_variable(self, one, False, value="120") + + fullMultipayloadEnum2 = frame.FindVariable("fullMultipayloadEnum2") + two = fullMultipayloadEnum2.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="9.5") + + bigFullMultipayloadEnum1 = frame.FindVariable("bigFullMultipayloadEnum1") + one = bigFullMultipayloadEnum1.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0) + second = one.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + + bigFullMultipayloadEnum2 = frame.FindVariable("bigFullMultipayloadEnum2") + two = bigFullMultipayloadEnum2.GetChildMemberWithName("two") + first = two.GetChildAtIndex(0) + second = two.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="452.5") + lldbutil.check_variable(self, second, False, value="753.5") sup = frame.FindVariable("sup") supField = sup.GetChildMemberWithName("supField") @@ -160,13 +196,11 @@ def implementation(self, ast): one = t.GetChildMemberWithName("one") first = one.GetChildAtIndex(0) second = one.GetChildAtIndex(1) - if str(one.GetError()) != 'error: Cannot compute size of type $sSi_SitD using static debug info.': - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - u = gsp3.GetChildMemberWithName("u") - two = u.GetChildMemberWithName("two") - if not ast: # FIXME! - lldbutil.check_variable(self, two, False, value="one") + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + u = gsp3.GetChildMemberWithName("u") + two = u.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value="one") gcp = frame.FindVariable("gcp") t = gcp.GetChildMemberWithName("t") @@ -176,21 +210,19 @@ def implementation(self, ast): either = frame.FindVariable("either") left = either.GetChildMemberWithName("left") - if str(left.GetError()) != 'error: Cannot compute size of type $sSiD using static debug info.': - lldbutil.check_variable(self, left, False, value="1234") - - either2 = frame.FindVariable("either2") - right = either2.GetChildMemberWithName("right") - t = right.GetChildMemberWithName("t") - one = t.GetChildMemberWithName("one") - first = one.GetChildAtIndex(0) - second = one.GetChildAtIndex(1) - if not ast: # FIXME! - lldbutil.check_variable(self, first, False, value="209") - lldbutil.check_variable(self, second, False, value="315") - u = right.GetChildMemberWithName("u") - two = u.GetChildMemberWithName("two") - lldbutil.check_variable(self, two, False, value='one') + lldbutil.check_variable(self, left, False, value="1234") + + either2 = frame.FindVariable("either2") + right = either2.GetChildMemberWithName("right") + t = right.GetChildMemberWithName("t") + one = t.GetChildMemberWithName("one") + first = one.GetChildAtIndex(0) + second = one.GetChildAtIndex(1) + lldbutil.check_variable(self, first, False, value="209") + lldbutil.check_variable(self, second, False, value="315") + u = right.GetChildMemberWithName("u") + two = u.GetChildMemberWithName("two") + lldbutil.check_variable(self, two, False, value='one') inner = frame.FindVariable("inner") value = inner.GetChildMemberWithName("value") @@ -222,8 +254,11 @@ def implementation(self, ast): innerFuncField = innerFunctionType.GetChildMemberWithName("innerFuncField") lldbutil.check_variable(self, innerFuncField, False, value='8479') - array = frame.FindVariable("array") - lldbutil.check_variable(self, array, False, num_children=4) + inlineArray = frame.FindVariable("inlineArray") + lldbutil.check_variable(self, inlineArray, False, num_children=4) for i in range(4): - lldbutil.check_variable(self, array.GetChildAtIndex(i), + lldbutil.check_variable(self, inlineArray.GetChildAtIndex(i), False, value=str(i+1)) + + string = frame.FindVariable("string") + lldbutil.check_variable(self, string, False, summary='"Hello"') diff --git a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift index c2fd8cda7bcb9..033ac534973f4 100644 --- a/lldb/test/API/lang/swift/embedded/frame_variable/main.swift +++ b/lldb/test/API/lang/swift/embedded/frame_variable/main.swift @@ -109,6 +109,29 @@ struct OuterGeneric { } } +struct TypeAliases { + struct Q { let t: T } + + struct S { + typealias A1 = Q + typealias A2 = Q + struct R { + typealias A3 = Q // Q + typealias A4 = Q // Q + typealias A5 = Q // Q + typealias A6 = Q<(R, V, T)> + let a3 : A3 + let a4 : A4 + let a5 : A5 + let a6 : A6 + } + let r : R + let q1 : A2 + let q2 : A2<(T, T)> + } + typealias A7 = Q +} + func g() { struct FunctionType { let funcField = 67 @@ -120,6 +143,18 @@ func g() { let varB = B() let tuple = (A(), B()) + let alias1 = TypeAliases.A7(t: 1) + let alias2 = TypeAliases.S.R( + a3: TypeAliases.Q(t: 3), + a4: TypeAliases.Q(t: 4), + a5: TypeAliases.Q(t: (5, 6)), + a6: TypeAliases.Q(t: (7, (8, 9), 10)) + ) + let alias3 = TypeAliases.S(r: alias2, + q1: TypeAliases.Q(t: 11), + q2: TypeAliases.Q(t: (12, 13)) + ) + let array : [Int] = [1, 2, 3, 4] let trivial = TrivialEnum.theCase let nonPayload1 = NonPayloadEnum.one let nonPayload2 = NonPayloadEnum.two @@ -158,13 +193,11 @@ func g() { let genericInner = OuterGeneric.GenericInner(t: 647, u: 674.5) let functionType = FunctionType() let innerFunctionType = InnerFunctionType() + var inlineArray: InlineArray<4, Int> = [1, 2, 3, 4] - var array: InlineArray<4, Int> = [1, 2, 3, 4] - - // Dummy statement to set breakpoint print can't be used in embedded Swift for now. - let dummy = A() // break here + let dummy = A() let string = StaticString("Hello") - print(string) + print(string) // break here } f() }