diff --git a/lldb/include/lldb/Symbol/SwiftASTContext.h b/lldb/include/lldb/Symbol/SwiftASTContext.h index 5cd9fccc68cf4..bcdd62a59a5bd 100644 --- a/lldb/include/lldb/Symbol/SwiftASTContext.h +++ b/lldb/include/lldb/Symbol/SwiftASTContext.h @@ -39,6 +39,7 @@ enum class IRGenDebugInfoLevel : unsigned; class CanType; class DependencyTracker; class DWARFImporterDelegate; +struct ImplicitImportInfo; class IRGenOptions; class NominalTypeDecl; class SearchPathOptions; @@ -595,7 +596,13 @@ class SwiftASTContext : public TypeSystemSwift { /// \return the ExtraArgs of the ClangImporterOptions. const std::vector &GetClangArguments(); - swift::ModuleDecl *CreateModule(const SourceModule &module, Status &error); + /// Attempt to create a Swift module, returning \c nullptr and setting + /// \p error if unsuccessful. + /// + /// \param importInfo Information about which modules should be implicitly + /// imported by each file of the module. + swift::ModuleDecl *CreateModule(const SourceModule &module, Status &error, + swift::ImplicitImportInfo importInfo); // This function should only be called when all search paths // for all items in a swift::ASTContext have been setup to @@ -1064,16 +1071,30 @@ class SwiftASTContext : public TypeSystemSwift { void SetCachedType(ConstString mangled, const lldb::TypeSP &type_sp) override; - static bool PerformUserImport(SwiftASTContext &swift_ast_context, - SymbolContext &sc, - ExecutionContextScope &exe_scope, - lldb::StackFrameWP &stack_frame_wp, - swift::SourceFile &source_file, Status &error); - - static bool PerformAutoImport(SwiftASTContext &swift_ast_context, - SymbolContext &sc, - lldb::StackFrameWP &stack_frame_wp, - swift::SourceFile *source_file, Status &error); + /// Retrieves the modules that need to be implicitly imported in a given + /// execution scope. This includes the modules imported by both the compile + /// unit as well as any imports from previous expression evaluations. + static bool + GetImplicitImports(SwiftASTContext &swift_ast_context, SymbolContext &sc, + ExecutionContextScope &exe_scope, + lldb::StackFrameWP &stack_frame_wp, + llvm::SmallVectorImpl &modules, + Status &error); + + /// Cache the user's imports from a SourceFile in a given execution scope such + /// that they are carried over into future expression evaluations. + static bool CacheUserImports(SwiftASTContext &swift_ast_context, + SymbolContext &sc, + ExecutionContextScope &exe_scope, + lldb::StackFrameWP &stack_frame_wp, + swift::SourceFile &source_file, Status &error); + + /// Retrieve the modules imported by the compilation unit. + static bool + GetCompileUnitImports(SwiftASTContext &swift_ast_context, SymbolContext &sc, + lldb::StackFrameWP &stack_frame_wp, + llvm::SmallVectorImpl &modules, + Status &error); protected: /// This map uses the string value of ConstStrings as the key, and the diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp index 5c73129e54e28..0dfa2a6d8d00f 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp @@ -1197,13 +1197,28 @@ static llvm::Expected ParseAndImport( snprintf(expr_name_buf, sizeof(expr_name_buf), "__lldb_expr_%u", options.GetExpressionNumber()); + // Gather the modules that need to be implicitly imported. + // The Swift stdlib needs to be imported before the SwiftLanguageRuntime can + // be used. + Status implicit_import_error; + llvm::SmallVector additional_imports; + if (!SwiftASTContext::GetImplicitImports(*swift_ast_context, sc, exe_scope, + stack_frame_wp, additional_imports, + implicit_import_error)) { + return make_error(llvm::Twine("in implicit-import:\n") + + implicit_import_error.AsCString()); + } + + swift::ImplicitImportInfo importInfo; + importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib; + for (auto *module : additional_imports) + importInfo.AdditionalModules.emplace_back(module, /*exported*/ false); + auto module_id = ast_context->getIdentifier(expr_name_buf); - auto &module = *swift::ModuleDecl::create(module_id, *ast_context); - const auto implicit_import_kind = - swift::SourceFile::ImplicitModuleImportKind::Stdlib; + auto &module = *swift::ModuleDecl::create(module_id, *ast_context, + importInfo); swift::SourceFileKind source_file_kind = swift::SourceFileKind::Library; - if (playground || repl) { source_file_kind = swift::SourceFileKind::Main; } @@ -1211,21 +1226,11 @@ static llvm::Expected ParseAndImport( // Create the source file. Note, we disable delayed parsing for the // swift expression parser. swift::SourceFile *source_file = new (*ast_context) swift::SourceFile( - module, source_file_kind, buffer_id, implicit_import_kind, - /*Keep tokens*/ false, /*KeepSyntaxTree*/ false, + module, source_file_kind, buffer_id, /*Keep tokens*/ false, + /*KeepSyntaxTree*/ false, swift::SourceFile::ParsingFlags::DisableDelayedBodies); module.addFile(*source_file); - - // The Swift stdlib needs to be imported before the - // SwiftLanguageRuntime can be used. - Status auto_import_error; - if (!SwiftASTContext::PerformAutoImport(*swift_ast_context, sc, - stack_frame_wp, source_file, - auto_import_error)) - return make_error(llvm::Twine("in auto-import:\n") + - auto_import_error.AsCString()); - // Swift Modules that rely on shared libraries (not frameworks) // don't record the link information in the swiftmodule file, so we // can't really make them work without outside information. @@ -1276,6 +1281,13 @@ static llvm::Expected ParseAndImport( // inserting them in. swift_ast_context->AddDebuggerClient(external_lookup); + if (swift_ast_context->HasErrors()) + return make_error(); + + // Resolve the file's imports, including the implicit ones returned from + // GetImplicitImports. + swift::performImportResolution(*source_file); + if (swift_ast_context->HasErrors()) return make_error(); @@ -1327,21 +1339,16 @@ static llvm::Expected ParseAndImport( stack_frame_sp.reset(); } - swift::performImportResolution(*source_file); - - if (swift_ast_context->HasErrors()) - return make_error(); - - // Do the auto-importing after Name Binding, that's when the Imports - // for the source file are figured out. + // Cache the source file's imports such that they're accessible to future + // expression evaluations. { std::lock_guard global_context_locker( IRExecutionUnit::GetLLVMGlobalContextMutex()); Status auto_import_error; - if (!SwiftASTContext::PerformUserImport(*swift_ast_context, sc, exe_scope, - stack_frame_wp, *source_file, - auto_import_error)) { + if (!SwiftASTContext::CacheUserImports(*swift_ast_context, sc, exe_scope, + stack_frame_wp, *source_file, + auto_import_error)) { return make_error(llvm::Twine("in user-import:\n") + auto_import_error.AsCString()); } diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp index 2a1b288de9b08..69790b0e8588d 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp @@ -566,18 +566,16 @@ void SwiftREPL::CompleteCode(const std::string ¤t_code, repl_module = swift_ast->GetModule(completion_module_info, error); if (repl_module == nullptr) { - repl_module = swift_ast->CreateModule(completion_module_info, error); - const swift::SourceFile::ImplicitModuleImportKind implicit_import_kind = - swift::SourceFile::ImplicitModuleImportKind::Stdlib; + swift::ImplicitImportInfo importInfo; + importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib; + repl_module = swift_ast->CreateModule(completion_module_info, error, + importInfo); llvm::Optional bufferID; swift::SourceFile *repl_source_file = new (*ast) swift::SourceFile(*repl_module, swift::SourceFileKind::REPL, bufferID, - implicit_import_kind, /*Keep tokens*/false); - - // Given this file is empty and only exists to import the standard - // library, we can go ahead and just mark it as having been type checked. - repl_source_file->ASTStage = swift::SourceFile::TypeChecked; + /*Keep tokens*/false); repl_module->addFile(*repl_source_file); + swift::performImportResolution(*repl_source_file); m_completion_module_initialized = true; } if (repl_module) { diff --git a/lldb/source/Symbol/SwiftASTContext.cpp b/lldb/source/Symbol/SwiftASTContext.cpp index 6e5f89eef56c0..ebb7fe8285245 100644 --- a/lldb/source/Symbol/SwiftASTContext.cpp +++ b/lldb/source/Symbol/SwiftASTContext.cpp @@ -3611,8 +3611,9 @@ SwiftASTContext::GetCachedModule(const SourceModule &module) { return nullptr; } -swift::ModuleDecl *SwiftASTContext::CreateModule(const SourceModule &module, - Status &error) { +swift::ModuleDecl * +SwiftASTContext::CreateModule(const SourceModule &module, Status &error, + swift::ImplicitImportInfo importInfo) { VALID_OR_RETURN(nullptr); if (!module.path.size()) { error.SetErrorStringWithFormat("invalid module name (empty)"); @@ -3633,7 +3634,7 @@ swift::ModuleDecl *SwiftASTContext::CreateModule(const SourceModule &module, swift::Identifier module_id( ast->getIdentifier(module.path.front().GetCString())); - auto *module_decl = swift::ModuleDecl::create(module_id, *ast); + auto *module_decl = swift::ModuleDecl::create(module_id, *ast, importInfo); if (!module_decl) { error.SetErrorStringWithFormat("failed to create module for \"%s\"", module.path.front().GetCString()); @@ -8355,14 +8356,12 @@ static void GetNameFromModule(swift::ModuleDecl *module, std::string &result) { } } -static bool -LoadOneModule(const SourceModule &module, SwiftASTContext &swift_ast_context, - lldb::StackFrameWP &stack_frame_wp, - llvm::SmallVectorImpl - &additional_imports, - Status &error) { +static swift::ModuleDecl *LoadOneModule(const SourceModule &module, + SwiftASTContext &swift_ast_context, + lldb::StackFrameWP &stack_frame_wp, + Status &error) { if (!module.path.size()) - return false; + return nullptr; error.Clear(); ConstString toplevel = module.path.front(); @@ -8401,7 +8400,7 @@ LoadOneModule(const SourceModule &module, SwiftASTContext &swift_ast_context, toplevel.AsCString(), error.AsCString()); if (!swift_module || swift_ast_context.HasFatalErrors()) { - return false; + return nullptr; } } @@ -8412,23 +8411,42 @@ LoadOneModule(const SourceModule &module, SwiftASTContext &swift_ast_context, LOG_PRINTF(LIBLLDB_LOG_EXPRESSIONS, "Imported module %s from {%s}", module.path.front().AsCString(), ss.GetData()); } + return swift_module; +} + +bool SwiftASTContext::GetImplicitImports( + SwiftASTContext &swift_ast_context, SymbolContext &sc, + ExecutionContextScope &exe_scope, lldb::StackFrameWP &stack_frame_wp, + llvm::SmallVectorImpl &modules, Status &error) { + if (!GetCompileUnitImports(swift_ast_context, sc, stack_frame_wp, modules, + error)) { + return false; + } + + auto *persistent_expression_state = + sc.target_sp->GetSwiftPersistentExpressionState(exe_scope); - additional_imports.push_back(swift::SourceFile::ImportedModuleDesc( - std::make_pair(swift::ModuleDecl::AccessPathTy(), swift_module), - swift::SourceFile::ImportOptions())); + // Get the hand-loaded modules from the SwiftPersistentExpressionState. + for (ConstString name : persistent_expression_state->GetHandLoadedModules()) { + SourceModule module_info; + module_info.path.push_back(name); + auto *module = LoadOneModule(module_info, swift_ast_context, stack_frame_wp, + error); + if (!module) + return false; + + modules.push_back(module); + } return true; } -bool SwiftASTContext::PerformUserImport(SwiftASTContext &swift_ast_context, - SymbolContext &sc, - ExecutionContextScope &exe_scope, - lldb::StackFrameWP &stack_frame_wp, - swift::SourceFile &source_file, - Status &error) { +bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context, + SymbolContext &sc, + ExecutionContextScope &exe_scope, + lldb::StackFrameWP &stack_frame_wp, + swift::SourceFile &source_file, + Status &error) { llvm::SmallString<1> m_description; - llvm::SmallVector - additional_imports; - llvm::SmallVector parsed_imports; swift::ModuleDecl::ImportFilter import_filter; @@ -8452,7 +8470,7 @@ bool SwiftASTContext::PerformUserImport(SwiftASTContext &swift_ast_context, "Performing auto import on found module: %s.\n", module_name.c_str()); if (!LoadOneModule(module_info, swift_ast_context, stack_frame_wp, - additional_imports, error)) + error)) return false; // How do we tell we are in REPL or playground mode? @@ -8460,54 +8478,43 @@ bool SwiftASTContext::PerformUserImport(SwiftASTContext &swift_ast_context, } } } - // Finally get the hand-loaded modules from the - // SwiftPersistentExpressionState and load them into this context: - for (ConstString name : persistent_expression_state->GetHandLoadedModules()) { - SourceModule module_info; - module_info.path.push_back(name); - if (!LoadOneModule(module_info, swift_ast_context, stack_frame_wp, - additional_imports, error)) - return false; - } - - source_file.addImports(additional_imports); return true; } -bool SwiftASTContext::PerformAutoImport(SwiftASTContext &swift_ast_context, - SymbolContext &sc, - lldb::StackFrameWP &stack_frame_wp, - swift::SourceFile *source_file, - Status &error) { - llvm::SmallVector - additional_imports; - - // Import the Swift standard library and its dependecies. +bool SwiftASTContext::GetCompileUnitImports( + SwiftASTContext &swift_ast_context, SymbolContext &sc, + lldb::StackFrameWP &stack_frame_wp, + llvm::SmallVectorImpl &modules, Status &error) { + // Import the Swift standard library and its dependencies. SourceModule swift_module; swift_module.path.push_back(ConstString("Swift")); - if (!LoadOneModule(swift_module, swift_ast_context, stack_frame_wp, - additional_imports, error)) + auto *stdlib = + LoadOneModule(swift_module, swift_ast_context, stack_frame_wp, error); + if (!stdlib) return false; + modules.push_back(stdlib); + CompileUnit *compile_unit = sc.comp_unit; - if (compile_unit && compile_unit->GetLanguage() == lldb::eLanguageTypeSwift) - for (const SourceModule &module : compile_unit->GetImportedModules()) { - // When building the Swift stdlib with debug info these will - // show up in "Swift.o", but we already imported them and - // manually importing them will fail. - if (module.path.size() && - llvm::StringSwitch(module.path.front().GetStringRef()) - .Cases("Swift", "SwiftShims", "Builtin", true) - .Default(false)) - continue; + if (!compile_unit || compile_unit->GetLanguage() != lldb::eLanguageTypeSwift) + return true; - if (!LoadOneModule(module, swift_ast_context, stack_frame_wp, - additional_imports, error)) - return false; - } - // source_file might be NULL outside of the expression parser, where - // we don't need to notify the source file of additional imports. - if (source_file) - source_file->addImports(additional_imports); + for (const SourceModule &module : compile_unit->GetImportedModules()) { + // When building the Swift stdlib with debug info these will + // show up in "Swift.o", but we already imported them and + // manually importing them will fail. + if (module.path.size() && + llvm::StringSwitch(module.path.front().GetStringRef()) + .Cases("Swift", "SwiftShims", "Builtin", true) + .Default(false)) + continue; + + auto *loaded_module = + LoadOneModule(module, swift_ast_context, stack_frame_wp, error); + if (!loaded_module) + return false; + + modules.push_back(loaded_module); + } return true; } diff --git a/lldb/source/Target/SwiftLanguageRuntime.cpp b/lldb/source/Target/SwiftLanguageRuntime.cpp index a2f4cb4818379..d9e59f809ff37 100644 --- a/lldb/source/Target/SwiftLanguageRuntime.cpp +++ b/lldb/source/Target/SwiftLanguageRuntime.cpp @@ -1198,7 +1198,8 @@ void SwiftLanguageRuntime::RegisterGlobalError(Target &target, ConstString name, Status module_creation_error; swift::ModuleDecl *module_decl = - ast_context->CreateModule(module_info, module_creation_error); + ast_context->CreateModule(module_info, module_creation_error, + /*importInfo*/ {}); if (module_creation_error.Success() && module_decl) { const bool is_static = false; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 035f15b3a01f0..ada11357234d8 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -2499,7 +2499,9 @@ SwiftASTContextReader Target::GetScratchSwiftASTContext( !swift_ast_ctx->HasFatalErrors()) { StackFrameWP frame_wp(frame_sp); SymbolContext sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); - swift_ast_ctx->PerformAutoImport(*swift_ast_ctx, sc, frame_wp, nullptr, error); + llvm::SmallVector modules; + swift_ast_ctx->GetCompileUnitImports(*swift_ast_ctx, sc, frame_wp, modules, + error); } return SwiftASTContextReader(GetSwiftScratchContextLock(), swift_ast_ctx);