diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index 4793988963c28..49bb4a4be7b2a 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -277,6 +277,7 @@ class SwiftLanguageRuntimeStub { return {}; } + void SymbolsDidLoad(const ModuleList &module_list) {} void ModulesDidLoad(const ModuleList &module_list) {} bool IsStoredInlineInBuffer(CompilerType type) { @@ -2359,6 +2360,10 @@ SwiftLanguageRuntime::GetReflectionContext() { return m_stub->GetReflectionContext(); } +void SwiftLanguageRuntime::SymbolsDidLoad(const ModuleList &module_list) { + FORWARD(SymbolsDidLoad, module_list); +} + bool SwiftLanguageRuntime::GetDynamicTypeAndAddress( ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h index 0385d687e5e70..bb147395848b6 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h @@ -116,6 +116,7 @@ class SwiftLanguageRuntime : public LanguageRuntime { return lldb::eLanguageTypeSwift; } + void SymbolsDidLoad(const ModuleList &module_list) override; void ModulesDidLoad(const ModuleList &module_list) override; bool IsSymbolARuntimeThunk(const Symbol &symbol) override; diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index 1e70a9e5ac8e8..15797c41a315e 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -258,27 +258,44 @@ void SwiftLanguageRuntimeImpl::PopLocalBuffer() { class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { SwiftLanguageRuntimeImpl &m_runtime; - TypeSystemSwift &m_typesystem; + Status m_error; + llvm::Optional m_reader; public: LLDBTypeInfoProvider(SwiftLanguageRuntimeImpl &runtime, - TypeSystemSwift &typesystem) + ExecutionContextScope *exe_scope) : m_runtime(runtime), - // Always use the typeref type system so we have fewer cache - // invalidations. - m_typesystem(typesystem.GetTypeSystemSwiftTypeRef()) {} + m_reader(m_runtime.GetProcess().GetTarget().GetSwiftScratchContext( + m_error, + exe_scope ? *exe_scope : m_runtime.GetProcess().GetTarget())) {} + LLDBTypeInfoProvider(SwiftLanguageRuntimeImpl &runtime, + ExecutionContext *exe_ctx) + : m_runtime(runtime), + m_reader(m_runtime.GetProcess().GetTarget().GetSwiftScratchContext( + m_error, exe_ctx ? *exe_ctx->GetBestExecutionContextScope() + : m_runtime.GetProcess().GetTarget())) {} swift::remote::TypeInfoProvider::IdType getId() override { - return (void *)&m_typesystem; + if (m_reader) + return (void *)((char *)m_reader->get() + + m_reader->get()->GetGeneration() + + m_runtime.GetGeneration()); + return (void *)0; } const swift::reflection::TypeInfo * getTypeInfo(llvm::StringRef mangledName) override { // TODO: Should we cache the mangled name -> compiler type lookup, too? - Log *log(GetLog(LLDBLog::Types)); - if (log) - LLDB_LOG(log, "[LLDBTypeInfoProvider] Looking up debug type info for {0}", - mangledName); + LLDB_LOG(GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] Looking up debug type info for {0}", + mangledName); + + if (!m_reader) { + LLDB_LOG(GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] no scratch context"); + return nullptr; + } + TypeSystemSwiftTypeRef &typesystem = *m_reader->get(); // Materialize a Clang type from the debug info. assert(swift::Demangle::getManglingPrefixLength(mangledName) == 0); @@ -303,7 +320,7 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { } #endif ConstString mangled(wrapped); - CompilerType swift_type = m_typesystem.GetTypeFromMangledTypename(mangled); + CompilerType swift_type = typesystem.GetTypeFromMangledTypename(mangled); auto ts = swift_type.GetTypeSystem().dyn_cast_or_null(); if (!ts) return nullptr; @@ -311,10 +328,10 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { bool is_imported = ts->IsImportedType(swift_type.GetOpaqueQualType(), &clang_type); if (!is_imported || !clang_type) { - if (log) - LLDB_LOG(log, - "[LLDBTypeInfoProvider] Could not find clang debug type info for {0}", - mangledName); + LLDB_LOG(GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] Could not find clang debug type info " + "for {0}", + mangledName); return nullptr; } @@ -344,10 +361,9 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider { CompilerType field_type = clang_type.GetFieldAtIndex( i, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); if (is_bitfield_ptr) { - Log *log(GetLog(LLDBLog::Types)); - if (log) - log->Printf("[LLDBTypeInfoProvider] bitfield support is not yet " - "implemented"); + LLDB_LOG( + GetLog(LLDBLog::Types), + "[LLDBTypeInfoProvider] bitfield support is not yet implemented"); continue; } swift::reflection::FieldInfo field_info = { @@ -724,7 +740,7 @@ SwiftLanguageRuntimeImpl::GetNumChildren(CompilerType type, if (!reflection_ctx) return {}; - LLDBTypeInfoProvider tip(*this, *ts); + LLDBTypeInfoProvider tip(*this, exe_scope); auto *cti = reflection_ctx->GetClassInstanceTypeInfo( tr, &tip, ts->GetDescriptorFinder()); if (auto *rti = @@ -801,7 +817,7 @@ SwiftLanguageRuntimeImpl::GetNumFields(CompilerType type, if (!reflection_ctx) return {}; - LLDBTypeInfoProvider tip(*this, *ts); + LLDBTypeInfoProvider tip(*this, exe_ctx); auto *cti = reflection_ctx->GetClassInstanceTypeInfo( tr, &tip, ts->GetDescriptorFinder()); if (auto *rti = llvm::dyn_cast_or_null(cti)) { @@ -964,7 +980,7 @@ SwiftLanguageRuntimeImpl::GetIndexOfChildMemberWithName( ++idx; } - LLDBTypeInfoProvider tip(*this, *ts); + LLDBTypeInfoProvider tip(*this, exe_ctx); // `current_tr` iterates the class hierarchy, from the current class, each // superclass, and ends on null. auto *current_tr = tr; @@ -1083,7 +1099,7 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex( if (!reflection_ctx) return {}; // The indirect enum field should point to a closure context. - LLDBTypeInfoProvider tip(*this, *ts); + LLDBTypeInfoProvider tip(*this, &exe_ctx); lldb::addr_t instance = MaskMaybeBridgedPointer(m_process, pointer); auto *ti = reflection_ctx->GetTypeInfoFromInstance( instance, &tip, ts->GetDescriptorFinder()); @@ -1261,7 +1277,7 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex( return supers.size() >= 2; }; - LLDBTypeInfoProvider tip(*this, *instance_ts); + LLDBTypeInfoProvider tip(*this, &exe_ctx); // Try out the instance pointer based super class traversal first, as its // usually faster. reflection_ctx->ForEachSuperClassType(&tip, ts->GetDescriptorFinder(), @@ -1359,7 +1375,8 @@ bool SwiftLanguageRuntimeImpl::ForEachSuperClassType( if (!ts) return false; - LLDBTypeInfoProvider tip(*this, *ts); + ExecutionContext exe_ctx(instance.GetExecutionContextRef()); + LLDBTypeInfoProvider tip(*this, &exe_ctx); lldb::addr_t pointer = instance.GetPointerValue(); return reflection_ctx->ForEachSuperClassType( &tip, ts->GetTypeSystemSwiftTypeRef().GetDescriptorFinder(), @@ -2915,7 +2932,7 @@ SwiftLanguageRuntimeImpl::GetSwiftRuntimeTypeInfo( if (!reflection_ctx) return nullptr; - LLDBTypeInfoProvider provider(*this, *ts); + LLDBTypeInfoProvider provider(*this, exe_scope); return reflection_ctx->GetTypeInfo( type_ref, &provider, ts->GetTypeSystemSwiftTypeRef().GetDescriptorFinder()); diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h index 57ca6a06fdb7d..7c8b80a313304 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h @@ -64,6 +64,8 @@ class SwiftLanguageRuntimeImpl { std::unordered_map> m_enum_spec; }; + unsigned GetGeneration() const { return m_generation; } + void SymbolsDidLoad(const ModuleList &module_list) { ++m_generation; } void ModulesDidLoad(const ModuleList &module_list); bool GetObjectDescription(Stream &str, ValueObject &object); @@ -403,6 +405,8 @@ class SwiftLanguageRuntimeImpl { /// added to the reflection context once it's being initialized. ModuleList m_modules_to_add; + /// Increased every time SymbolsDidLoad is called. + unsigned m_generation = 0; /// Add the image to the reflection context. /// \return true on success. bool AddModuleToReflectionContext(const lldb::ModuleSP &module_sp); diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index 76462696545a6..dfef98b867fbe 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -542,7 +542,7 @@ IsClangImportedType(NodePointer node, case Node::Kind::Enum: case Node::Kind::TypeAlias: if (!IsClangImportedType(node->getFirstChild(), decl_context)) - return false; + return false; // When C++ interop is enabled, Swift enums represent Swift namespaces. decl_context.push_back({node->getKind() == Node::Kind::Enum @@ -1489,6 +1489,7 @@ void TypeSystemSwiftTypeRef::NotifyAllTypeSystems( void TypeSystemSwiftTypeRefForExpressions::ModulesDidLoad( ModuleList &module_list) { + ++m_generation; NotifyAllTypeSystems([&](TypeSystemSP ts_sp) { if (auto swift_ast_ctx = llvm::dyn_cast_or_null(ts_sp.get())) @@ -3163,9 +3164,9 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex( child_is_deref_of_parent = false; language_flags = 0; auto fallback = [&]() -> CompilerType { - LLDB_LOGF(GetLog(LLDBLog::Types), - "Had to engage SwiftASTContext fallback for type %s.", - AsMangledName(type)); + LLDB_LOG(GetLog(LLDBLog::Types), + "Had to engage SwiftASTContext fallback for type {0}, field #{1}.", + AsMangledName(type), idx); if (auto *swift_ast_context = GetSwiftASTContextFromExecutionContext(exe_ctx)) return swift_ast_context->GetChildCompilerTypeAtIndex( diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h index 8e582ae7189e2..7d27e6d406b00 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h @@ -534,10 +534,13 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef { /// Forwards to SwiftASTContext. PersistentExpressionState *GetPersistentExpressionState() override; Status PerformCompileUnitImports(const SymbolContext &sc); + /// Returns how often ModulesDidLoad was called/ + unsigned GetGeneration() const { return m_generation; } friend class SwiftASTContextForExpressions; protected: lldb::TargetWP m_target_wp; + unsigned m_generation = 0; /// This exists to implement the PerformCompileUnitImports /// mechanism. diff --git a/lldb/test/API/lang/swift/late_symbols/Makefile b/lldb/test/API/lang/swift/late_symbols/Makefile new file mode 100644 index 0000000000000..0a3e708e02d94 --- /dev/null +++ b/lldb/test/API/lang/swift/late_symbols/Makefile @@ -0,0 +1,6 @@ +SWIFT_SOURCES := main.swift +SWIFT_BRIDGING_HEADER := bridging.h +DISABLE_SWIFT_INTERFACE := YES +HIDE_SWIFTMODULE := YES + +include Makefile.rules diff --git a/lldb/test/API/lang/swift/late_symbols/TestSwiftLateSymbols.py b/lldb/test/API/lang/swift/late_symbols/TestSwiftLateSymbols.py new file mode 100644 index 0000000000000..70c5cda528ce0 --- /dev/null +++ b/lldb/test/API/lang/swift/late_symbols/TestSwiftLateSymbols.py @@ -0,0 +1,47 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import unittest2 +import shutil +import os + +class TestSwiftLateSymbols(TestBase): + @swiftTest + @skipUnlessDarwin + @skipIf(debug_info=no_match(["dsym"])) + def test_any_object_type(self): + """Test the AnyObject type""" + self.build() + dsym = self.getBuildArtifact('a.out.dSYM') + stash = self.getBuildArtifact('hidden.noindex') + os.unlink(self.getBuildArtifact('main.swift.o')) + os.makedirs(stash) + shutil.move(dsym, stash) + target, process, thread, bkpt = lldbutil.run_to_name_breakpoint( + self, 'breakpoint') + # return to main(), at a place where all variables are available + thread.StepOut() + + frame = thread.frames[0] + var_object = frame.FindVariable("object", lldb.eNoDynamicValues) + self.assertFalse(var_object.IsValid()) + + self.expect('add-dsym ' + stash + '/a.out.dSYM') + frame = thread.frames[0] + var_object = frame.FindVariable("object", lldb.eNoDynamicValues) + self.assertTrue(var_object.IsValid()) + + lldbutil.check_variable( + self, + var_object, + use_dynamic=False, + typename="bridging.h.FromC") + var_object_x = var_object.GetDynamicValue( + lldb.eDynamicCanRunTarget).GetChildMemberWithName("i") + lldbutil.check_variable( + self, + var_object_x, + use_dynamic=False, + value='23', + typename="Swift.Int32") diff --git a/lldb/test/API/lang/swift/late_symbols/bridging.h b/lldb/test/API/lang/swift/late_symbols/bridging.h new file mode 100644 index 0000000000000..2196d62f46598 --- /dev/null +++ b/lldb/test/API/lang/swift/late_symbols/bridging.h @@ -0,0 +1,3 @@ +struct FromC { + int i; +}; diff --git a/lldb/test/API/lang/swift/late_symbols/main.swift b/lldb/test/API/lang/swift/late_symbols/main.swift new file mode 100644 index 0000000000000..601a24bad7ae2 --- /dev/null +++ b/lldb/test/API/lang/swift/late_symbols/main.swift @@ -0,0 +1,11 @@ +func use(_ t: T) {} +func breakpoint(_ object: FromC) { + print("stop") +} + +func main() { + var object = FromC(i: 23) + breakpoint(object) +} + +main()