Skip to content

Commit 80066b9

Browse files
Merge pull request #11904 from adrian-prantl/cherry-pick-swift-release-6.3-LLDB-Set-up-an-explicit-Swift-module-loader
[Cherry-pick into swift/release/6.3] [LLDB] Set up an explicit Swift module loader
2 parents 668693d + b5d3e95 commit 80066b9

File tree

6 files changed

+117
-29
lines changed

6 files changed

+117
-29
lines changed

lldb/include/lldb/Core/ModuleList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class ModuleListProperties : public Properties {
8383
bool GetUseSwiftClangImporter() const;
8484
bool GetUseSwiftDWARFImporter() const;
8585
bool SetUseSwiftDWARFImporter(bool new_value);
86+
bool GetUseSwiftExplicitModuleLoader() const;
87+
bool SetUseSwiftExplicitModuleLoader(bool new_value);
8688
bool GetSwiftValidateTypeSystem() const;
8789
bool GetSwiftTypeSystemFallback() const;
8890
bool GetSwiftLoadConformances() const;

lldb/source/Core/CoreProperties.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ let Definition = "modulelist" in {
2525
def UseSwiftDWARFImporter: Property<"use-swift-dwarfimporter", "Boolean">,
2626
DefaultTrue,
2727
Desc<"Reconstruct Clang module dependencies from DWARF when debugging Swift code">;
28+
def UseSwiftExplicitModuleLoader
29+
: Property<"use-swift-explicit-module-loader", "Boolean">,
30+
DefaultTrue,
31+
Desc<"Prefer explicitly specified modules over ones found in dSYMs">;
2832
def SwiftValidateTypeSystem: Property<"swift-validate-typesystem", "Boolean">,
2933
DefaultFalse,
3034
Desc<"Validate all Swift typesystem queries. Used for testing an asserts-enabled LLDB only.">;

lldb/source/Core/ModuleList.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,17 @@ bool ModuleListProperties::SetUseSwiftDWARFImporter(bool new_value) {
199199
return SetPropertyAtIndex(idx, new_value);
200200
}
201201

202+
bool ModuleListProperties::GetUseSwiftExplicitModuleLoader() const {
203+
const uint32_t idx = ePropertyUseSwiftExplicitModuleLoader;
204+
return GetPropertyAtIndexAs<bool>(
205+
idx, g_modulelist_properties[idx].default_uint_value != 0);
206+
}
207+
208+
bool ModuleListProperties::SetUseSwiftExplicitModuleLoader(bool new_value) {
209+
const uint32_t idx = ePropertyUseSwiftExplicitModuleLoader;
210+
return SetPropertyAtIndex(idx, new_value);
211+
}
212+
202213
bool ModuleListProperties::GetSwiftValidateTypeSystem() const {
203214
const uint32_t idx = ePropertySwiftValidateTypeSystem;
204215
return GetPropertyAtIndexAs<bool>(

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

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,22 @@ void SwiftASTContext::AddExtraClangArgs(
18961896
RemoveExplicitModules(importer_options.ExtraArgs);
18971897
}
18981898

1899+
bool SwiftASTContext::IsModuleAvailableInCAS(const std::string &key) {
1900+
auto id = m_cas->parseID(key);
1901+
if (!id) {
1902+
HEALTH_LOG_PRINTF("failed to parse CASID when loading module: %s",
1903+
toString(id.takeError()).c_str());
1904+
return false;
1905+
}
1906+
auto lookup = m_action_cache->get(*id);
1907+
if (!lookup) {
1908+
HEALTH_LOG_PRINTF("module lookup failure through action cache: %s",
1909+
toString(lookup.takeError()).c_str());
1910+
return false;
1911+
}
1912+
return (bool)*lookup;
1913+
};
1914+
18991915
void SwiftASTContext::AddExtraClangCC1Args(
19001916
const std::vector<std::string> &source,
19011917
const std::vector<std::pair<std::string, bool>> module_search_paths,
@@ -1967,26 +1983,9 @@ void SwiftASTContext::AddExtraClangCC1Args(
19671983
invocation.getCASOpts().PluginOptions =
19681984
GetCASOptions().Config.PluginOptions;
19691985

1970-
// Check the module availability in CAS, if not, fallback to regular load.
1971-
auto CheckModuleInCAS = [&](const std::string &key) {
1972-
auto id = m_cas->parseID(key);
1973-
if (!id) {
1974-
HEALTH_LOG_PRINTF("failed to parse CASID when loading module: %s",
1975-
toString(id.takeError()).c_str());
1976-
return false;
1977-
}
1978-
auto lookup = m_action_cache->get(*id);
1979-
if (!lookup) {
1980-
HEALTH_LOG_PRINTF("module lookup failure through action cache: %s",
1981-
toString(lookup.takeError()).c_str());
1982-
return false;
1983-
}
1984-
return (bool)*lookup;
1985-
};
1986-
19871986
use_cas_module = llvm::all_of(
19881987
invocation.getFrontendOpts().ModuleCacheKeys, [&](const auto &entry) {
1989-
auto exist = CheckModuleInCAS(entry.second);
1988+
bool exist = IsModuleAvailableInCAS(entry.second);
19901989
if (!exist)
19911990
HEALTH_LOG_PRINTF("module '%s' cannot be load "
19921991
"from CAS using key: %s, fallback to "
@@ -3745,7 +3744,6 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
37453744
std::string moduleCachePath =
37463745
GetCompilerInvocation().getClangModuleCachePath().str();
37473746
std::unique_ptr<swift::ClangImporter> clang_importer_up;
3748-
auto &clang_importer_options = GetClangImporterOptions();
37493747
if (!m_ast_context_up->SearchPathOpts.getSDKPath().empty() ||
37503748
TargetHasNoSDK()) {
37513749
// Create the DWARFImporterDelegate.
@@ -3845,15 +3843,34 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
38453843
m_ast_context_up->addModuleLoader(std::move(memory_buffer_loader_up));
38463844
}
38473845

3846+
// 2. Create the explicit swift module loader.
3847+
if (props.GetUseSwiftExplicitModuleLoader()) {
3848+
auto &search_path_opts = GetCompilerInvocation().getSearchPathOptions();
3849+
std::unique_ptr<swift::ModuleLoader> esml_up =
3850+
swift::ExplicitSwiftModuleLoader::create(
3851+
*m_ast_context_up, m_dependency_tracker.get(), loading_mode,
3852+
search_path_opts.ExplicitSwiftModuleMapPath,
3853+
search_path_opts.ExplicitSwiftModuleInputs,
3854+
/*IgnoreSwiftSourceInfo*/ false);
3855+
if (esml_up) {
3856+
m_explicit_swift_module_loader =
3857+
static_cast<swift::ExplicitSwiftModuleLoader *>(esml_up.get());
3858+
m_ast_context_up->addModuleLoader(std::move(esml_up), /*isClang=*/false,
3859+
/*isDwarf=*/false,
3860+
/*isInterface=*/false,
3861+
/*isExplicit=*/true);
3862+
}
3863+
}
3864+
38483865
// Add a module interface checker.
38493866
m_ast_context_up->addModuleInterfaceChecker(
3850-
std::make_unique<swift::ModuleInterfaceCheckerImpl>(*m_ast_context_up,
3851-
moduleCachePath, prebuiltModuleCachePath,
3852-
swift::ModuleInterfaceLoaderOptions()));
3867+
std::make_unique<swift::ModuleInterfaceCheckerImpl>(
3868+
*m_ast_context_up, moduleCachePath, prebuiltModuleCachePath,
3869+
swift::ModuleInterfaceLoaderOptions()));
38533870

3854-
// 2. Create and install the module interface loader.
3871+
// 3. Create and install the module interface loader.
38553872
//
3856-
// The ordering of 2-4 is the same as the Swift compiler's 1-3,
3873+
// The ordering of 2-4 is the same as the Swift compiler's 2-4,
38573874
// where unintuitively the serialized module loader comes before the
38583875
// module interface loader. The reason for this is that the module
38593876
// interface loader is actually 2-in-1 and secretly attempts to load
@@ -3865,21 +3882,22 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
38653882
if (loading_mode != swift::ModuleLoadingMode::OnlySerialized) {
38663883
std::unique_ptr<swift::ModuleLoader> module_interface_loader_up(
38673884
swift::ModuleInterfaceLoader::create(
3868-
*m_ast_context_up, *static_cast<swift::ModuleInterfaceCheckerImpl*>(
3869-
m_ast_context_up->getModuleInterfaceChecker()), m_dependency_tracker.get(),
3870-
loading_mode));
3885+
*m_ast_context_up,
3886+
*static_cast<swift::ModuleInterfaceCheckerImpl *>(
3887+
m_ast_context_up->getModuleInterfaceChecker()),
3888+
m_dependency_tracker.get(), loading_mode));
38713889
if (module_interface_loader_up)
38723890
m_ast_context_up->addModuleLoader(std::move(module_interface_loader_up));
38733891
}
38743892

3875-
// 3. Create and install the serialized module loader.
3893+
// 4. Create and install the serialized module loader.
38763894
std::unique_ptr<swift::ModuleLoader> serialized_module_loader_up(
38773895
swift::ImplicitSerializedModuleLoader::create(
38783896
*m_ast_context_up, m_dependency_tracker.get(), loading_mode));
38793897
if (serialized_module_loader_up)
38803898
m_ast_context_up->addModuleLoader(std::move(serialized_module_loader_up));
38813899

3882-
// 4. Install the clang importer.
3900+
// 5. Install the clang importer.
38833901
if (clang_importer_up) {
38843902
m_clangimporter = (swift::ClangImporter *)clang_importer_up.get();
38853903
m_ast_context_up->addModuleLoader(std::move(clang_importer_up),
@@ -4077,6 +4095,23 @@ SwiftASTContext::GetModule(const SourceModule &module, bool *cached) {
40774095
// Create a diagnostic consumer for the diagnostics produced by the import.
40784096
auto import_diags = getScopedDiagnosticConsumer();
40794097

4098+
// Is this an explicitly specified explicit Swift module?
4099+
StringRef module_path = module.search_path.GetStringRef();
4100+
bool is_esml_module = (module_path.ends_with(".swiftmodule") &&
4101+
llvm::sys::fs::exists(module_path)) ||
4102+
(m_cas && IsModuleAvailableInCAS(module_path.str()));
4103+
if (is_esml_module) {
4104+
std::string path = module_path.str();
4105+
bool unloaded = false;
4106+
if (m_explicit_swift_module_loader) {
4107+
ast->addExplicitModulePath(module_name, path);
4108+
if (auto *memory_loader = GetMemoryBufferModuleLoader())
4109+
unloaded = memory_loader->unregisterMemoryBuffer(module_name);
4110+
}
4111+
HEALTH_LOG_PRINTF("found explicit module \"%s\"%s", path.c_str(),
4112+
unloaded ? "; replacing AST section module" : "");
4113+
}
4114+
40804115
swift::ModuleDecl *module_decl = ast->getModuleByName(module_name);
40814116

40824117
// Error handling.
@@ -4099,6 +4134,16 @@ SwiftASTContext::GetModule(const SourceModule &module, bool *cached) {
40994134
LOG_PRINTF(GetLog(LLDBLog::Types), "(\"%s\") -- found %s",
41004135
module_name.c_str(), module_decl->getName().str().str().c_str());
41014136

4137+
if (is_esml_module) {
4138+
// Simulate the effect of the BypassResilience flag in the
4139+
// MemoryBufferSerializedModuleLoader. Explicitly specified
4140+
// modules are not typically produced from textual interfaces. By
4141+
// disabling resilience, the debugger can directly access private
4142+
// members.
4143+
//if (!module_decl->isBuiltFromInterface())
4144+
// module_decl->setBypassResilience();
4145+
}
4146+
41024147
m_swift_module_cache.insert({module_name, *module_decl});
41034148
return *module_decl;
41044149
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ class SwiftASTContext : public TypeSystemSwift {
278278

279279
void ConfigureModuleValidation(std::vector<std::string> &extra_args);
280280

281+
/// Check whether a module with key \c key is available in CAS.
282+
bool IsModuleAvailableInCAS(const std::string &key);
283+
281284
/// Add a list of Clang arguments to the ClangImporter options and
282285
/// apply the working directory to any relative paths.
283286
void AddExtraClangArgs(
@@ -972,6 +975,7 @@ class SwiftASTContext : public TypeSystemSwift {
972975
/// Owned by the AST.
973976
swift::MemoryBufferSerializedModuleLoader *m_memory_buffer_module_loader =
974977
nullptr;
978+
swift::ModuleLoader *m_explicit_swift_module_loader = nullptr;
975979
swift::ClangImporter *m_clangimporter = nullptr;
976980
/// Wraps the clang::ASTContext owned by ClangImporter.
977981
std::shared_ptr<TypeSystemClang> m_clangimporter_typesystem;

lldb/test/API/lang/swift/explicit_modules/simple/TestSwiftExplicitModules.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,30 @@ def test(self):
1313
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
1414
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))
1515

16+
log = self.getBuildArtifact("types.log")
17+
self.expect('log enable lldb types -f "%s"' % log)
1618
self.expect("expression c", substrs=['hello explicit'])
19+
self.filecheck('platform shell cat "%s"' % log, __file__)
20+
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift"){{.*}} found explicit module {{.*}}a.swiftmodule
21+
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift"){{.*}} Module import remark: loaded module 'a'; source: '{{.*}}a.swiftmodule', loaded: '{{.*}}a.swiftmodule'
1722

23+
@swiftTest
24+
def test_disable_esml(self):
25+
"""Test disabling the explicit Swift module loader"""
26+
self.build()
27+
self.expect("settings set symbols.use-swift-explicit-module-loader false")
28+
29+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
30+
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))
31+
32+
log = self.getBuildArtifact("types.log")
33+
self.expect('log enable lldb types -f "%s"' % log)
34+
self.expect("expression c", substrs=['hello explicit'])
35+
self.filecheck('platform shell cat "%s"' % log, __file__, '--check-prefix=DISABLED')
36+
# DISABLED: SwiftASTContextForExpressions(module: "a", cu: "main.swift"){{.*}} found explicit module {{.*}}a.swiftmodule
37+
# DISABLED: SwiftASTContextForExpressions(module: "a", cu: "main.swift"){{.*}} Module import remark: loaded module 'a'; source: 'a', loaded: 'a'
38+
39+
1840
@swiftTest
1941
@skipUnlessDarwin
2042
def test_import(self):

0 commit comments

Comments
 (0)