From da28c330d277edc7260d12fee1f53d71224a1f38 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 27 Sep 2024 11:11:33 -0700 Subject: [PATCH] [lldb] Support plain ObjC names in LLDBTypeInfoProvider (#9320) Extend `LLDBTypeInfoProvider` to support ObjC class names (such as "NSObject", "NSView") in addition to mangled Swift names. This is to support `ObjCClassTypeRefs`, which contain the class name, but not the mangled name. Note that `ObjCClassTypeRefs` are typerefs for classes in the ObjC (`__C`) module. Depends on https://github.com/swiftlang/swift/pull/76678 (cherry picked from commit 4a1abae5581c76dd1d0bab82269aafa185d387b1) --- ...ftLanguageRuntimeDynamicTypeResolution.cpp | 25 +++++++++++++---- .../Plugins/TypeSystem/Swift/SwiftDemangle.h | 27 +++++++++++++++++++ .../swift/typerefs/objc-descendent/Makefile | 3 +++ ...iftObjCDescendantClassWithoutASTContext.py | 17 ++++++++++++ .../swift/typerefs/objc-descendent/main.swift | 13 +++++++++ 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 lldb/test/API/lang/swift/typerefs/objc-descendent/Makefile create mode 100644 lldb/test/API/lang/swift/typerefs/objc-descendent/TestSwiftObjCDescendantClassWithoutASTContext.py create mode 100644 lldb/test/API/lang/swift/typerefs/objc-descendent/main.swift diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index b39d1b69ba1a8..d1bfe814487ce 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -317,12 +317,26 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { std::string wrapped; // The mangled name passed in is bare. Add global prefix ($s) and type (D). llvm::raw_string_ostream(wrapped) << "$s" << mangledName << 'D'; + swift::Demangle::Demangler dem; + auto *node = dem.demangleSymbol(wrapped); + if (!node) { + // Try `mangledName` as plain ObjC class name. Ex: NSObject, NSView, etc. + auto maybeMangled = swift_demangle::mangleClass( + dem, swift::MANGLING_MODULE_OBJC, mangledName); + if (!maybeMangled.isSuccess()) { + LLDB_LOG(GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] invalid mangled name: {0}", + mangledName); + return nullptr; + } + wrapped = maybeMangled.result(); + LLDB_LOG(GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] using mangled ObjC class name: {0}", + wrapped); + } else { #ifndef NDEBUG - { // Check that our hardcoded mangling wrapper is still up-to-date. - swift::Demangle::Context dem; - auto node = dem.demangleSymbolAsNode(wrapped); - assert(node && node->getKind() == swift::Demangle::Node::Kind::Global); + assert(node->getKind() == swift::Demangle::Node::Kind::Global); assert(node->getNumChildren() == 1); node = node->getChild(0); assert(node->getKind() == swift::Demangle::Node::Kind::TypeMangling); @@ -332,8 +346,9 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { assert(node->getNumChildren() == 1); node = node->getChild(0); assert(node->getKind() != swift::Demangle::Node::Kind::Type); - } #endif + } + ConstString mangled(wrapped); CompilerType swift_type = typesystem.GetTypeFromMangledTypename(mangled); auto ts = swift_type.GetTypeSystem().dyn_cast_or_null(); diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h b/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h index c83ba76b5de65..0d5a46de4d98a 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h @@ -80,6 +80,33 @@ GetDemangledType(swift::Demangle::Demangler &dem, llvm::StringRef name) { return GetType(dem.demangleSymbol(name)); } +/// Wrap node in Global/TypeMangling/Type. +static swift::Demangle::NodePointer +mangleType(swift::Demangle::Demangler &dem, + swift::Demangle::NodePointer typeNode) { + auto *global = dem.createNode(Node::Kind::Global); + auto *typeMangling = dem.createNode(Node::Kind::TypeMangling); + global->addChild(typeMangling, dem); + auto *type = dem.createNode(Node::Kind::Type); + typeMangling->addChild(type, dem); + type->addChild(typeNode, dem); + return global; +} + +/// Produce a type mangling for a class. +inline ManglingErrorOr mangleClass(swift::Demangle::Demangler &dem, + llvm::StringRef moduleName, + llvm::StringRef className) { + auto *classNode = dem.createNode(Node::Kind::Class); + auto *module = + dem.createNodeWithAllocatedText(Node::Kind::Module, moduleName); + auto *identifier = + dem.createNodeWithAllocatedText(Node::Kind::Identifier, className); + classNode->addChild(module, dem); + classNode->addChild(identifier, dem); + return mangleNode(mangleType(dem, classNode)); +} + } // namespace swift_demangle } // namespace lldb_private diff --git a/lldb/test/API/lang/swift/typerefs/objc-descendent/Makefile b/lldb/test/API/lang/swift/typerefs/objc-descendent/Makefile new file mode 100644 index 0000000000000..2a69023633b34 --- /dev/null +++ b/lldb/test/API/lang/swift/typerefs/objc-descendent/Makefile @@ -0,0 +1,3 @@ +SWIFT_SOURCES := main.swift + +include Makefile.rules diff --git a/lldb/test/API/lang/swift/typerefs/objc-descendent/TestSwiftObjCDescendantClassWithoutASTContext.py b/lldb/test/API/lang/swift/typerefs/objc-descendent/TestSwiftObjCDescendantClassWithoutASTContext.py new file mode 100644 index 0000000000000..7e941b69bff7c --- /dev/null +++ b/lldb/test/API/lang/swift/typerefs/objc-descendent/TestSwiftObjCDescendantClassWithoutASTContext.py @@ -0,0 +1,17 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestCase(TestBase): + @swiftTest + @skipUnlessFoundation + def test(self): + """Print an ObjC derived object without using the AST context.""" + self.build() + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.swift") + ) + self.runCmd("settings set symbols.swift-enable-ast-context false") + self.expect("v", substrs=["num = 15"]) diff --git a/lldb/test/API/lang/swift/typerefs/objc-descendent/main.swift b/lldb/test/API/lang/swift/typerefs/objc-descendent/main.swift new file mode 100644 index 0000000000000..048bc4424acf6 --- /dev/null +++ b/lldb/test/API/lang/swift/typerefs/objc-descendent/main.swift @@ -0,0 +1,13 @@ +import Foundation + +class C: NSObject { + var num: Int = 15 +} + +func main() { + let c = C() + // break here + print(c) +} + +main()