Skip to content

Commit 5cbd9b7

Browse files
Merge pull request #7259 from adrian-prantl/107031048-5.9
Parse plugin search paths from swift modules that are interactively
2 parents fdda925 + 83d0b1d commit 5cbd9b7

File tree

7 files changed

+162
-74
lines changed

7 files changed

+162
-74
lines changed

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

Lines changed: 103 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ static void printASTValidationError(
10851085
llvm::raw_ostream &errs,
10861086
const swift::serialization::ValidationInfo &ast_info,
10871087
const swift::serialization::ExtendedValidationInfo &ext_ast_info,
1088-
Module &module, StringRef module_buf, bool invalid_name,
1088+
StringRef module_name, StringRef module_buf, bool invalid_name,
10891089
bool invalid_size) {
10901090
const char *error = getImportFailureString(ast_info.status);
10911091
errs << "AST validation error";
@@ -1110,9 +1110,9 @@ static void printASTValidationError(
11101110
- SDK path: {7}
11111111
- Clang Importer Options:
11121112
)",
1113-
ast_info.name, module.GetSpecificationDescription(), error,
1114-
ast_info.targetTriple, ast_info.shortVersion, ast_info.bytes,
1115-
module_buf.size(), ext_ast_info.getSDKPath());
1113+
ast_info.name, module_name, error, ast_info.targetTriple,
1114+
ast_info.shortVersion, ast_info.bytes, module_buf.size(),
1115+
ext_ast_info.getSDKPath());
11161116
for (StringRef ExtraOpt : ext_ast_info.getExtraClangImporterOptions())
11171117
LLDB_LOG(log, " -- {0}", ExtraOpt);
11181118
}
@@ -1170,21 +1170,16 @@ static std::string GetPluginServerForSDK(llvm::StringRef sdk_path) {
11701170
/// invocation with the concatenated search paths from the blobs.
11711171
/// \returns true if an error was encountered.
11721172
static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
1173-
Module &module,
1173+
llvm::StringRef module_name,
1174+
llvm::ArrayRef<StringRef> buffers,
1175+
const PathMappingList &path_map,
11741176
bool discover_implicit_search_paths,
11751177
const std::string &m_description,
11761178
llvm::raw_ostream &error,
11771179
bool &got_serialized_options,
11781180
bool &found_swift_modules) {
11791181
bool found_validation_errors = false;
11801182
got_serialized_options = false;
1181-
auto ast_file_datas = module.GetASTData(eLanguageTypeSwift);
1182-
LOG_PRINTF(GetLog(LLDBLog::Types), "Found %d AST file data entries.",
1183-
(int)ast_file_datas.size());
1184-
1185-
// If no N_AST symbols exist, this is not an error.
1186-
if (ast_file_datas.empty())
1187-
return false;
11881183

11891184
auto &search_path_options = invocation.getSearchPathOptions();
11901185
auto get_override_server = [&](llvm::StringRef plugin_path) -> std::string {
@@ -1257,9 +1252,7 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
12571252

12581253
// An AST section consists of one or more AST modules, optionally
12591254
// with headers. Iterate over all AST modules.
1260-
for (auto ast_file_data_sp : ast_file_datas) {
1261-
llvm::StringRef buf((const char *)ast_file_data_sp->GetBytes(),
1262-
ast_file_data_sp->GetByteSize());
1255+
for (auto buf : buffers) {
12631256
swift::serialization::ValidationInfo info;
12641257
for (; !buf.empty(); buf = buf.substr(info.bytes)) {
12651258
llvm::SmallVector<swift::serialization::SearchPath> searchPaths;
@@ -1274,8 +1267,8 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
12741267
if (invalid_ast || invalid_size || invalid_name) {
12751268
// Validation errors are diagnosed, but not fatal for the context.
12761269
found_validation_errors = true;
1277-
printASTValidationError(error, info, extended_validation_info, module,
1278-
buf, invalid_name, invalid_size);
1270+
printASTValidationError(error, info, extended_validation_info,
1271+
module_name, buf, invalid_name, invalid_size);
12791272
// If there's a size error, quit the loop early, otherwise try the next.
12801273
if (invalid_size)
12811274
break;
@@ -1287,8 +1280,7 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
12871280

12881281
auto remap = [&](const std::string &path) {
12891282
ConstString remapped;
1290-
if (module.GetSourceMappingList().RemapPath(ConstString(path),
1291-
remapped))
1283+
if (path_map.RemapPath(ConstString(path), remapped))
12921284
return remapped.GetStringRef().str();
12931285
return path;
12941286
};
@@ -1761,17 +1753,37 @@ static std::string GetSDKPathFromDebugInfo(std::string m_description,
17611753
return GetSDKPath(m_description, sdk);
17621754
}
17631755

1756+
static std::vector<llvm::StringRef>
1757+
GetASTBuffersFromModule(const std::string &m_description,
1758+
llvm::ArrayRef<lldb::DataBufferSP> ast_file_datas,
1759+
std::string &module_name) {
1760+
LOG_PRINTF(GetLog(LLDBLog::Types), "Found %d AST file data entries in %s.",
1761+
(int)ast_file_datas.size(), module_name.c_str());
1762+
std::vector<llvm::StringRef> buffers;
1763+
for (auto &data : ast_file_datas)
1764+
if (data)
1765+
buffers.push_back(
1766+
StringRef((const char *)data->GetBytes(), data->GetByteSize()));
1767+
return buffers;
1768+
}
1769+
17641770
/// Detect whether a Swift module was "imported" by DWARFImporter.
17651771
/// All this *really* means is that it couldn't be loaded through any
17661772
/// other mechanism.
17671773
static bool IsDWARFImported(swift::ModuleDecl &module) {
1768-
return std::any_of(module.getFiles().begin(), module.getFiles().end(),
1769-
[](swift::FileUnit *file_unit) {
1770-
return (file_unit->getKind() ==
1771-
swift::FileUnitKind::DWARFModule);
1772-
});
1774+
return llvm::any_of(module.getFiles(), [](swift::FileUnit *file_unit) {
1775+
return (file_unit->getKind() == swift::FileUnitKind::DWARFModule);
1776+
});
1777+
}
1778+
1779+
/// Detect whether this is a proper Swift module.
1780+
static bool IsSerializedAST(swift::ModuleDecl &module) {
1781+
return llvm::any_of(module.getFiles(), [](swift::FileUnit *file_unit) {
1782+
return (file_unit->getKind() == swift::FileUnitKind::SerializedAST);
1783+
});
17731784
}
17741785

1786+
17751787
lldb::TypeSystemSP
17761788
SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
17771789
TypeSystemSwiftTypeRef &typeref_typesystem,
@@ -1878,15 +1890,24 @@ SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
18781890
bool got_serialized_options = false;
18791891
llvm::SmallString<0> error;
18801892
llvm::raw_svector_ostream errs(error);
1881-
// Implicit search paths will be discoverd by ValidateSecionModules().
1893+
// Implicit search paths will be discovered by ValidateSecionModules().
18821894
bool discover_implicit_search_paths = false;
1883-
if (DeserializeAllCompilerFlags(swift_ast_sp->GetCompilerInvocation(),
1884-
module, discover_implicit_search_paths,
1885-
m_description, errs, got_serialized_options,
1886-
found_swift_modules)) {
1887-
// Validation errors are not fatal for the context.
1888-
swift_ast_sp->AddDiagnostic(eDiagnosticSeverityError, errs.str());
1889-
}
1895+
auto ast_file_datas = module.GetASTData(eLanguageTypeSwift);
1896+
std::string module_name = module.GetSpecificationDescription();
1897+
std::vector<llvm::StringRef> buffers =
1898+
GetASTBuffersFromModule(m_description, ast_file_datas, module_name);
1899+
1900+
// If no N_AST symbols exist, this is not an error.
1901+
if (!buffers.empty())
1902+
if (DeserializeAllCompilerFlags(
1903+
swift_ast_sp->GetCompilerInvocation(),
1904+
module_name, buffers,
1905+
module.GetSourceMappingList(), discover_implicit_search_paths,
1906+
m_description, errs, got_serialized_options,
1907+
found_swift_modules)) {
1908+
// Validation errors are not fatal for the context.
1909+
swift_ast_sp->AddDiagnostic(eDiagnosticSeverityError, errs.str());
1910+
}
18901911

18911912
llvm::StringRef serialized_triple =
18921913
swift_ast_sp->GetCompilerInvocation().getTargetTriple();
@@ -2180,13 +2201,21 @@ static void ProcessModule(
21802201
llvm::SmallString<0> error;
21812202
llvm::raw_svector_ostream errs(error);
21822203
swift::CompilerInvocation invocation;
2183-
if (DeserializeAllCompilerFlags(
2184-
invocation, *module_sp, discover_implicit_search_paths, m_description,
2185-
errs, got_serialized_options, found_swift_modules)) {
2186-
// TODO: After removing DeserializeAllCompilerFlags from
2187-
// CreateInstance(per-Module), errs will need to be
2188-
// collected here and surfaced.
2189-
}
2204+
auto ast_file_datas = module_sp->GetASTData(eLanguageTypeSwift);
2205+
std::string module_name = module_sp->GetSpecificationDescription();
2206+
std::vector<llvm::StringRef> buffers =
2207+
GetASTBuffersFromModule(m_description, ast_file_datas, module_name);
2208+
2209+
// If no N_AST symbols exist, this is not an error.
2210+
if (!buffers.empty())
2211+
if (DeserializeAllCompilerFlags(
2212+
invocation, module_name, buffers, module_sp->GetSourceMappingList(),
2213+
discover_implicit_search_paths, m_description, errs,
2214+
got_serialized_options, found_swift_modules)) {
2215+
// TODO: After removing DeserializeAllCompilerFlags from
2216+
// CreateInstance(per-Module), errs will need to be
2217+
// collected here and surfaced.
2218+
}
21902219

21912220
// Copy the interesting deserialized flags to the out parameters.
21922221
const auto &opts = invocation.getSearchPathOptions();
@@ -8316,10 +8345,42 @@ bool SwiftASTContextForExpressions::CacheUserImports(
83168345
LOG_PRINTF(GetLog(LLDBLog::Types | LLDBLog::Expressions),
83178346
"Performing auto import on found module: %s.\n",
83188347
module_name.c_str());
8319-
if (!LoadOneModule(module_info, *this, process_sp,
8320-
/*import_dylibs=*/true, error))
8348+
auto *module_decl = LoadOneModule(module_info, *this, process_sp,
8349+
/*import_dylibs=*/true, error);
8350+
if (!module_decl)
83218351
return false;
8322-
8352+
if (IsSerializedAST(*module_decl)) {
8353+
// Parse additional search paths from the module.
8354+
StringRef ast_file = module_decl->getModuleLoadedFilename();
8355+
if (llvm::sys::path::is_absolute(ast_file)) {
8356+
auto file_or_err =
8357+
llvm::MemoryBuffer::getFile(ast_file, /*IsText=*/false,
8358+
/*RequiresNullTerminator=*/false);
8359+
if (!file_or_err.getError() && file_or_err->get()) {
8360+
PathMappingList path_remap;
8361+
llvm::SmallString<0> error;
8362+
bool found_swift_modules = false;
8363+
bool got_serialized_options = false;
8364+
llvm::raw_svector_ostream errs(error);
8365+
bool discover_implicit_search_paths = false;
8366+
swift::CompilerInvocation &invocation = GetCompilerInvocation();
8367+
8368+
LOG_PRINTF(GetLog(LLDBLog::Types),
8369+
"Scanning for search paths in %s",
8370+
ast_file.str().c_str());
8371+
if (DeserializeAllCompilerFlags(
8372+
invocation, ast_file, {file_or_err->get()->getBuffer()},
8373+
path_remap, discover_implicit_search_paths,
8374+
m_description.str().str(), errs, got_serialized_options,
8375+
found_swift_modules)) {
8376+
LOG_PRINTF(GetLog(LLDBLog::Types), "Could not parse %s: %s",
8377+
ast_file.str().c_str(), error.str().str().c_str());
8378+
}
8379+
if (got_serialized_options)
8380+
LogConfiguration();
8381+
}
8382+
}
8383+
}
83238384
// How do we tell we are in REPL or playground mode?
83248385
AddHandLoadedModule(module_const_str, attributed_import);
83258386
}

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)