diff --git a/lldb/scripts/check-ast-context.py b/lldb/scripts/check-ast-context.py index 676ca66b79f2c..e6de9d3852e99 100755 --- a/lldb/scripts/check-ast-context.py +++ b/lldb/scripts/check-ast-context.py @@ -421,7 +421,8 @@ def look_for_METHOD(c): 'GetFatalErrors', 'PrintDiagnostics', 'GetASTContext', - 'SetTriple' + 'SetTriple', + 'LogConfiguration' ] for method in methods: diff --git a/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp b/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp index 01146775bef90..c7d424e830e6d 100644 --- a/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp +++ b/lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp @@ -889,8 +889,15 @@ std::vector SwiftLanguage::GetPossibleFormattersMatches( const bool check_cpp = false; const bool check_objc = false; - bool canBeSwiftDynamic = compiler_type.IsPossibleDynamicType( - nullptr, check_cpp, check_objc); + bool canBeSwiftDynamic = + compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc) || + // Foundation (but really any library) may create new + // Objective-C classes at runtime and LLDB's ObjC runtime + // implementation doesn't yet get notified about this. As a + // workaround we try to interpret ObjC id pointers as Swift + // classes to make them available. + (compiler_type.GetCanonicalType().GetTypeClass() == + eTypeClassObjCObjectPointer); if (canBeSwiftDynamic) { do { diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp index 67bdd4f1f3922..888cf30218374 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp @@ -1684,6 +1684,14 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, m_description, target ? target->GetArchitecture().GetTriple() : triple, target))); + bool suppress_config_log = false; + auto defer_log = llvm::make_scope_exit([swift_ast_sp, &suppress_config_log] { + // To avoid spamming the log with useless info, we don't log the + // configuration if everything went fine and the current module + // doesn't have any Swift contents (i.e., the shared cache dylibs). + if (!suppress_config_log) + swift_ast_sp->LogConfiguration(); + }); // This is a module AST context, mark it as such. swift_ast_sp->m_is_scratch_context = false; @@ -1696,9 +1704,7 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, bool set_triple = false; bool found_swift_modules = false; - SymbolFile *sym_file = module.GetSymbolFile(); - std::string target_triple; if (sym_file) { @@ -1821,7 +1827,10 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, std::vector module_names; swift_ast_sp->RegisterSectionModules(module, module_names); - if (module_names.size()) { + if (!module_names.size()) { + // This dylib has no Swift contents; logging the configuration is pointless. + suppress_config_log = true; + } else { swift_ast_sp->ValidateSectionModules(module, module_names); if (lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)) { std::lock_guard locker(g_log_mutex); @@ -1829,7 +1838,6 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, static_cast(&module), module.GetFileSpec().GetFilename().AsCString(""), static_cast(swift_ast_sp.get())); - swift_ast_sp->LogConfiguration(); } } @@ -1916,6 +1924,8 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, // detect if we have a iOS simulator. std::shared_ptr swift_ast_sp( new SwiftASTContextForExpressions(m_description, target)); + auto defer_log = llvm::make_scope_exit( + [swift_ast_sp] { swift_ast_sp->LogConfiguration(); }); LOG_PRINTF(LIBLLDB_LOG_TYPES, "(Target)"); @@ -2270,7 +2280,6 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language, LOG_PRINTF(LIBLLDB_LOG_TYPES, "((Target*)%p) = %p", static_cast(&target), static_cast(swift_ast_sp.get())); - swift_ast_sp->LogConfiguration(); if (swift_ast_sp->HasFatalErrors()) { logError(swift_ast_sp->GetFatalErrors().AsCString()); @@ -4795,6 +4804,12 @@ CompilerType SwiftASTContext::GetErrorType() { return {}; } +CompilerType SwiftASTContext::GetObjCObjectType() { + // FIXME: ClangImporter::Implementation stores this type, but it's not + // exposed. + return GetCompilerType(ConstString("$sSo8NSObjectCD")); +} + SwiftASTContext *SwiftASTContext::GetSwiftASTContext(swift::ASTContext *ast) { SwiftASTContext *swift_ast = GetASTMap().Lookup(ast); return swift_ast; @@ -4913,8 +4928,8 @@ void SwiftASTContext::ClearModuleDependentCaches() { } void SwiftASTContext::LogConfiguration() { - VALID_OR_RETURN_VOID(); - + // It makes no sense to call VALID_OR_RETURN here. We specifically + // want the logs in the error case! Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); if (!log) return; diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h index 8980c380d0678..eef67192774b3 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h @@ -356,6 +356,7 @@ class SwiftASTContext : public TypeSystemSwift { CreateTupleType(const std::vector &elements) override; CompilerType GetErrorType() override; + CompilerType GetObjCObjectType() override; bool HasErrors(); diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.h index 0978f0edb8f39..e81b957b8a95a 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.h @@ -116,6 +116,7 @@ class TypeSystemSwift : public TypeSystem { virtual bool IsImportedType(lldb::opaque_compiler_type_t type, CompilerType *original_type) = 0; virtual CompilerType GetErrorType() = 0; + virtual CompilerType GetObjCObjectType() = 0; virtual CompilerType GetReferentType(lldb::opaque_compiler_type_t type) = 0; static CompilerType GetInstanceType(CompilerType ct); virtual CompilerType GetInstanceType(lldb::opaque_compiler_type_t type) = 0; diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index f6d3638086722..5de46688241bd 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -2752,6 +2752,23 @@ CompilerType TypeSystemSwiftTypeRef::GetErrorType() { VALIDATE_AND_RETURN_STATIC(impl, GetErrorType); } +CompilerType TypeSystemSwiftTypeRef::GetObjCObjectType() { + auto impl = [&]() { + using namespace swift::Demangle; + Demangler dem; + auto *obj_type = dem.createNode(Node::Kind::Type); + NodePointer s = dem.createNode(Node::Kind::Structure); + NodePointer m = + dem.createNode(Node::Kind::Module, swift::MANGLING_MODULE_OBJC); + NodePointer ident = dem.createNode(Node::Kind::Identifier, "NSObject"); + s->addChild(m, dem); + s->addChild(ident, dem); + obj_type->addChild(s, dem); + return RemangleAsType(dem, obj_type); + }; + VALIDATE_AND_RETURN_STATIC(impl, GetObjCObjectType); +} + CompilerType TypeSystemSwiftTypeRef::GetReferentType(opaque_compiler_type_t type) { auto impl = [&]() -> CompilerType { diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index b578fdde4807f..4b47ef110e7f7 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -233,6 +233,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift { /// builtins (int <-> Swift.Int) as Clang types. CompilerType GetAsClangTypeOrNull(lldb::opaque_compiler_type_t type); CompilerType GetErrorType() override; + CompilerType GetObjCObjectType() override; CompilerType GetReferentType(lldb::opaque_compiler_type_t type) override; CompilerType GetInstanceType(lldb::opaque_compiler_type_t type) override; TypeAllocationStrategy diff --git a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 46f66f9837348..12cc7db44d1f3 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -886,7 +886,7 @@ llvm::Optional SwiftLanguageRuntimeImpl::GetMemberVariableOffsetRemote auto frame = instance ? instance->GetExecutionContextRef().GetFrameSP().get() : nullptr; if (auto *ti = llvm::dyn_cast_or_null( - GetTypeInfo(instance_type, frame))) { + GetSwiftRuntimeTypeInfo(instance_type, frame))) { auto fields = ti->getFields(); LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES), "using record type info"); @@ -1040,10 +1040,11 @@ SwiftLanguageRuntimeImpl::GetNumChildren(CompilerType type, auto frame = valobj ? valobj->GetExecutionContextRef().GetFrameSP().get() : nullptr; const swift::reflection::TypeRef *tr = nullptr; - auto *ti = GetTypeInfo(type, frame, &tr); + auto *ti = GetSwiftRuntimeTypeInfo(type, frame, &tr); + if (!ti) + return {}; // Structs and Tuples. - if (auto *rti = - llvm::dyn_cast_or_null(ti)) { + if (auto *rti = llvm::dyn_cast(ti)) { switch (rti->getRecordKind()) { case swift::reflection::RecordKind::ExistentialMetatype: case swift::reflection::RecordKind::ThickFunction: @@ -1060,13 +1061,11 @@ SwiftLanguageRuntimeImpl::GetNumChildren(CompilerType type, return rti->getNumFields(); } } - if (auto *eti = llvm::dyn_cast_or_null(ti)) { + if (auto *eti = llvm::dyn_cast(ti)) { return eti->getNumPayloadCases(); } // Objects. - if (auto *rti = - llvm::dyn_cast_or_null(ti)) { - + if (auto *rti = llvm::dyn_cast(ti)) { switch (rti->getReferenceKind()) { case swift::reflection::ReferenceKind::Weak: case swift::reflection::ReferenceKind::Unowned: @@ -1113,7 +1112,9 @@ SwiftLanguageRuntimeImpl::GetNumFields(CompilerType type, using namespace swift::reflection; // Try the static type metadata. const TypeRef *tr = nullptr; - auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr(), &tr); + auto *ti = GetSwiftRuntimeTypeInfo(type, exe_ctx->GetFramePtr(), &tr); + if (!ti) + return {}; // Structs and Tuples. switch (ti->getKind()) { case TypeInfoKind::Record: { @@ -1246,7 +1247,9 @@ llvm::Optional SwiftLanguageRuntimeImpl::GetEnumCaseName( CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) { using namespace swift::reflection; using namespace swift::remote; - auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr()); + auto *ti = GetSwiftRuntimeTypeInfo(type, exe_ctx->GetFramePtr()); + if (!ti) + return {}; if (ti->getKind() != TypeInfoKind::Enum) return {}; @@ -1278,7 +1281,9 @@ llvm::Optional SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName( using namespace swift::reflection; // Try the static type metadata. const TypeRef *tr = nullptr; - auto *ti = GetTypeInfo(type, exe_ctx->GetFramePtr(), &tr); + auto *ti = GetSwiftRuntimeTypeInfo(type, exe_ctx->GetFramePtr(), &tr); + if (!ti) + return {}; switch (ti->getKind()) { case TypeInfoKind::Record: { // Structs and Tuples. @@ -1391,7 +1396,9 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex( // Try the static type metadata. auto frame = valobj ? valobj->GetExecutionContextRef().GetFrameSP().get() : nullptr; - auto *ti = GetTypeInfo(type, frame); + auto *ti = GetSwiftRuntimeTypeInfo(type, frame); + if (!ti) + return {}; // Structs and Tuples. if (auto *rti = llvm::dyn_cast_or_null(ti)) { @@ -2486,7 +2493,8 @@ static bool CouldHaveDynamicValue(ValueObject &in_value) { // disable it. return !in_value.IsBaseClass(); } - return var_type.IsPossibleDynamicType(nullptr, false, false); + bool check_objc = true; + return var_type.IsPossibleDynamicType(nullptr, false, check_objc); } bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress( @@ -2497,10 +2505,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress( if (use_dynamic == lldb::eNoDynamicValues) return false; - // Try to import a Clang type into Swift. - if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC) - return GetDynamicTypeAndAddress_ClangType( - in_value, use_dynamic, class_type_or_name, address, value_type); if (!CouldHaveDynamicValue(in_value)) return false; @@ -2509,11 +2513,33 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress( // use the scratch context where such operations are legal and safe. assert(IsScratchContextLocked(in_value.GetTargetSP()) && "Swift scratch context not locked ahead of dynamic type resolution"); + CompilerType val_type(in_value.GetCompilerType()); + llvm::Optional maybe_scratch_ctx = in_value.GetScratchSwiftASTContext(); + + // Try to import a Clang type into Swift. + if (in_value.GetObjectRuntimeLanguage() == eLanguageTypeObjC) { + if (GetDynamicTypeAndAddress_ClangType( + in_value, use_dynamic, class_type_or_name, address, value_type)) + return true; + // If the type couldn't be resolved by the Clang runtime: + // Foundation, for example, generates new Objective-C classes on + // the fly (such as instances of _DictionaryStorage) and + // LLDB's ObjC runtime implementation isn't set up to recognize + // these. As a workaround, try to resolve them as Swift types. + if (val_type.GetCanonicalType().GetTypeClass() == + eTypeClassObjCObjectPointer) + if (maybe_scratch_ctx) + if (auto *scratch_ctx = maybe_scratch_ctx->get()) + val_type = scratch_ctx->GetObjCObjectType(); + } + if (!maybe_scratch_ctx) return false; SwiftASTContextForExpressions *scratch_ctx = maybe_scratch_ctx->get(); + if (!scratch_ctx) + return false; auto retry_once = [&]() { // Retry exactly once using the per-module fallback scratch context. @@ -2536,7 +2562,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress( // Import the type into the scratch context. Any form of dynamic // type resolution may trigger a cross-module import. - CompilerType val_type(in_value.GetCompilerType()); Flags type_info(val_type.GetTypeInfo()); if (!type_info.AnySet(eTypeIsSwift)) return false; @@ -2754,7 +2779,8 @@ SwiftLanguageRuntimeImpl::GetTypeRef(CompilerType type, return type_ref; } -const swift::reflection::TypeInfo *SwiftLanguageRuntimeImpl::GetTypeInfo( +const swift::reflection::TypeInfo * +SwiftLanguageRuntimeImpl::GetSwiftRuntimeTypeInfo( CompilerType type, ExecutionContextScope *exe_scope, swift::reflection::TypeRef const **out_tr) { auto *ts = llvm::dyn_cast_or_null(type.GetTypeSystem()); @@ -2796,7 +2822,7 @@ const swift::reflection::TypeInfo *SwiftLanguageRuntimeImpl::GetTypeInfo( } bool SwiftLanguageRuntimeImpl::IsStoredInlineInBuffer(CompilerType type) { - if (auto *type_info = GetTypeInfo(type, nullptr)) + if (auto *type_info = GetSwiftRuntimeTypeInfo(type, nullptr)) return type_info->isBitwiseTakable() && type_info->getSize() <= 24; return true; } @@ -2804,14 +2830,14 @@ bool SwiftLanguageRuntimeImpl::IsStoredInlineInBuffer(CompilerType type) { llvm::Optional SwiftLanguageRuntimeImpl::GetBitSize(CompilerType type, ExecutionContextScope *exe_scope) { - if (auto *type_info = GetTypeInfo(type, exe_scope)) + if (auto *type_info = GetSwiftRuntimeTypeInfo(type, exe_scope)) return type_info->getSize() * 8; return {}; } llvm::Optional SwiftLanguageRuntimeImpl::GetByteStride(CompilerType type) { - if (auto *type_info = GetTypeInfo(type, nullptr)) + if (auto *type_info = GetSwiftRuntimeTypeInfo(type, nullptr)) return type_info->getStride(); return {}; } @@ -2819,7 +2845,7 @@ SwiftLanguageRuntimeImpl::GetByteStride(CompilerType type) { llvm::Optional SwiftLanguageRuntimeImpl::GetBitAlignment(CompilerType type, ExecutionContextScope *exe_scope) { - if (auto *type_info = GetTypeInfo(type, exe_scope)) + if (auto *type_info = GetSwiftRuntimeTypeInfo(type, exe_scope)) return type_info->getAlignment() * 8; return {}; } diff --git a/lldb/source/Target/SwiftLanguageRuntimeImpl.h b/lldb/source/Target/SwiftLanguageRuntimeImpl.h index 0ec6b4a358037..139a23db90cc6 100644 --- a/lldb/source/Target/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Target/SwiftLanguageRuntimeImpl.h @@ -77,9 +77,10 @@ class SwiftLanguageRuntimeImpl { Status &error); /// Ask Remote Mirrors for the type info about a Swift type. + /// This will return a nullptr if the lookup fails. const swift::reflection::TypeInfo * - GetTypeInfo(CompilerType type, ExecutionContextScope *exe_scope, - swift::reflection::TypeRef const **out_tr = nullptr); + GetSwiftRuntimeTypeInfo(CompilerType type, ExecutionContextScope *exe_scope, + swift::reflection::TypeRef const **out_tr = nullptr); llvm::Optional lookupClangTypeInfo(CompilerType clang_type); diff --git a/lldb/test/Shell/SwiftREPL/DictBridging.test b/lldb/test/Shell/SwiftREPL/DictBridging.test index 95fccb4817b5d..7472cfa386f8f 100644 --- a/lldb/test/Shell/SwiftREPL/DictBridging.test +++ b/lldb/test/Shell/SwiftREPL/DictBridging.test @@ -68,7 +68,17 @@ let d_objc2 = NSArray(object: [1: 2] as [NSNumber: NSNumber] as NSDictionary) let d_objc3 = NSArray(object: [1: 2] as [Int: Int] as NSDictionary) // DICT-LABEL: d_objc3: NSArray = 1 element { // DICT-NEXT: [0] = 1 key/value pair { -// DICT-NEXT: [0] = (key = 1, value = 2) +// +// Allowing for both multi-line and single-line +// formatting, depending on CoreFoundation +// implementation: +// +// DICT-NOT: } +// DICT: [0] = +// DICT-NOT: } +// DICT: key = 1 +// DICT-NOT: } +// DICT: value = 2 // DICT-NEXT: } // DICT-NEXT: }