Skip to content

Commit 8837679

Browse files
committed
Parse plugin search paths from swift modules that are interactively
imported in the expression evaluator or REPL. rdar://107031048
1 parent 38484e7 commit 8837679

File tree

7 files changed

+105
-36
lines changed

7 files changed

+105
-36
lines changed

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

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,16 @@ static bool IsDWARFImported(swift::ModuleDecl &module) {
17651765
});
17661766
}
17671767

1768+
/// Detect whether this is a proper Swift module.
1769+
static bool IsSerializedAST(swift::ModuleDecl &module) {
1770+
return std::any_of(module.getFiles().begin(), module.getFiles().end(),
1771+
[](swift::FileUnit *file_unit) {
1772+
return (file_unit->getKind() ==
1773+
swift::FileUnitKind::SerializedAST);
1774+
});
1775+
}
1776+
1777+
17681778
lldb::TypeSystemSP
17691779
SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
17701780
TypeSystemSwiftTypeRef &typeref_typesystem,
@@ -1871,7 +1881,7 @@ SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
18711881
bool got_serialized_options = false;
18721882
llvm::SmallString<0> error;
18731883
llvm::raw_svector_ostream errs(error);
1874-
// Implicit search paths will be discoverd by ValidateSecionModules().
1884+
// Implicit search paths will be discovered by ValidateSecionModules().
18751885
bool discover_implicit_search_paths = false;
18761886

18771887
auto ast_file_datas = module.GetASTData(eLanguageTypeSwift);
@@ -8363,10 +8373,42 @@ bool SwiftASTContextForExpressions::CacheUserImports(
83638373
LOG_PRINTF(GetLog(LLDBLog::Types | LLDBLog::Expressions),
83648374
"Performing auto import on found module: %s.\n",
83658375
module_name.c_str());
8366-
if (!LoadOneModule(module_info, *this, process_sp,
8367-
/*import_dylibs=*/true, error))
8376+
auto *module_decl = LoadOneModule(module_info, *this, process_sp,
8377+
/*import_dylibs=*/true, error);
8378+
if (!module_decl)
83688379
return false;
8369-
8380+
if (IsSerializedAST(*module_decl)) {
8381+
// Parse additional search paths from the module.
8382+
StringRef ast_file = module_decl->getModuleLoadedFilename();
8383+
if (llvm::sys::path::is_absolute(ast_file)) {
8384+
auto file_or_err =
8385+
llvm::MemoryBuffer::getFile(ast_file, /*IsText=*/false,
8386+
/*RequiresNullTerminator=*/false);
8387+
if (!file_or_err.getError() && file_or_err->get()) {
8388+
PathMappingList path_remap;
8389+
llvm::SmallString<0> error;
8390+
bool found_swift_modules = false;
8391+
bool got_serialized_options = false;
8392+
llvm::raw_svector_ostream errs(error);
8393+
bool discover_implicit_search_paths = false;
8394+
swift::CompilerInvocation &invocation = GetCompilerInvocation();
8395+
8396+
LOG_PRINTF(GetLog(LLDBLog::Types),
8397+
"Scanning for search paths in %s",
8398+
ast_file.str().c_str());
8399+
if (DeserializeAllCompilerFlags(
8400+
invocation, ast_file, {file_or_err->get()->getBuffer()},
8401+
path_remap, discover_implicit_search_paths,
8402+
m_description.str().str(), errs, got_serialized_options,
8403+
found_swift_modules)) {
8404+
LOG_PRINTF(GetLog(LLDBLog::Types), "Could not parse %s: %s",
8405+
ast_file.str().c_str(), error.str().str().c_str());
8406+
}
8407+
if (got_serialized_options)
8408+
LogConfiguration();
8409+
}
8410+
}
8411+
}
83708412
// How do we tell we are in REPL or playground mode?
83718413
AddHandLoadedModule(module_const_str, attributed_import);
83728414
}

lldb/test/API/lang/swift/deployment_target/TestSwiftDeploymentTarget.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,6 @@ def test_swift_deployment_target_from_macho(self):
6666
self, "break here", lldb.SBFileSpec("main.swift")
6767
)
6868
self.expect("expression f", substrs=["i = 23"])
69-
70-
found_no_ast = False
71-
found_triple = False
72-
import io
73-
74-
logfile = io.open(log, "r", encoding="utf-8")
75-
for line in logfile:
76-
if (
77-
'SwiftASTContextForModule("a.out")::DeserializeAllCompilerFlags() -- Found 0 AST file data entries.'
78-
in line
79-
):
80-
found_no_ast = True
81-
if (
82-
'SwiftASTContextForModule("a.out")::SetTriple(' in line
83-
and "apple-macosx11.0" in line
84-
):
85-
found_triple = True
86-
self.assertTrue(found_no_ast)
87-
self.assertTrue(found_triple)
69+
self.filecheck('platform shell cat ""%s"' % log, __file__)
70+
# CHECK: SwiftASTContextForExpressions::SetTriple({{.*}}apple-macosx11.0.0
71+
# CHECK: SwiftASTContextForExpressions::RegisterSectionModules("a.out") retrieved 0 AST Data blobs
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@freestanding(expression) public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroImpl", type: "StringifyMacro")

lldb/test/API/lang/swift/macro/Makefile

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1-
SWIFT_SOURCES := main.swift
2-
SWIFTFLAGS_EXTRAS = -enable-experimental-feature Macros \
3-
-load-plugin-library $(BUILDDIR)/libMacroImpl.dylib
1+
SWIFTFLAGS_EXTRAS = -I.
42

5-
all: libMacroImpl.dylib $(EXE)
3+
ifneq "$(SWIFT_SOURCES)" "empty.swift"
4+
5+
SWIFTFLAGS_EXTRAS += -load-plugin-library $(BUILDDIR)/libMacroImpl.dylib
6+
LD_EXTRAS = -L$(BUILDDIR) -lMacro
7+
8+
endif
9+
10+
all: libMacro.dylib libMacroImpl.dylib $(EXE)
611

712
include Makefile.rules
813

14+
libMacro.dylib:
15+
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
16+
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
17+
VPATH=$(SRCDIR) -I $(SRCDIR) \
18+
-f $(THIS_FILE_DIR)/Makefile.rules \
19+
DYLIB_SWIFT_SOURCES=Macro.swift \
20+
DYLIB_NAME=Macro \
21+
DYLIB_ONLY=YES \
22+
SWIFT_SOURCES= \
23+
SWIFTFLAGS_EXTRAS="-load-plugin-library $(BUILDDIR)/libMacroImpl.dylib" \
24+
all
25+
$(RM) $(BUILDDIR)/Macro.swiftinterface
26+
927
libMacroImpl.dylib:
1028
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
1129
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \

lldb/test/API/lang/swift/macro/TestSwiftMacro.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@
88
class TestSwiftMacro(lldbtest.TestBase):
99

1010
NO_DEBUG_INFO_TESTCASE = True
11-
12-
@swiftTest
13-
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
14-
@expectedFailureAll(oslist=["linux"])
15-
def test(self):
16-
"""Test Swift macros"""
17-
self.build()
18-
11+
def setupPluginServerForTesting(self):
1912
# Find the path to the just-built swift-plugin-server.
2013
# FIXME: this is not very robust.
2114
def replace_last(old, new, string):
@@ -33,6 +26,15 @@ def replace_last(old, new, string):
3326
'settings set target.experimental.swift-plugin-server-for-path %s=%s'
3427
% (self.getBuildDir(), swift_plugin_server))
3528

29+
30+
@swiftTest
31+
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
32+
@expectedFailureAll(oslist=["linux"])
33+
def testDebugging(self):
34+
"""Test Swift macros"""
35+
self.build(dictionary={'SWIFT_SOURCES': 'main.swift'})
36+
self.setupPluginServerForTesting()
37+
3638
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
3739
self, "break here", lldb.SBFileSpec("main.swift")
3840
)
@@ -53,3 +55,24 @@ def replace_last(old, new, string):
5355
# Make sure we can set a symbolic breakpoint on a macro.
5456
b = target.BreakpointCreateByName("stringify")
5557
self.assertGreaterEqual(b.GetNumLocations(), 1)
58+
59+
@swiftTest
60+
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
61+
@expectedFailureAll(oslist=["linux"])
62+
def testInteractive(self):
63+
"""Test Swift macros that are loaded via a user-initiated import"""
64+
self.build(dictionary={'SWIFT_SOURCES': 'empty.swift'})
65+
self.setupPluginServerForTesting()
66+
target, process, thread, bkpt = lldbutil.run_to_name_breakpoint(
67+
self, "main"
68+
)
69+
70+
types_log = self.getBuildArtifact('types.log')
71+
self.expect('log enable lldb types -f "%s"' % types_log)
72+
self.expect('expression -- import Macro')
73+
self.expect('expression -- #stringify(1)', substrs=['0 = 1', '1 = "1"'])
74+
self.filecheck('platform shell cat "%s"' % types_log, __file__)
75+
# CHECK: CacheUserImports(){{.*}}: Macro.
76+
# CHECK: SwiftASTContextForExpressions::LoadOneModule(){{.*}}Imported module Macro from {kind = Serialized Swift AST, filename = "{{.*}}Macro.swiftmodule";}
77+
# CHECK: CacheUserImports(){{.*}}Scanning for search paths in{{.*}}Macro.swiftmodule
78+
# CHECK: SwiftASTContextForExpressions::LogConfiguration(){{.*}} -external-plugin-path {{.*}}/lang/swift/macro/{{.*}}#{{.*}}/swift-plugin-server
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("Hello World")

lldb/test/API/lang/swift/macro/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@freestanding(expression) macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroImpl", type: "StringifyMacro")
1+
import Macro
22

33
func testStringify(a: Int, b: Int) {
44
print("break here")

0 commit comments

Comments
 (0)