Skip to content

Commit 493d831

Browse files
Merge pull request #4077 from adrian-prantl/88974768
Avoid importing dynamic libraries and frameworks are already in the t…
2 parents 2b47160 + ab85ab8 commit 493d831

File tree

15 files changed

+242
-43
lines changed

15 files changed

+242
-43
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ class TargetProperties : public Properties {
177177

178178
bool GetSwiftReadMetadataFromDSYM() const;
179179

180+
bool GetSwiftAutoImportFrameworks() const;
181+
180182
bool GetEnableAutoImportClangModules() const;
181183

182184
bool GetUseAllCompilerFlags() const;

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,8 +1278,7 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
12781278
Status error;
12791279
SourceModule module_info;
12801280
module_info.path.emplace_back("Swift");
1281-
swift::ModuleDecl *module =
1282-
swift_ast_context.GetModule(module_info, error);
1281+
swift::ModuleDecl *module = swift_ast_context.GetModule(module_info, error);
12831282

12841283
if (error.Fail() || !module) {
12851284
LLDB_LOG(log, "couldn't load Swift Standard Library\n");

lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,7 @@ void SwiftREPL::CompleteCode(const std::string &current_code,
580580
completion_module_info.path.push_back(ConstString("repl"));
581581
swift::ModuleDecl *repl_module = nullptr;
582582
if (m_completion_module_initialized)
583-
repl_module =
584-
swift_ast->GetModule(completion_module_info, error);
583+
repl_module = swift_ast->GetModule(completion_module_info, error);
585584
if (repl_module == nullptr) {
586585
swift::ImplicitImportInfo importInfo;
587586
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/AST/SubstitutionMap.h"
3838
#include "swift/AST/Type.h"
3939
#include "swift/AST/Types.h"
40+
#include "swift/AST/ASTWalker.h"
4041
#include "swift/ASTSectionImporter/ASTSectionImporter.h"
4142
#include "swift/Basic/DiagnosticOptions.h"
4243
#include "swift/Basic/Dwarf.h"
@@ -3378,7 +3379,10 @@ void SwiftASTContext::CacheModule(swift::ModuleDecl *module) {
33783379
}
33793380

33803381
swift::ModuleDecl *SwiftASTContext::GetModule(const SourceModule &module,
3381-
Status &error) {
3382+
Status &error, bool *cached) {
3383+
if (cached)
3384+
*cached = false;
3385+
33823386
VALID_OR_RETURN(nullptr);
33833387
if (!module.path.size())
33843388
return nullptr;
@@ -3392,8 +3396,11 @@ swift::ModuleDecl *SwiftASTContext::GetModule(const SourceModule &module,
33923396
return nullptr;
33933397
}
33943398

3395-
if (swift::ModuleDecl *module_decl = GetCachedModule(module))
3399+
if (swift::ModuleDecl *module_decl = GetCachedModule(module)) {
3400+
if (cached)
3401+
*cached = true;
33963402
return module_decl;
3403+
}
33973404

33983405
LLDB_SCOPED_TIMER();
33993406
swift::ASTContext *ast = GetASTContext();
@@ -3527,27 +3534,33 @@ swift::ModuleDecl *SwiftASTContext::GetModule(const FileSpec &module_spec,
35273534
return NULL;
35283535
}
35293536

3530-
swift::ModuleDecl *
3531-
SwiftASTContext::FindAndLoadModule(const SourceModule &module, Process &process,
3532-
Status &error) {
3537+
template<typename ModuleT> swift::ModuleDecl *
3538+
SwiftASTContext::FindAndLoadModule(const ModuleT &module, Process &process,
3539+
bool import_dylib, Status &error) {
35333540
VALID_OR_RETURN(nullptr);
35343541

3535-
swift::ModuleDecl *swift_module = GetModule(module, error);
3542+
bool cached = false;
3543+
swift::ModuleDecl *swift_module = GetModule(module, error, &cached);
3544+
35363545
if (!swift_module)
35373546
return nullptr;
3538-
LoadModule(swift_module, process, error);
3539-
return swift_module;
3540-
}
35413547

3542-
swift::ModuleDecl *
3543-
SwiftASTContext::FindAndLoadModule(const FileSpec &module_spec,
3544-
Process &process, Status &error) {
3545-
VALID_OR_RETURN(nullptr);
3548+
// If import_dylib is true, this is an explicit "import Module"
3549+
// declaration in a user expression, and we should load the dylib
3550+
// even if we already cached an implicit import (which may not have
3551+
// loaded the dylib). If target.swift-auto-import-frameworks is
3552+
// set, all implicitly imported Swift modules' associated frameworks
3553+
// will be imported too.
3554+
TargetSP target_sp(GetTargetWP().lock());
3555+
if (target_sp)
3556+
import_dylib |= target_sp->GetSwiftAutoImportFrameworks();
3557+
3558+
if (cached && !import_dylib)
3559+
return swift_module;
3560+
3561+
if (import_dylib)
3562+
LoadModule(swift_module, process, error);
35463563

3547-
swift::ModuleDecl *swift_module = GetModule(module_spec, error);
3548-
if (!swift_module)
3549-
return nullptr;
3550-
LoadModule(swift_module, process, error);
35513564
return swift_module;
35523565
}
35533566

@@ -3615,6 +3628,13 @@ void SwiftASTContext::LoadModule(swift::ModuleDecl *swift_module,
36153628
// name are the same, and that we are contained in
36163629
// FileName.framework with no other intervening frameworks. We
36173630
// can get more restrictive if this gives false positives.
3631+
//
3632+
// If the framework exists on disk but it's a static framework
3633+
// (i.e., the binary inside is a static archive instead of a
3634+
// dylib) this cannot be detected. The dlopen call will fail,
3635+
// and dlerror does not contain enough information to
3636+
// unambiguously identify this case. So it will look as if the
3637+
// framework hasn't been found.
36183638
ConstString library_cstr(library_name);
36193639

36203640
std::string framework_name(library_name);
@@ -8149,6 +8169,7 @@ static void GetNameFromModule(swift::ModuleDecl *module, std::string &result) {
81498169
static swift::ModuleDecl *LoadOneModule(const SourceModule &module,
81508170
SwiftASTContext &swift_ast_context,
81518171
lldb::ProcessSP process_sp,
8172+
bool import_dylibs,
81528173
Status &error) {
81538174
LLDB_SCOPED_TIMER();
81548175
if (!module.path.size())
@@ -8167,8 +8188,8 @@ static swift::ModuleDecl *LoadOneModule(const SourceModule &module,
81678188
toplevel.GetStringRef() == imported_header_module->getName().str())
81688189
swift_module = imported_header_module;
81698190
else if (process_sp)
8170-
swift_module =
8171-
swift_ast_context.FindAndLoadModule(module, *process_sp.get(), error);
8191+
swift_module = swift_ast_context.FindAndLoadModule(
8192+
module, *process_sp.get(), import_dylibs, error);
81728193
else
81738194
swift_module = swift_ast_context.GetModule(module, error);
81748195

@@ -8243,8 +8264,8 @@ bool SwiftASTContext::GetImplicitImports(
82438264
// Otherwise, try reloading the ModuleDecl using the module name.
82448265
SourceModule module_info;
82458266
module_info.path.emplace_back(module_pair.first());
8246-
auto *module =
8247-
LoadOneModule(module_info, swift_ast_context, process_sp, error);
8267+
auto *module = LoadOneModule(module_info, swift_ast_context, process_sp,
8268+
/*import_dylibs=*/false, error);
82488269
if (!module)
82498270
return false;
82508271

@@ -8273,10 +8294,24 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82738294

82748295
size_t completion = 0;
82758296

8297+
/// Find all explicit imports in the expression.
8298+
struct UserImportFinder : public swift::ASTWalker {
8299+
llvm::SmallDenseSet<swift::ModuleDecl*, 1> imports;
8300+
8301+
bool walkToDeclPre(swift::Decl *D) override {
8302+
if (auto *ID = llvm::dyn_cast<swift::ImportDecl>(D))
8303+
if (auto *M = ID->getModule())
8304+
imports.insert(M);
8305+
return true;
8306+
}
8307+
};
8308+
UserImportFinder import_finder;
8309+
source_file.walk(import_finder);
8310+
82768311
for (const auto &attributed_import : src_file_imports) {
82778312
progress.Increment(++completion);
82788313
swift::ModuleDecl *module = attributed_import.module.importedModule;
8279-
if (module) {
8314+
if (module && import_finder.imports.count(module)) {
82808315
std::string module_name;
82818316
GetNameFromModule(module, module_name);
82828317
if (!module_name.empty()) {
@@ -8286,7 +8321,8 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82868321
LOG_PRINTF(GetLog(LLDBLog::Types | LLDBLog::Expressions),
82878322
"Performing auto import on found module: %s.\n",
82888323
module_name.c_str());
8289-
if (!LoadOneModule(module_info, swift_ast_context, process_sp, error))
8324+
if (!LoadOneModule(module_info, swift_ast_context, process_sp,
8325+
/*import_dylibs=*/true, error))
82908326
return false;
82918327

82928328
// How do we tell we are in REPL or playground mode?
@@ -8340,8 +8376,8 @@ bool SwiftASTContext::GetCompileUnitImportsImpl(
83408376
// Import the Swift standard library and its dependencies.
83418377
SourceModule swift_module;
83428378
swift_module.path.emplace_back("Swift");
8343-
auto *stdlib =
8344-
LoadOneModule(swift_module, *this, process_sp, error);
8379+
auto *stdlib = LoadOneModule(swift_module, *this, process_sp,
8380+
/*import_dylibs=*/true, error);
83458381
if (!stdlib)
83468382
return false;
83478383

@@ -8370,8 +8406,8 @@ bool SwiftASTContext::GetCompileUnitImportsImpl(
83708406
.Default(false))
83718407
continue;
83728408

8373-
auto *loaded_module =
8374-
LoadOneModule(module, *this, process_sp, error);
8409+
auto *loaded_module = LoadOneModule(module, *this, process_sp,
8410+
/*import_dylibs=*/false, error);
83758411
if (!loaded_module)
83768412
return false;
83778413

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -285,21 +285,19 @@ class SwiftASTContext : public TypeSystemSwift {
285285
// for all items in a swift::ASTContext have been setup to
286286
// allow for imports to happen correctly. Use with caution,
287287
// or use the GetModule() call that takes a FileSpec.
288-
swift::ModuleDecl *GetModule(const SourceModule &module, Status &error);
288+
swift::ModuleDecl *GetModule(const SourceModule &module, Status &error,
289+
bool *cached = nullptr);
289290

290291
swift::ModuleDecl *GetModule(const FileSpec &module_spec, Status &error);
291292

292293
void CacheModule(swift::ModuleDecl *module);
293294

294-
// Call this after the search paths are set up, it will find the module given
295-
// by module, load the module into the AST context, and also load any
296-
// "LinkLibraries" that the module requires.
297-
298-
swift::ModuleDecl *FindAndLoadModule(const SourceModule &module,
299-
Process &process, Status &error);
300-
301-
swift::ModuleDecl *FindAndLoadModule(const FileSpec &module_spec,
302-
Process &process, Status &error);
295+
/// Call this after the search paths are set up, it will find the module given
296+
/// by module, load the module into the AST context, and (if import_dylib is
297+
/// set) also load any "LinkLibraries" that the module requires.
298+
template <typename ModuleT>
299+
swift::ModuleDecl *FindAndLoadModule(const ModuleT &module, Process &process,
300+
bool import_dylib, Status &error);
303301

304302
void LoadModule(swift::ModuleDecl *swift_module, Process &process,
305303
Status &error);

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,8 +1321,9 @@ TypeSystemSwiftTypeRefForExpressions::TypeSystemSwiftTypeRefForExpressions(
13211321
void TypeSystemSwiftTypeRefForExpressions::PerformCompileUnitImports(
13221322
SymbolContext &sc) {
13231323
Status error;
1324-
// FIXME: this is uninitialized!
13251324
lldb::ProcessSP process_sp;
1325+
if (auto target_sp = sc.target_sp)
1326+
process_sp = target_sp->GetProcessSP();
13261327
if (m_swift_ast_context_initialized)
13271328
GetSwiftASTContext()->PerformCompileUnitImports(sc, process_sp, error);
13281329
else
@@ -1383,8 +1384,9 @@ TypeSystemSwiftTypeRefForExpressions::GetSwiftASTContext() const {
13831384

13841385
if (m_initial_symbol_context) {
13851386
Status error;
1386-
// FIXME: not initialized!
13871387
lldb::ProcessSP process_sp;
1388+
if (TargetSP target_sp = GetTargetWP().lock())
1389+
process_sp = target_sp->GetProcessSP();
13881390
m_swift_ast_context->PerformCompileUnitImports(*m_initial_symbol_context,
13891391
process_sp, error);
13901392
m_initial_symbol_context.reset();

lldb/source/Target/Target.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4175,6 +4175,7 @@ bool TargetProperties::GetSwiftCreateModuleContextsInParallel() const {
41754175
return true;
41764176
}
41774177

4178+
41784179
bool TargetProperties::GetSwiftReadMetadataFromFileCache() const {
41794180
const Property *exp_property = m_collection_sp->GetPropertyAtIndex(
41804181
nullptr, false, ePropertyExperimental);
@@ -4210,6 +4211,13 @@ bool TargetProperties::GetSwiftReadMetadataFromDSYM() const {
42104211

42114212
return true;
42124213
}
4214+
4215+
bool TargetProperties::GetSwiftAutoImportFrameworks() const {
4216+
const uint32_t idx = ePropertySwiftAutoImportFrameworks;
4217+
return m_collection_sp->GetPropertyAtIndexAsBoolean(
4218+
nullptr, idx, g_target_properties[idx].default_uint_value != 0);
4219+
}
4220+
42134221
ArchSpec TargetProperties::GetDefaultArchitecture() const {
42144222
OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(
42154223
nullptr, ePropertyDefaultArch);

lldb/source/Target/TargetProperties.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ let Definition = "target" in {
190190
def SwiftExtraClangFlags: Property<"swift-extra-clang-flags", "String">,
191191
DefaultStringValue<"">,
192192
Desc<"Additional -Xcc flags to be passed to the Swift ClangImporter.">;
193+
def SwiftAutoImportFrameworks : Property<"swift-auto-import-frameworks", "Boolean">,
194+
DefaultFalse,
195+
Desc<"Automatically import all frameworks and dynamic libraries that are autolinked by Swift modules in the target.">;
193196
def UseAllCompilerFlags: Property<"use-all-compiler-flags", "Boolean">,
194197
DefaultTrue,
195198
Desc<"Try to use compiler flags for all modules when setting up the Swift expression parser, not just the main executable.">;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public typealias MyNumber = Int
2+
public class C {
3+
public init() { n = MyNumber(23) }
4+
let n : MyNumber
5+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
SWIFTFLAGS_EXTRAS = -F $(BUILDDIR)
4+
5+
all: Lazy.framework $(EXE)
6+
7+
include Makefile.rules
8+
9+
Lazy.framework: $(SRCDIR)/Lazy.swift
10+
$(MAKE) -f $(MAKEFILE_RULES) \
11+
DYLIB_NAME=Lazy \
12+
DYLIB_SWIFT_SOURCES=Lazy.swift \
13+
DYLIB_MODULENAME=Lazy \
14+
FRAMEWORK=Lazy
15+
rm -f $(BUILDDIR)/Lazy.swiftmodule $(BUILDDIR)/Lazy.swiftinterface
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestSwiftLazyFramework(lldbtest.TestBase):
10+
11+
NO_DEBUG_INFO_TESTCASE = True
12+
mydir = lldbtest.TestBase.compute_mydir(__file__)
13+
14+
@swiftTest
15+
@skipIf(oslist=no_match(["macosx"]))
16+
def test_system_framework(self):
17+
"""Test that a framework that is registered as autolinked in a Swift
18+
module used in the target, but not linked against the target is
19+
automatically loaded by LLDB."""
20+
self.build()
21+
self.expect("settings set target.swift-auto-import-frameworks true")
22+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
23+
self, 'break here', lldb.SBFileSpec('main.swift'))
24+
25+
# Verify that lazy is not linked in.
26+
self.runCmd("image list")
27+
output = self.res.GetOutput()
28+
self.assertIn("dyld", output)
29+
self.assertNotIn("Lazy.framework/Versions/A/Lazy", output)
30+
# FIXME: we should automatically retry the expression on dylib import.
31+
self.expect("expression -- 1", error=True)
32+
self.expect("expression -- C()", substrs=['23'])
33+
34+
# Verify that lazy has been dynamically loaded.
35+
self.expect("image list", substrs=["Lazy.framework/Versions/A/Lazy"])
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Lazy
2+
let n = MyNumber(42)
3+
print("break here")
4+
print(n)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public struct D { public init() {} }
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
SWIFTFLAGS_EXTRAS = -I$(BUILDDIR) -F$(BUILDDIR)
4+
5+
FRAMEWORKS=$(patsubst %,a%.framework,$(shell seq -s " " 0 $(N)))
6+
7+
all: $(FRAMEWORKS) dylib $(EXE)
8+
9+
include Makefile.rules
10+
11+
lib%.a: %.swift
12+
$(MAKE) -f $(MAKEFILE_RULES) \
13+
DYLIB_NAME=static \
14+
SWIFT_SOURCES=$(patsubst lib%.a,%.swift,$@) \
15+
MODULENAME=$(patsubst lib%.a,%,$@) \
16+
SWIFTFLAGS_EXTRAS="$(patsubst %,-F%/DOES_NOT_EXIST,$(FRAMEWORKS))" \
17+
$(patsubst lib%.a,%.o,$@) \
18+
$(patsubst lib%.a,%.swiftmodule,$@)
19+
ar -r $@ $(BUILDDIR)/$(patsubst lib%.a,%.o,$@)
20+
21+
%.framework: lib%.a
22+
mkdir -p $(BUILDDIR)/$@/Headers
23+
mkdir -p $(BUILDDIR)/$@/Modules
24+
mkdir -p $(BUILDDIR)/$@/Resources
25+
mv $< $(BUILDDIR)/$@/$(patsubst lib%.a,%,$<)
26+
mkdir -p $(BUILDDIR)/$@/Modules/$(patsubst lib%.a,%.swiftmodule,$<)
27+
mv $(BUILDDIR)/$(patsubst lib%.a,%.swiftmodule,$<) $(BUILDDIR)/$@/Modules/$(patsubst lib%.a,%.swiftmodule,$<)/$(ARCH)-apple-macos.swiftmodule
28+
mv $(BUILDDIR)/$(patsubst lib%.a,%.swiftinterface,$<) $(BUILDDIR)/$@/Modules/
29+
30+
dylib: Dylib.swift
31+
$(MAKE) -f $(MAKEFILE_RULES) \
32+
DYLIB_NAME=Dylib \
33+
DYLIB_SWIFT_SOURCES=Dylib.swift \
34+
DYLIB_MODULENAME=Dylib \
35+
FRAMEWORK=Dylib
36+
rm -f $(BUILDDIR)/Dylib.swiftmodule $(BUILDDIR)/Dylib.swiftinterface

0 commit comments

Comments
 (0)