Skip to content

Clear the Clang type cache when new modules are loaded / Create non-null typerefs in field descriptors for Clang types #8480

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
merged 5 commits into from
Mar 26, 2024
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
13 changes: 7 additions & 6 deletions lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class TargetReflectionContext : public ReflectionContextInterface {
const swift::reflection::TypeRef *type_ref =
GetTypeRefOrNull(dem, node, descriptor_finder);
if (!type_ref)
LLDB_LOG(GetLog(LLDBLog::Types), "Could not find typeref for type: {0}",
LLDB_LOG(GetLog(LLDBLog::Types), "Could not find typeref for type {0}",
mangled_type_name);
return type_ref;
}
Expand Down Expand Up @@ -197,8 +197,9 @@ class TargetReflectionContext : public ReflectionContextInterface {
std::stringstream ss;
type_ref->dump(ss);
LLDB_LOG(log,
"[TargetReflectionContext::getTypeInfo] Getting "
"type info for typeref:\n{0}", ss.str());
"[TargetReflectionContext[{0:x}]::getTypeInfo] Getting type "
"info for typeref {1}",
provider ? provider->getId() : 0, ss.str());
}

auto type_info = m_reflection_ctx.getTypeInfo(type_ref, provider);
Expand All @@ -207,7 +208,7 @@ class TargetReflectionContext : public ReflectionContextInterface {
type_ref->dump(ss);
LLDB_LOG(log,
"[TargetReflectionContext::getTypeInfo] Could not get "
"type info for typeref:\n{0}",
"type info for typeref {0}",
ss.str());
}

Expand All @@ -216,8 +217,8 @@ class TargetReflectionContext : public ReflectionContextInterface {
type_info->dump(ss);
LLDB_LOG(log,
"[TargetReflectionContext::getTypeInfo] Found "
"type info:\n{0}",
ss.str());
"type info {0}",
ss.str());
}
return type_info;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
ExecutionContext exe_ctx;
process.CalculateExecutionContext(exe_ctx);
auto *exe_scope = exe_ctx.GetBestExecutionContextScope();
TypeSystemSwiftTypeRef &typesystem = *m_reader->get();
// Build a TypeInfo for the Clang type.
auto size = clang_type.GetByteSize(exe_scope);
auto bit_align = clang_type.GetTypeBitAlign(exe_scope);
Expand All @@ -372,11 +373,14 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
"[LLDBTypeInfoProvider] bitfield support is not yet implemented");
continue;
}
CompilerType swift_type =
typesystem.ConvertClangTypeToSwiftType(field_type);
auto *typeref = m_runtime.GetTypeRef(swift_type, &typesystem);
swift::reflection::FieldInfo field_info = {
name, (unsigned)bit_offset_ptr / 8, 0, nullptr,
name, (unsigned)bit_offset_ptr / 8, 0, typeref,
*GetOrCreateTypeInfo(field_type)};
fields.push_back(field_info);
}
}
}
return m_runtime.emplaceClangTypeInfo(clang_type, size, bit_align, fields);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ class SwiftLanguageRuntimeImpl {

bool IsABIStable();

/// Use the reflection context to build a TypeRef object.
const swift::reflection::TypeRef *
GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder);

void DumpTyperef(CompilerType type, TypeSystemSwiftTypeRef *module_holder,
Stream *s);

Expand All @@ -212,10 +216,6 @@ class SwiftLanguageRuntimeImpl {
SwiftLanguageRuntime::ForEachGenericParameter(node, callback);
}

/// Use the reflection context to build a TypeRef object.
const swift::reflection::TypeRef *
GetTypeRef(CompilerType type, TypeSystemSwiftTypeRef *module_holder);

/// If \p instance points to a Swift object, retrieve its
/// RecordTypeInfo and pass it to the callback \p fn. Repeat the
/// process with all superclasses. If \p fn returns \p true, early
Expand Down
85 changes: 62 additions & 23 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

#include <algorithm>
#include <sstream>
#include <type_traits>

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -190,7 +191,6 @@ GetMangledName(swift::Demangle::Demangler &dem,
return mangleNode(global);
}

/// Find a Clang type by name in the modules in \p module_holder.
TypeSP TypeSystemSwiftTypeRef::LookupClangType(StringRef name_ref) {
llvm::SmallVector<CompilerContext, 2> decl_context;
// Make up a decl context for non-nested types.
Expand All @@ -199,45 +199,65 @@ TypeSP TypeSystemSwiftTypeRef::LookupClangType(StringRef name_ref) {
return LookupClangType(name_ref, decl_context);
}

/// Find a Clang type by name in the modules in \p module_holder.
TypeSP TypeSystemSwiftTypeRef::LookupClangType(
StringRef name_ref, llvm::ArrayRef<CompilerContext> decl_context) {

/// Look up one Clang type in a module.
static TypeSP LookupClangType(Module &m,
llvm::ArrayRef<CompilerContext> decl_context) {
TypeQuery query(decl_context, TypeQueryOptions::e_find_one |
TypeQueryOptions::e_module_search);
query.SetLanguages(TypeSystemClang::GetSupportedLanguagesForTypes());
TypeResults results;
m.FindTypes(query, results);
return results.GetFirstType();
}

auto lookup = [&](Module &M) -> TypeSP {
TypeResults results;
M.FindTypes(query, results);
return results.GetFirstType();
};
TypeSP TypeSystemSwiftTypeRef::LookupClangType(
StringRef name_ref, llvm::ArrayRef<CompilerContext> decl_context,
ExecutionContext *exe_ctx) {
Module *m = GetModule();
if (!m)
return {};
return ::LookupClangType(const_cast<Module &>(*m), decl_context);
}

TypeSP TypeSystemSwiftTypeRefForExpressions::LookupClangType(
StringRef name_ref, llvm::ArrayRef<CompilerContext> decl_context,
ExecutionContext *exe_ctx) {
// Check the cache first. Negative results are also cached.
TypeSP result;
ConstString name(name_ref);
if (m_clang_type_cache.Lookup(name.AsCString(), result))
return result;

if (auto *M = GetModule()) {
TypeSP result = lookup(*M);
// Cache it.
m_clang_type_cache.Insert(name.AsCString(), result);
return result;
}

TargetSP target_sp = GetTargetWP().lock();
if (!target_sp)
return {};
target_sp->GetImages().ForEach([&](const ModuleSP &module) -> bool {

ModuleSP cur_module;
if (exe_ctx)
if (StackFrame *frame = exe_ctx->GetFramePtr())
cur_module =
frame->GetSymbolContext(lldb::eSymbolContextModule).module_sp;

auto lookup = [&](const ModuleSP &m) -> bool {
// Already visited this.
if (m == cur_module)
return true;

// Don't recursively call into LookupClangTypes() to avoid filling
// hundreds of image caches with negative results.
result = lookup(const_cast<Module &>(*module));
result = ::LookupClangType(const_cast<Module &>(*m), decl_context);
// Cache it in the expression context.
if (result)
m_clang_type_cache.Insert(name.AsCString(), result);
return !result;
});
};

// Visit the current module first as a performance optimization heuristic.
if (cur_module)
if (!lookup(cur_module))
return result;

target_sp->GetImages().ForEach(lookup);
return result;
}

Expand Down Expand Up @@ -331,6 +351,8 @@ TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type,
return optional;
}
}
if (clang_type.IsAnonymousType())
return nullptr;
llvm::StringRef clang_name = clang_type.GetTypeName().GetStringRef();
#define MAP_TYPE(C_TYPE_NAME, C_TYPE_KIND, C_TYPE_BITWIDTH, SWIFT_MODULE_NAME, \
SWIFT_TYPE_NAME, CAN_BE_MISSING, C_NAME_MAPPING) \
Expand Down Expand Up @@ -383,6 +405,8 @@ TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type,
auto *tuple = dem.createNode(Node::Kind::Tuple);
NodePointer element_type = GetClangTypeNode(
{clang_type.GetTypeSystem(), elem_type.getAsOpaquePtr()}, dem);
if (!element_type)
return nullptr;
for (unsigned i = 0; i < size; ++i) {
NodePointer tuple_element = dem.createNode(Node::Kind::TupleElement);
NodePointer type = dem.createNode(Node::Kind::Type);
Expand Down Expand Up @@ -414,6 +438,8 @@ TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type,
break;

NodePointer element_type_node = GetClangTypeNode(element_type, dem);
if (!element_type_node)
return nullptr;
llvm::SmallVector<NodePointer, 1> elements({element_type_node});
return CreateBoundGenericStruct("SIMD" + std::to_string(size),
swift::STDLIB_NAME, elements, dem);
Expand Down Expand Up @@ -819,8 +845,12 @@ TypeSystemSwiftTypeRef::GetCanonicalNode(swift::Demangle::Demangler &dem,
case Node::Kind::BoundGenericTypeAlias:
case Node::Kind::TypeAlias: {
auto node_clangtype = ResolveTypeAlias(dem, node);
if (CompilerType clang_type = node_clangtype.second)
return GetClangTypeNode(clang_type, dem);
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;
Expand Down Expand Up @@ -1491,6 +1521,7 @@ void TypeSystemSwiftTypeRef::NotifyAllTypeSystems(
void TypeSystemSwiftTypeRefForExpressions::ModulesDidLoad(
ModuleList &module_list) {
++m_generation;
m_clang_type_cache.Clear();
NotifyAllTypeSystems([&](TypeSystemSP ts_sp) {
if (auto swift_ast_ctx =
llvm::dyn_cast_or_null<SwiftASTContextForExpressions>(ts_sp.get()))
Expand Down Expand Up @@ -3180,8 +3211,11 @@ TypeSystemSwiftTypeRef::GetClangTypeTypeNode(swift::Demangle::Demangler &dem,
assert(clang_type.GetTypeSystem().isa_and_nonnull<TypeSystemClang>() &&
"expected a clang type");
using namespace swift::Demangle;
NodePointer node = GetClangTypeNode(clang_type, dem);
if (!node)
return nullptr;
NodePointer type = dem.createNode(Node::Kind::Type);
type->addChild(GetClangTypeNode(clang_type, dem), dem);
type->addChild(node, dem);
return type;
}

Expand Down Expand Up @@ -3358,6 +3392,8 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
swift::Demangle::Demangler dem;
swift::Demangle::NodePointer node =
GetClangTypeTypeNode(dem, clang_child_type);
if (!node)
return {};
switch (node->getChild(0)->getKind()) {
case swift::Demangle::Node::Kind::Class:
prefix = "ObjectiveC.";
Expand Down Expand Up @@ -3440,6 +3476,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
ast_child_name = suffix.str();
assert((llvm::StringRef(child_name).contains('.') ||
llvm::StringRef(ast_child_name).contains('.') ||
llvm::StringRef(ast_child_name).starts_with("_") ||
Equivalent(child_name, ast_child_name)));
assert(ast_language_flags ||
(Equivalent(std::optional<uint64_t>(child_byte_size),
Expand Down Expand Up @@ -4457,6 +4494,8 @@ TypeSystemSwiftTypeRef::GetTypedefedType(opaque_compiler_type_t type) {
} else {
NodePointer clang_node =
GetClangTypeNode(std::get<CompilerType>(pair), dem);
if (!clang_node)
return {};
type_node->addChild(clang_node, dem);
}
return RemangleAsType(dem, type_node);
Expand Down
22 changes: 16 additions & 6 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,11 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
lldb::TypeSP LookupClangType(llvm::StringRef name_ref);

/// Search the debug info for a Clang type with the specified name and decl
/// context, and cache the result.
lldb::TypeSP LookupClangType(llvm::StringRef name_ref,
llvm::ArrayRef<CompilerContext> decl_context);
/// context.
virtual lldb::TypeSP
LookupClangType(llvm::StringRef name_ref,
llvm::ArrayRef<CompilerContext> decl_context,
ExecutionContext *exe_ctx = nullptr);

/// Attempts to convert a Clang type into a Swift type.
/// For example, int is converted to Int32.
Expand All @@ -397,6 +399,7 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {

/// Lookup a type in the debug info.
lldb::TypeSP FindTypeInModule(lldb::opaque_compiler_type_t type);

protected:
/// Helper that creates an AST type from \p type.
void *ReconstructType(lldb::opaque_compiler_type_t type,
Expand Down Expand Up @@ -491,8 +494,6 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {

/// All lldb::Type pointers produced by DWARFASTParser Swift go here.
ThreadSafeDenseMap<const char *, lldb::TypeSP> m_swift_type_map;
/// Map ConstString Clang type identifiers to Clang types.
ThreadSafeDenseMap<const char *, lldb::TypeSP> m_clang_type_cache;
};

/// This one owns a SwiftASTContextForExpressions.
Expand Down Expand Up @@ -535,8 +536,15 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
/// Forwards to SwiftASTContext.
PersistentExpressionState *GetPersistentExpressionState() override;
Status PerformCompileUnitImports(const SymbolContext &sc);
/// Returns how often ModulesDidLoad was called/
/// Returns how often ModulesDidLoad was called.
unsigned GetGeneration() const { return m_generation; }
/// Performs a target-wide search.
/// \param exe_ctx is a hint for where to look first.
lldb::TypeSP
LookupClangType(llvm::StringRef name_ref,
llvm::ArrayRef<CompilerContext> decl_context,
ExecutionContext *exe_ctx) override;


friend class SwiftASTContextForExpressions;
protected:
Expand All @@ -553,6 +561,8 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
/// Perform all the implicit imports for the current frame.
mutable std::unique_ptr<SymbolContext> m_initial_symbol_context_up;
std::unique_ptr<SwiftPersistentExpressionState> m_persistent_state_up;
/// Map ConstString Clang type identifiers to Clang types.
ThreadSafeDenseMap<const char *, lldb::TypeSP> m_clang_type_cache;
};

} // namespace lldb_private
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
struct FromClang {
int x;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
struct FromClang {
int x;
};
27 changes: 27 additions & 0 deletions lldb/test/API/lang/swift/late_swift_dylib_clangdeps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# This Makefile recursively calls itself, hence the ?=.
EXE ?= a.out
SWIFT_SOURCES ?= loader.swift
SWIFT_BRIDGING_HEADER ?= ClangHeader.h
SWIFT_PRECOMPILE_BRIDGING_HEADER ?= NO
SWIFTFLAGS_EXTRAS ?= -enable-bare-slash-regex

all: dylib $(EXE)

include Makefile.rules

.PHONY: dylib
dylib:
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
VPATH=$(SRCDIR) -I $(SRCDIR) \
-f $(SRCDIR)/Makefile \
DYLIB_FILENAME=dylib.dylib \
DYLIB_SWIFT_SOURCES=dylib.swift \
DYLIB_NAME=dylib \
DYLIB_ONLY=YES \
SWIFTFLAGS_EXTRAS="-Xcc -I$(SRCDIR)" \
SWIFT_SOURCES= \
SWIFT_BRIDGING_HEADER= \
LD_EXTRAS="-lSwiftCore -Xlinker -exported_symbol -Xlinker _f" \
dylib.dylib

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil

class TestSwiftLateSwiftDylibClangDeps(TestBase):
@skipUnlessDarwin
@swiftTest
@skipIfDarwinEmbedded
def test(self):
"""Test that the reflection metadata cache is invalidated
when new DWARF debug info is available"""
self.build()
target, process, _, _ = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("loader.swift"))

# Initialize SwiftASTContext before loading the dylib.
self.runCmd("setting set symbols.swift-enable-ast-context false")
self.expect("v fromClang",
substrs=["missing debug info", "FromClang"])

bkpt = target.BreakpointCreateByLocation(
lldb.SBFileSpec('dylib.swift'), 5)
threads = lldbutil.continue_to_breakpoint(process, bkpt)

self.expect("v x", substrs=['42'])
self.expect("frame select 1")
self.expect("v fromClang", substrs=['23'])
Loading