diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp index d3377c428e30b..c33d59b113f62 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp @@ -94,6 +94,9 @@ void SwiftASTManipulatorBase::DoInitialization() { swift::FuncDecl *entrypoint_decl = nullptr; /// This is optional. swift::FuncDecl *ext_method_decl = nullptr; + /// When evaluating a generic expression this is the inner + /// function containing the user expression. + swift::FuncDecl *user_expr_decl = nullptr; /// When evaluating self as generic, this is the trampoline function that /// calls the ext_method_decl. swift::FuncDecl *trampoline_decl = nullptr; @@ -128,6 +131,8 @@ void SwiftASTManipulatorBase::DoInitialization() { entrypoint_decl = FD; else if (FD->getNameStr().equals("$__lldb_sink")) sink_decl = FD; + else if (FD->getNameStr().equals("$__lldb_user_expr")) + user_expr_decl = FD; return Action::SkipChildren(); } }; @@ -136,16 +141,17 @@ void SwiftASTManipulatorBase::DoInitialization() { m_source_file.walk(func_finder); m_extension_decl = func_finder.extension_decl; - if (m_extension_decl) { + if (func_finder.ext_method_decl) { m_function_decl = func_finder.ext_method_decl; m_entrypoint_decl = func_finder.entrypoint_decl; - m_trampoline_decl = func_finder.trampoline_decl; - m_sink_decl = func_finder.sink_decl; - } else { + } else if (func_finder.user_expr_decl) { + m_function_decl = func_finder.user_expr_decl; + m_entrypoint_decl = func_finder.entrypoint_decl; + } else m_function_decl = func_finder.entrypoint_decl; - m_entrypoint_decl = nullptr; - } - + m_entrypoint_decl = func_finder.entrypoint_decl; + m_trampoline_decl = func_finder.trampoline_decl; + m_sink_decl = func_finder.sink_decl; assert(m_function_decl); // Find the body in the function @@ -698,25 +704,24 @@ bool SwiftASTManipulator::FixupResultAfterTypeChecking(Status &error) { swift::Type result_type; for (size_t i = 0; i < num_results; i++) { swift::VarDecl *the_decl = m_result_info[i].tmp_var_decl; - if (the_decl->hasInterfaceType()) { - swift::Type its_type = the_decl->getType(); - if (result_type.isNull()) { - result_type = its_type; - } else if (!its_type.getPointer()->isEqual(result_type)) { - std::string prev_type_name = result_type.getPointer()->getString(); - std::string cur_type_name = its_type.getPointer()->getString(); - - error.SetErrorStringWithFormat( - "Type for %zuth return value is inconsistent, previous type: %s, " - "current type: %s.", - i, prev_type_name.c_str(), cur_type_name.c_str()); - return false; - } - } else { + if (!the_decl->hasInterfaceType()) { error.SetErrorStringWithFormat( "Type of %zuth return value could not be determined.", i); return false; } + swift::Type its_type = the_decl->getType(); + if (result_type.isNull()) { + result_type = its_type; + } else if (!its_type.getPointer()->isEqual(result_type)) { + std::string prev_type_name = result_type.getPointer()->getString(); + std::string cur_type_name = its_type.getPointer()->getString(); + + error.SetErrorStringWithFormat( + "Type for %zuth return value is inconsistent, previous type: %s, " + "current type: %s.", + i, prev_type_name.c_str(), cur_type_name.c_str()); + return false; + } } if (result_type.isNull()) { @@ -728,7 +733,6 @@ bool SwiftASTManipulator::FixupResultAfterTypeChecking(Status &error) { } swift::ASTContext &ast_context = m_source_file.getASTContext(); - CompilerType return_ast_type = ToCompilerType(result_type.getPointer()); swift::Identifier result_var_name = ast_context.getIdentifier(GetResultName()); @@ -864,7 +868,9 @@ swift::FuncDecl *SwiftASTManipulator::GetFunctionToInjectVariableInto( // When not binding generic type parameters, we want to inject the metadata // pointers in the wrapper, so we can pass them as opaque pointers in the // trampoline function later on. - if (m_bind_generic_types == lldb::eDontBind && variable.IsMetadataPointer()) + if (m_bind_generic_types == lldb::eDontBind && + (variable.IsMetadataPointer() || variable.IsPackCount() || + variable.IsUnboundPack())) return m_entrypoint_decl; return m_function_decl; @@ -878,6 +884,20 @@ llvm::Optional SwiftASTManipulator::GetSwiftTypeForVariable( if (!type_system_swift) return {}; + // When injecting a value pack or pack count into the outer + // lldb_expr function, treat it as an opaque raw pointer. + if (m_bind_generic_types == lldb::eDontBind && variable.IsUnboundPack()) { + auto swift_ast_ctx = type_system_swift->GetSwiftASTContext(); + if (swift_ast_ctx) { + auto it = m_type_aliases.find("$__lldb_builtin_ptr_t"); + if (it == m_type_aliases.end()) + return {}; + return swift::Type(it->second); + } + //swift_ast_ctx->GetBuiltinRawPointerType()); + return {}; + } + // This might be a referenced type, which will confuse the type checker. // The access pattern for these types is the same as for the referent // type, so it is fine to just strip it off. @@ -930,16 +950,20 @@ swift::VarDecl *SwiftASTManipulator::GetVarDeclForVariableInFunction( const swift::Identifier name = variable.GetName(); // We may need to mutate the self variable later, so hardcode it to a var // in that case. - const auto introducer = variable.IsSelf() ? swift::VarDecl::Introducer::Var - : variable.GetVarIntroducer(); + const auto introducer = (variable.IsSelf() || variable.IsUnboundPack()) + ? swift::VarDecl::Introducer::Var + : variable.GetVarIntroducer(); const swift::ASTContext &ast_context = m_source_file.getASTContext(); swift::VarDecl *redirected_var_decl = new (ast_context) swift::VarDecl( - /*is_staic*/ false, introducer, loc, name, containing_function); + /*is_static*/ false, introducer, loc, name, containing_function); redirected_var_decl->setInterfaceType(swift_type); redirected_var_decl->setDebuggerVar(true); redirected_var_decl->setImplicit(true); + redirected_var_decl->setImplInfo(swift::StorageImplInfo( + swift::ReadImplKind::Stored, swift::WriteImplKind::Stored, + swift::ReadWriteImplKind::Stored)); // This avoids having local variables filtered out by // swift::namelookup::filterForDiscriminator(). @@ -1245,6 +1269,8 @@ SwiftASTManipulator::MakeTypealias(swift::Identifier name, CompilerType &type, m_source_file.addTopLevelDecl(type_alias_decl); } + m_type_aliases.insert( + {name.str(), type_alias_decl->getStructuralType().getPointer()}); return type_alias_decl; } diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h b/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h index 921bac97f6acd..b880d0df87842 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.h @@ -109,17 +109,22 @@ class SwiftASTManipulatorBase { return m_name.str().startswith("$τ_0_"); } bool IsSelf() const { - return !m_name.str().compare("$__lldb_injected_self"); + return m_name.str().equals("$__lldb_injected_self"); } + bool IsPackCount() const { + return m_name.str().startswith("$pack_count_"); + } + bool IsUnboundPack() const { return m_is_unbound_pack; } VariableInfo() : m_type(), m_name(), m_metadata() {} VariableInfo(CompilerType &type, swift::Identifier name, VariableMetadataSP metadata, swift::VarDecl::Introducer introducer, - bool is_capture_list = false) + bool is_capture_list = false, bool is_unbound_pack = false) : m_type(type), m_name(name), m_var_introducer(introducer), - m_is_capture_list(is_capture_list), m_metadata(metadata) {} + m_is_capture_list(is_capture_list), + m_is_unbound_pack(is_unbound_pack), m_metadata(metadata) {} void Print(Stream &stream) const; @@ -134,6 +139,7 @@ class SwiftASTManipulatorBase { swift::VarDecl::Introducer m_var_introducer = swift::VarDecl::Introducer::Var; bool m_is_capture_list = false; + bool m_is_unbound_pack = false; public: VariableMetadataSP m_metadata; @@ -287,6 +293,7 @@ class SwiftASTManipulator : public SwiftASTManipulatorBase { void InsertError(swift::VarDecl *error_var, swift::Type &error_type); std::vector m_result_info; + llvm::StringMap m_type_aliases; }; } diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp index 49a0b48aed53f..95154dbca10f0 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp @@ -526,6 +526,16 @@ static void AddRequiredAliases(Block *block, lldb::StackFrameSP &stack_frame_sp, lldb::BindGenericTypes bind_generic_types) { LLDB_SCOPED_TIMER(); + // Alias builtin types, since we can't use them directly in source code. + auto builtin_ptr_t = swift_ast_context.GetBuiltinRawPointerType(); + manipulator.MakeTypealias( + swift_ast_context.GetASTContext()->getIdentifier("$__lldb_builtin_ptr_t"), + builtin_ptr_t, false); + auto builtin_int_t = swift_ast_context.GetBuiltinIntType(); + manipulator.MakeTypealias( + swift_ast_context.GetASTContext()->getIdentifier("$__lldb_builtin_int_t"), + builtin_int_t, false); + // First emit the typealias for "$__lldb_context". lldb::VariableSP self_var_sp = SwiftExpressionParser::FindSelfVariable(block); @@ -653,11 +663,6 @@ static void AddRequiredAliases(Block *block, lldb::StackFrameSP &stack_frame_sp, "archetype - could not make the $__lldb_context " "typealias."); } - // Alias the builtin type, since we can't use it directly in source code. - auto builtin_ptr_t = swift_ast_context.GetBuiltinRawPointerType(); - manipulator.MakeTypealias( - swift_ast_context.GetASTContext()->getIdentifier("$__lldb_builtin_ptr_t"), - builtin_ptr_t, false); } static void ResolveSpecialNames( @@ -1097,6 +1102,18 @@ AddArchetypesTypeAliases(std::unique_ptr &code_manipulator, auto &typeref_typesystem = swift_ast_context.GetTypeSystemSwiftTypeRef(); + // Skip this for variadic generic functions. + ConstString func_name = + stack_frame.GetSymbolContext(lldb::eSymbolContextFunction) + .GetFunctionName(Mangled::ePreferMangled); + if (auto signature = SwiftLanguageRuntime::GetGenericSignature( + func_name.GetStringRef(), typeref_typesystem)) + if (signature->pack_expansions.size()) { + LLDB_LOG(log, "[AddArchetypesTypeAliases] Variadic generic functions are " + "not supported."); + return type_aliases; + } + struct MetadataPointerInfo { unsigned int depth; unsigned int index; @@ -1121,16 +1138,11 @@ AddArchetypesTypeAliases(std::unique_ptr &code_manipulator, if (type_name.empty()) continue; - auto name = variable.GetName().str(); - if (!name.consume_front("$τ_")) - continue; - - auto pair = name.split('_'); - auto depth_str = pair.first; - auto index_str = pair.second; - unsigned int depth, index; - if (depth_str.getAsInteger(10, depth) || index_str.getAsInteger(10, index)) + auto di = ParseSwiftGenericParameter(variable.GetName().str()); + if (!di) continue; + unsigned depth = di->first; + unsigned index = di->second; auto it = visible_metadata_pointers.find(type_name); if (it != visible_metadata_pointers.end()) { @@ -1146,7 +1158,7 @@ AddArchetypesTypeAliases(std::unique_ptr &code_manipulator, } } - // Creata a typealias from name -> type for each visible metadata pointer. + // Create a typealias from name -> type for each visible metadata pointer. for (auto &pair : visible_metadata_pointers) { llvm::StringRef &type_name = pair.getFirst(); MetadataPointerInfo &info = pair.getSecond(); @@ -1333,7 +1345,7 @@ static llvm::Expected ParseAndImport( enable_bare_slash_regex_literals; invocation.getLangOptions().EnableExperimentalStringProcessing = enable_bare_slash_regex_literals; - + invocation.getLangOptions().Features.insert(swift::Feature::VariadicGenerics); auto should_use_prestable_abi = [&]() { lldb::StackFrameSP this_frame_sp(stack_frame_wp.lock()); @@ -1490,12 +1502,7 @@ RedirectCallFromSinkToTrampolineFunction(llvm::Module &module, } auto *trampoline_func_decl = manipulator.GetTrampolineDecl(); - if (!trampoline_func_decl) { - log->Printf( - "[RedirectCallFromSinkToTrampolineFunction] Could not set the call: no " - "trampoline func decl."); - return false; - } + bool have_self = trampoline_func_decl; auto *sink_decl = manipulator.GetSinkDecl(); if (!sink_decl) { @@ -1505,44 +1512,49 @@ RedirectCallFromSinkToTrampolineFunction(llvm::Module &module, return false; } - auto expr_func_name = mangler.mangleEntity(entrypoint_decl); - auto wrapped_func_name = mangler.mangleEntity(func_decl); - auto trampoline_func_name = mangler.mangleEntity(trampoline_func_decl); - auto sink_func_name = mangler.mangleEntity(sink_decl); + std::string expr_func_name = mangler.mangleEntity(entrypoint_decl); + std::string wrapped_func_name = mangler.mangleEntity(func_decl); + std::string trampoline_func_name; + if (have_self) + trampoline_func_name = mangler.mangleEntity(trampoline_func_decl); + std::string sink_func_name = mangler.mangleEntity(sink_decl); llvm::Function *lldb_expr_func = module.getFunction(expr_func_name); llvm::Function *wrapped_func = module.getFunction(wrapped_func_name); - llvm::Function *trampoline_func = module.getFunction(trampoline_func_name); + llvm::Function *trampoline_func = nullptr; + if (have_self) + trampoline_func = module.getFunction(trampoline_func_name); llvm::Function *sink_func = module.getFunction(sink_func_name); + llvm::Function *callee_func = have_self ? trampoline_func : wrapped_func; - assert(lldb_expr_func && wrapped_func && trampoline_func && sink_decl); - if (!lldb_expr_func || !wrapped_func || !trampoline_func || !sink_func) { + assert(lldb_expr_func && wrapped_func && callee_func && sink_decl); + if (!lldb_expr_func || !wrapped_func || !callee_func || !sink_func) { log->Printf( "[RedirectCallFromSinkToTrampolineFunction] Could not set the call: " "could not find one of the required functions in the IR."); return false; } - auto *trampoline_func_type = trampoline_func->getFunctionType(); - auto trampoline_num_params = trampoline_func_type->getNumParams(); + auto *callee_func_type = callee_func->getFunctionType(); + auto callee_num_params = callee_func_type->getNumParams(); // There should be at least 3 params, the raw pointer, the self type, and at // least one pointer to metadata. - if (trampoline_num_params < 3) { + if (callee_num_params < (have_self ? 3 : 2)) { log->Printf( "[RedirectCallFromSinkToTrampolineFunction] Could not set the call: " - "trampoline function has %u parameters", - trampoline_num_params); + "callee function has %u parameters", + callee_num_params); return false; } auto *sink_func_type = sink_func->getFunctionType(); auto sink_num_params = sink_func_type->getNumParams(); - if (trampoline_num_params != sink_num_params) { + if (callee_num_params != sink_num_params) { log->Printf( "[RedirectCallFromSinkToTrampolineFunction] Could not set the call: " - "trampoline function has %u parameters but sink has %u parameters.", - trampoline_num_params, sink_num_params); + "callee function has %u parameters but sink has %u parameters.", + callee_num_params, sink_num_params); return false; } @@ -1596,9 +1608,9 @@ RedirectCallFromSinkToTrampolineFunction(llvm::Module &module, // self. llvm::Value *lldb_arg_ptr = sink_call->getArgOperand(0); llvm::Value *self_load = sink_call->getArgOperand(1); - llvm::SmallVector metadata_loads; - for (size_t i = 2; i < sink_num_params; ++i) - metadata_loads.emplace_back(sink_call->getArgOperand(i)); + llvm::SmallVector generic_args; + for (size_t i = (have_self ? 2 : 1); i < sink_num_params; ++i) + generic_args.emplace_back(sink_call->getArgOperand(i)); // Delete the sink since we fished out the values we needed. sink_call->eraseFromParent(); @@ -1620,23 +1632,24 @@ RedirectCallFromSinkToTrampolineFunction(llvm::Module &module, // new call there. llvm::IRBuilder<> builder(&it); - llvm::Type *lldb_arg_type = trampoline_func_type->getParamType(1); - llvm::Type *self_type = trampoline_func_type->getParamType(2); - // Bitcast the operands to the expected types, since they were type-erased // in the call to the sink. - auto *self_ptr = builder.CreateBitCast(self_opaque_ptr, lldb_arg_type); - - llvm::SmallVector trampoline_call_params; - trampoline_call_params.push_back(lldb_arg_ptr); - trampoline_call_params.push_back(self_ptr); - for (auto &metadata_load : metadata_loads) - trampoline_call_params.push_back( - builder.CreateBitCast(metadata_load, self_type)); + llvm::SmallVector call_params; + call_params.push_back(lldb_arg_ptr); + if (have_self) { + llvm::Type *self_type = callee_func_type->getParamType(1); + auto *self_ptr = builder.CreateBitCast(self_opaque_ptr, self_type); + call_params.push_back(self_ptr); + } + for (auto &arg : generic_args) + call_params.push_back( + arg->getType()->isPointerTy() + ? builder.CreateBitCast( + arg, callee_func_type->getParamType(call_params.size())) + : arg); // Finally, create the call. - builder.CreateCall(trampoline_func_type, trampoline_func, - trampoline_call_params); + builder.CreateCall(callee_func_type, callee_func, call_params); return true; } diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.cpp index 3bfd5bb4ef7c0..10b62cb4a5b42 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.cpp @@ -17,15 +17,81 @@ #include "llvm/ADT/StringRef.h" #include "swift/Basic/LangOptions.h" +#include "swift/Demangling/Demangle.h" +#include "swift/Demangling/Demangler.h" using namespace lldb; using namespace lldb_private; +namespace lldb_private { +llvm::Optional> +ParseSwiftGenericParameter(llvm::StringRef name) { + if (!name.consume_front("$τ_")) + return {}; + + auto pair = name.split('_'); + auto depth_str = pair.first; + auto index_str = pair.second; + unsigned depth, index; + if (depth_str.getAsInteger(10, depth) || index_str.getAsInteger(10, index)) + return {}; + return {{depth, index}}; +} +} // namespace lldb_private + static const char *GetUserCodeStartMarker() { return "/*__LLDB_USER_START__*/\n"; } static const char *GetUserCodeEndMarker() { return "\n/*__LLDB_USER_END__*/"; } +/// Remove SILPacktype and print the name with substitutions applied. +static std::string TransformPackType( + CompilerType type, + llvm::SmallDenseMap, llvm::SmallString<4>> + subs) { + auto tss = type.GetTypeSystem().dyn_cast_or_null(); + if (!tss) + return ""; + auto &ts = tss->GetTypeSystemSwiftTypeRef(); + using namespace swift::Demangle; + Demangler dem; + NodePointer node = ts.GetCanonicalDemangleTree( + dem, type.GetMangledTypeName().GetStringRef()); + + node = TypeSystemSwiftTypeRef::Transform(dem, node, [](NodePointer n) { + if (n->getKind() == Node::Kind::SILPackIndirect && n->getNumChildren() == 1) { + n = n->getFirstChild(); + if (n->getKind() == Node::Kind::Type && n->getNumChildren() == 1) + return n->getFirstChild(); + } + //if (n->getKind() == Node::Kind::Pack && n->getNumChildren() == 2) { + // auto pack = dem.createNode(Node::Kind::PackExpansion); + // pack->addChild(n/*->getChild(0)*/, dem); + // //pack->addChild(n->getChild(1), dem); + // return pack; + //} + return n; + }); + + ConstString type_name = ts.RemangleAsType(dem, node).GetMangledTypeName(); + swift::Demangle::DemangleOptions options; + options = swift::Demangle::DemangleOptions::SimplifiedUIDemangleOptions(); + options.DisplayStdlibModule = false; + options.DisplayObjCModule = false; + options.QualifyEntities = true; + options.DisplayModuleNames = true; + options.DisplayLocalNameContexts = false; + options.DisplayDebuggerGeneratedModule = false; + options.GenericParameterName = [&](uint64_t depth, + uint64_t index) -> std::string { + auto it = subs.find({depth, index}); + if (it != subs.end()) + return it->second.str().str(); + return ""; + }; + return swift::Demangle::demangleSymbolAsString(type_name.GetStringRef(), + options); +} struct CallsAndArgs { std::string lldb_user_expr; @@ -64,42 +130,107 @@ struct CallsAndArgs { /// - And a matching call to the sink function: /// /// lldb_sink($__lldb_arg, $__lldb_injected_self, $τ_0_0, $τ_0_1, ..., $τ_0_n) -static CallsAndArgs MakeGenericSignaturesAndCalls( - llvm::ArrayRef local_variables) { +static llvm::Expected MakeGenericSignaturesAndCalls( + llvm::ArrayRef local_variables, + const llvm::Optional &generic_sig, + bool needs_object_ptr) { llvm::SmallVector metadata_variables; for (auto &var : local_variables) if (var.IsOutermostMetadataPointer()) metadata_variables.push_back(var); - std::string generic_param_list; - llvm::raw_string_ostream generic_param_list_stream(generic_param_list); - for (size_t i = 0; i < metadata_variables.size(); ++i) - generic_param_list_stream << "T" << i << ","; + // The number of metadata variables could be > if the function is in + // a generic context. + if (generic_sig && + (metadata_variables.size() < generic_sig->dependent_generic_param_count)) + return llvm::make_error( + llvm::inconvertibleErrorCode(), "Inconsistent generic signature"); + + llvm::SmallDenseMap, llvm::SmallString<4>> subs; + std::string generic_params; + std::string generic_params_no_packs; + llvm::raw_string_ostream s_generic_params(generic_params); + llvm::raw_string_ostream s_generic_params_no_packs(generic_params_no_packs); + for (size_t i = 0; i < metadata_variables.size(); ++i) { + llvm::SmallString<4> archetype_name; + llvm::raw_svector_ostream s_archetype_name(archetype_name); + bool is_pack = false; + unsigned depth, index; + if (generic_sig) { + auto &gp = generic_sig->generic_params[i]; + is_pack = gp.is_pack; + depth = gp.depth; + index = gp.index; + } else { + auto di = + ParseSwiftGenericParameter(metadata_variables[i].GetName().str()); + if (!di) + return llvm::make_error( + llvm::inconvertibleErrorCode(), "unexpected metadata variable"); + depth = di->first; + index = di->second; + } + if (is_pack) + s_archetype_name << "each "; + s_archetype_name << "T" << i; + if (!is_pack) + s_generic_params_no_packs << archetype_name << ","; + subs.insert({{depth, index}, archetype_name}); + s_generic_params << archetype_name << ","; + } - if (!generic_param_list.empty()) - generic_param_list.pop_back(); + if (!generic_params.empty()) + generic_params.pop_back(); + if (!generic_params_no_packs.empty()) + generic_params_no_packs.pop_back(); std::string user_expr; llvm::raw_string_ostream user_expr_stream(user_expr); - user_expr_stream << "func $__lldb_user_expr<" << generic_param_list + user_expr_stream << "func $__lldb_user_expr<" << generic_params << ">(_ $__lldb_arg: UnsafeMutablePointer<(" - << generic_param_list << ")>)"; - + << generic_params_no_packs << ")>"; + for (auto &var : local_variables) + if (var.GetType().GetTypeInfo() & lldb::eTypeIsPack) + user_expr_stream << ", _ " << var.GetName() << ": " + << TransformPackType(var.GetType(), subs); + user_expr_stream << ")"; std::string trampoline; llvm::raw_string_ostream trampoline_stream(trampoline); - trampoline_stream << "func $__lldb_trampoline<" << generic_param_list + trampoline_stream << "func $__lldb_trampoline<" << generic_params << ">(_ $__lldb_arg: UnsafeMutablePointer<(" - << generic_param_list - << ")>, _ $__lldb_injected_self: inout $__lldb_context)"; + << generic_params_no_packs << ")>"; + if (needs_object_ptr) + trampoline_stream << ", _ $__lldb_injected_self: inout $__lldb_context"; + trampoline_stream << ")"; std::string sink; std::string call; llvm::raw_string_ostream sink_stream(sink); llvm::raw_string_ostream call_stream(call); sink_stream << "func $__lldb_sink(_ $__lldb_arg : " - "UnsafeMutablePointer, _: $__lldb_builtin_ptr_t"; - call_stream << "$__lldb_sink($__lldb_arg, $__lldb_injected_self"; + "UnsafeMutablePointer"; + call_stream << "$__lldb_sink($__lldb_arg"; + if (needs_object_ptr) { + sink_stream << ", _: $__lldb_builtin_ptr_t"; + call_stream << ", $__lldb_injected_self"; + } + unsigned num_value_packs = 0; + for (auto &var : local_variables) + if (var.IsUnboundPack()) { + ++num_value_packs; + sink_stream << ", _: $__lldb_builtin_ptr_t"; + call_stream << ", " << var.GetName(); + } + // FIXME: This assumes all pack variables are local function arguments. + assert(!generic_sig || + num_value_packs == generic_sig->pack_expansions.size()); + + if (generic_sig) + for (unsigned i = 0; i < generic_sig->num_counts; ++i) { + sink_stream << ", _: $__lldb_builtin_int_t"; + call_stream << ", $pack_count_" << i; + } for (auto &var : metadata_variables) { sink_stream << ", _: $__lldb_builtin_ptr_t"; call_stream << ", " << var.GetName().str(); @@ -107,15 +238,18 @@ static CallsAndArgs MakeGenericSignaturesAndCalls( sink_stream << ")"; call_stream << ")"; - return {user_expr, trampoline, sink, call}; + CallsAndArgs retval = {user_expr, trampoline, sink, call}; + return retval; } -void WrapExpression( +static Status WrapExpression( lldb_private::Stream &wrapped_stream, const char *orig_text, bool needs_object_ptr, bool static_method, bool is_class, bool weak_self, const EvaluateExpressionOptions &options, llvm::StringRef os_version, uint32_t &first_body_line, - llvm::ArrayRef local_variables) { + llvm::ArrayRef local_variables, + const llvm::Optional &generic_sig) { + Status status; first_body_line = 0; // set to invalid // TODO make the extension private so we're not polluting the class static unsigned int counter = 0; @@ -169,7 +303,7 @@ __builtin_logger_initialize() orig_text); } first_body_line = 1; - return; + return status; } assert(!playground && "Playground mode not expected"); @@ -183,7 +317,7 @@ __builtin_logger_initialize() wrapped_stream.Printf("%s", orig_text); } first_body_line = 1; - return; + return status; } assert(!playground && !repl && "Playground/REPL mode not expected"); @@ -286,7 +420,12 @@ do { // FIXME: the current approach names the generic parameter "T", use the // user's name for the generic parameter, so they can refer to it in // their expression. - auto c = MakeGenericSignaturesAndCalls(local_variables); + auto c = MakeGenericSignaturesAndCalls(local_variables, generic_sig, + needs_object_ptr); + if (!c) { + status.SetErrorString(llvm::toString(c.takeError())); + return status; + } wrapped_stream.Printf( R"( extension %s$__lldb_context { @@ -317,10 +456,10 @@ func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer) { } )", optional_extension, availability.c_str(), func_decorator, - c.lldb_user_expr.c_str(), wrapped_expr_text.GetData(), - availability.c_str(), c.lldb_trampoline.c_str(), - availability.c_str(), c.lldb_sink.c_str(), availability.c_str(), - c.lldb_call.c_str()); + c->lldb_user_expr.c_str(), wrapped_expr_text.GetData(), + availability.c_str(), c->lldb_trampoline.c_str(), + availability.c_str(), c->lldb_sink.c_str(), availability.c_str(), + c->lldb_call.c_str()); } else { wrapped_stream.Printf(R"( @@ -345,6 +484,32 @@ func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer) { current_counter); } first_body_line = 5; + } else if (options.GetBindGenericTypes() == lldb::eDontBind) { + auto c = MakeGenericSignaturesAndCalls(local_variables, generic_sig, + needs_object_ptr); + if (!c) { + status.SetErrorString(llvm::toString(c.takeError())); + return status; + } + wrapped_stream.Printf(R"( +@LLDBDebuggerFunction %s %s { + %s +} + +@LLDBDebuggerFunction %s +%s {} + + +@LLDBDebuggerFunction %s +func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer) { + %s +} +)", + availability.c_str(), c->lldb_user_expr.c_str(), + wrapped_expr_text.GetData(), availability.c_str(), + c->lldb_sink.c_str(), availability.c_str(), + c->lldb_call.c_str()); + } else { wrapped_stream.Printf( "@LLDBDebuggerFunction %s\n" @@ -354,6 +519,7 @@ func $__lldb_expr(_ $__lldb_arg : UnsafeMutablePointer) { availability.c_str(), wrapped_expr_text.GetData()); first_body_line = 4; } + return status; } /// Format the OS name the way that Swift availability attributes do. @@ -370,12 +536,14 @@ uint32_t SwiftExpressionSourceCode::GetNumBodyLines() { return m_num_body_lines; } -bool SwiftExpressionSourceCode::GetText( +Status SwiftExpressionSourceCode::GetText( std::string &text, lldb::LanguageType wrapping_language, bool needs_object_ptr, bool static_method, bool is_class, bool weak_self, - const EvaluateExpressionOptions &options, ExecutionContext &exe_ctx, - uint32_t &first_body_line, + const EvaluateExpressionOptions &options, + const llvm::Optional &generic_sig, + ExecutionContext &exe_ctx, uint32_t &first_body_line, llvm::ArrayRef local_variables) const { + Status status; Target *target = exe_ctx.GetTargetPtr(); @@ -395,7 +563,8 @@ bool SwiftExpressionSourceCode::GetText( } if (wrapping_language != eLanguageTypeSwift) { - return false; + status.SetErrorString("language is not Swift"); + return status; } StreamString wrap_stream; @@ -429,8 +598,10 @@ bool SwiftExpressionSourceCode::GetText( llvm::cast( target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeSwift)); - if (!persistent_state) - return false; + if (!persistent_state) { + status.SetErrorString("no persistent state"); + return status; + } std::vector persistent_results; // Check if we have already declared the playground stub debug functions persistent_state->GetSwiftPersistentDecls(ConstString("__builtin_log_with_id"), {}, @@ -443,16 +614,19 @@ bool SwiftExpressionSourceCode::GetText( localOptions.SetPreparePlaygroundStubFunctions(need_to_declare_log_functions); std::string full_body = m_prefix + m_body; - WrapExpression(wrap_stream, full_body.c_str(), needs_object_ptr, - static_method, is_class, weak_self, localOptions, - os_vers.str(), first_body_line, local_variables); + status = WrapExpression(wrap_stream, full_body.c_str(), needs_object_ptr, + static_method, is_class, weak_self, localOptions, + os_vers.str(), first_body_line, local_variables, + generic_sig); + if (status.Fail()) + return status; text = wrap_stream.GetString().str(); } else { text.append(m_body); } - return true; + return status; } bool SwiftExpressionSourceCode::GetOriginalBodyBounds( diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.h index e26670b1bf973..fc7a66459d06d 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.h +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionSourceCode.h @@ -13,9 +13,14 @@ #include "lldb/Expression/Expression.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/lldb-enumerations.h" +#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h" namespace lldb_private { +/// Parse a name such as "$τ_0_0". +llvm::Optional> +ParseSwiftGenericParameter(llvm::StringRef name); + class SwiftExpressionSourceCode : public ExpressionSourceCode { public: @@ -37,11 +42,12 @@ class SwiftExpressionSourceCode : public ExpressionSourceCode { uint32_t GetNumBodyLines(); - bool GetText( + Status GetText( std::string &text, lldb::LanguageType wrapping_language, bool needs_object_ptr, bool static_method, bool is_class, bool weak_self, - const EvaluateExpressionOptions &options, ExecutionContext &exe_ctx, - uint32_t &first_body_line, + const EvaluateExpressionOptions &options, + const llvm::Optional &generic_sig, + ExecutionContext &exe_ctx, uint32_t &first_body_line, llvm::ArrayRef local_variables) const; private: diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp index 4f648d3bcfbf9..0866253f32a11 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp @@ -302,15 +302,24 @@ static bool AddVariableInfo( if (!stack_frame_sp) return true; + if (!variable_sp || !variable_sp->GetType()) + return true; + CompilerType target_type; + bool is_unbound_pack = + bind_generic_types == lldb::eDontBind && + (variable_sp->GetType()->GetForwardCompilerType().GetTypeInfo() & + lldb::eTypeIsPack); // If we're not binding the generic types, we need to set the self type as an // opaque pointer type. This is necessary because we don't bind the generic // parameters, and we can't have a type with unbound generics in a non-generic // function. - if (is_self && bind_generic_types == lldb::eDontBind) { + if (bind_generic_types == lldb::eDontBind && is_self) target_type = ast_context.GetBuiltinRawPointerType(); - } else { + else if (is_unbound_pack) + target_type = variable_sp->GetType()->GetForwardCompilerType(); + else { CompilerType var_type = SwiftExpressionParser::ResolveVariable( variable_sp, stack_frame_sp, runtime, use_dynamic, bind_generic_types); @@ -329,7 +338,7 @@ static bool AddVariableInfo( // If we couldn't fully realize the type, then we aren't going // to get very far making a local out of it, so discard it here. Log *log = GetLog(LLDBLog::Types | LLDBLog::Expressions); - if (!SwiftASTContext::IsFullyRealized(target_type)) { + if (!is_unbound_pack && !SwiftASTContext::IsFullyRealized(target_type)) { if (log) log->Printf("Discarding local %s because we couldn't fully realize it, " "our best attempt was: %s.", @@ -377,7 +386,8 @@ static bool AddVariableInfo( target_type, ast_context.GetASTContext()->getIdentifier(overridden_name), metadata_sp, variable_sp->IsConstant() ? swift::VarDecl::Introducer::Let - : swift::VarDecl::Introducer::Var); + : swift::VarDecl::Introducer::Var, + false, is_unbound_pack); local_variables.push_back(variable_info); processed_variables.insert(overridden_name); @@ -466,18 +476,22 @@ GetPersistentState(Target *target, ExecutionContext &exe_ctx) { /// - The Self type can only have one generic parameter. /// - The Self type has to be the outermost type with unbound generics. static bool CanEvaluateExpressionWithoutBindingGenericParams( - const llvm::SmallVectorImpl - &variables, + const llvm::SmallVectorImpl &variables, + const llvm::Optional &generic_sig, Block *block, StackFrame &stack_frame) { // First, find the compiler type of self with the generic parameters not // bound. auto self_var = SwiftExpressionParser::FindSelfVariable(block); - if (!self_var) + if (!self_var) { + // Freestanding variadic generic functions are also supported. + if (generic_sig) + return generic_sig->pack_expansions.size(); + return false; + } - lldb::ValueObjectSP self_valobj = - stack_frame.GetValueObjectForFrameVariable(self_var, - lldb::eNoDynamicValues); + lldb::ValueObjectSP self_valobj = stack_frame.GetValueObjectForFrameVariable( + self_var, lldb::eNoDynamicValues); if (!self_valobj) return false; @@ -578,9 +592,18 @@ SwiftUserExpression::GetTextAndSetExpressionParser( return ParseResult::retry_no_bind_generic_params; } + if (stack_frame) { + // Extract the generic signature of the context. + ConstString func_name = + stack_frame->GetSymbolContext(lldb::eSymbolContextFunction) + .GetFunctionName(Mangled::ePreferMangled); + m_generic_signature = SwiftLanguageRuntime::GetGenericSignature( + func_name.GetStringRef(), m_swift_ast_ctx->GetTypeSystemSwiftTypeRef()); + } + if (m_options.GetBindGenericTypes() == lldb::eDontBind && !CanEvaluateExpressionWithoutBindingGenericParams( - local_variables, sc.block, *stack_frame.get())) { + local_variables, m_generic_signature, sc.block, *stack_frame.get())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "Could not evaluate the expression without binding generic types."); @@ -588,12 +611,15 @@ SwiftUserExpression::GetTextAndSetExpressionParser( } uint32_t first_body_line = 0; - if (!source_code->GetText(m_transformed_text, m_options.GetLanguage(), - m_needs_object_ptr, m_in_static_method, m_is_class, - m_is_weak_self, m_options, exe_ctx, first_body_line, - local_variables)) { - diagnostic_manager.PutString(eDiagnosticSeverityError, - "couldn't construct expression body"); + Status status = source_code->GetText( + m_transformed_text, m_options.GetLanguage(), m_needs_object_ptr, + m_in_static_method, m_is_class, m_is_weak_self, m_options, + m_generic_signature, exe_ctx, first_body_line, local_variables); + if (status.Fail()) { + diagnostic_manager.PutString( + eDiagnosticSeverityError, + "couldn't construct expression body: " + + std::string(status.AsCString(""))); return ParseResult::unrecoverable_error; } diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h b/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h index 384f26d343c8d..1edf050c06e69 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h @@ -19,6 +19,7 @@ #include #include +#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h" #include "SwiftExpressionParser.h" #include "lldb/Expression/LLVMUserExpression.h" #include "lldb/Expression/Materializer.h" @@ -189,6 +190,7 @@ class SwiftUserExpression : public LLVMUserExpression { SwiftASTContextForExpressions *m_swift_ast_ctx; PersistentVariableDelegate m_persistent_variable_delegate; std::unique_ptr m_parser; + llvm::Optional m_generic_signature; Status m_err; bool m_runs_in_playground_or_repl; bool m_needs_object_ptr = false; diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index e2c0b41185093..d2910240bc0b5 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -2469,10 +2469,9 @@ SwiftLanguageRuntimeImpl::BindGenericTypeParameters(StackFrame &stack_frame, "No scratch context available."); return ts.GetTypeFromMangledTypename(mangled_name); } - CompilerType bound_type = scratch_ctx->RemangleAsType(dem, node); - LLDB_LOGF(GetLog(LLDBLog::Expressions | LLDBLog::Types), "Bound %s -> %s.", - mangled_name.GetCString(), - bound_type.GetMangledTypeName().GetCString()); + CompilerType bound_type = scratch_ctx->RemangleAsType(dem, node); + LLDB_LOG(GetLog(LLDBLog::Expressions | LLDBLog::Types), "Bound {0} -> {1}.", + mangled_name, bound_type.GetMangledTypeName()); return bound_type; } diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp index a54e6be8999c3..2cec760726388 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp @@ -7677,6 +7677,11 @@ SwiftASTContext::ConvertClangTypeToSwiftType(CompilerType clang_type) { return {this->weak_from_this(), ast_type}; } +CompilerType SwiftASTContext::GetBuiltinIntType() { + // FIXME: use target int size! + return GetTypeFromMangledTypename(ConstString("$sBi64_D")); +} + bool SwiftASTContext::TypeHasArchetype(CompilerType type) { auto swift_type = GetSwiftType(type); if (swift_type) diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h index 1094da5ba73fb..456b2fc5248cc 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h @@ -363,6 +363,7 @@ class SwiftASTContext : public TypeSystemSwift { TypeSystemClang &clang_typesystem) override; CompilerType GetBuiltinRawPointerType() override; + CompilerType GetBuiltinIntType(); /// Attempts to convert a Clang type into a Swift type. /// For example, int is converted to Int32. diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index dd20bdd4b2bb2..b61c95b08759e 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -1965,12 +1965,18 @@ TypeSystemSwiftTypeRef::RemangleAsType(swift::Demangle::Demangler &dem, return {}; using namespace swift::Demangle; - assert(node->getKind() == Node::Kind::Type && "expected type node"); - auto global = dem.createNode(Node::Kind::Global); - auto type_mangling = dem.createNode(Node::Kind::TypeMangling); - type_mangling->addChild(node, dem); - global->addChild(type_mangling, dem); - auto mangling = mangleNode(global); + if (node->getKind() != Node::Kind::Global) { + auto global = dem.createNode(Node::Kind::Global); + if (node->getKind() != Node::Kind::TypeMangling) { + auto type_mangling = dem.createNode(Node::Kind::TypeMangling); + type_mangling->addChild(node, dem); + assert(node->getKind() == Node::Kind::Type); + node = type_mangling; + } + global->addChild(node, dem); + node = global; + } + auto mangling = mangleNode(node); if (!mangling.isSuccess()) return {}; ConstString mangled_element(mangling.result()); diff --git a/lldb/test/API/lang/swift/variadic_generics/TestSwiftVariadicGenerics.py b/lldb/test/API/lang/swift/variadic_generics/TestSwiftVariadicGenerics.py index 6496ab4ed1687..99d862f21232f 100644 --- a/lldb/test/API/lang/swift/variadic_generics/TestSwiftVariadicGenerics.py +++ b/lldb/test/API/lang/swift/variadic_generics/TestSwiftVariadicGenerics.py @@ -18,6 +18,13 @@ def test(self): self.expect("frame variable", substrs=["Pack{(a.A, a.B)}", "args", "i = 23", "d = 2.71"]) + # Test that an expression can be set up in a variadic environment. + self.expect("expr --bind-generic-types=true -- 0", substrs=["0"]) + self.expect("expr --bind-generic-types=false -- 0", substrs=["0"]) + # FIXME: crashes the compiler. + #self.expect("expr --bind-generic-params=false -- (repeat each args)", + # substrs=["args"]) + # f2(us: a, vs: b) process.Continue() self.expect("frame variable",