Skip to content

Commit e8e7c53

Browse files
Merge pull request #11834 from adrian-prantl/add-esml
[LLDB] Set up an explicit Swift module loader
2 parents 51330f9 + ce39c37 commit e8e7c53

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
@@ -1899,6 +1899,22 @@ void SwiftASTContext::AddExtraClangArgs(
18991899
RemoveExplicitModules(importer_options.ExtraArgs);
19001900
}
19011901

1902+
bool SwiftASTContext::IsModuleAvailableInCAS(const std::string &key) {
1903+
auto id = m_cas->parseID(key);
1904+
if (!id) {
1905+
HEALTH_LOG_PRINTF("failed to parse CASID when loading module: %s",
1906+
toString(id.takeError()).c_str());
1907+
return false;
1908+
}
1909+
auto lookup = m_action_cache->get(*id);
1910+
if (!lookup) {
1911+
HEALTH_LOG_PRINTF("module lookup failure through action cache: %s",
1912+
toString(lookup.takeError()).c_str());
1913+
return false;
1914+
}
1915+
return (bool)*lookup;
1916+
};
1917+
19021918
void SwiftASTContext::AddExtraClangCC1Args(
19031919
const std::vector<std::string> &source,
19041920
const std::vector<std::pair<std::string, bool>> module_search_paths,
@@ -1970,26 +1986,9 @@ void SwiftASTContext::AddExtraClangCC1Args(
19701986
invocation.getCASOpts().PluginOptions =
19711987
GetCASOptions().CASOpts.PluginOptions;
19721988

1973-
// Check the module availability in CAS, if not, fallback to regular load.
1974-
auto CheckModuleInCAS = [&](const std::string &key) {
1975-
auto id = m_cas->parseID(key);
1976-
if (!id) {
1977-
HEALTH_LOG_PRINTF("failed to parse CASID when loading module: %s",
1978-
toString(id.takeError()).c_str());
1979-
return false;
1980-
}
1981-
auto lookup = m_action_cache->get(*id);
1982-
if (!lookup) {
1983-
HEALTH_LOG_PRINTF("module lookup failure through action cache: %s",
1984-
toString(lookup.takeError()).c_str());
1985-
return false;
1986-
}
1987-
return (bool)*lookup;
1988-
};
1989-
19901989
use_cas_module = llvm::all_of(
19911990
invocation.getFrontendOpts().ModuleCacheKeys, [&](const auto &entry) {
1992-
auto exist = CheckModuleInCAS(entry.second);
1991+
bool exist = IsModuleAvailableInCAS(entry.second);
19931992
if (!exist)
19941993
HEALTH_LOG_PRINTF("module '%s' cannot be load "
19951994
"from CAS using key: %s, fallback to "
@@ -3748,7 +3747,6 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
37483747
std::string moduleCachePath =
37493748
GetCompilerInvocation().getClangModuleCachePath().str();
37503749
std::unique_ptr<swift::ClangImporter> clang_importer_up;
3751-
auto &clang_importer_options = GetClangImporterOptions();
37523750
if (!m_ast_context_up->SearchPathOpts.getSDKPath().empty() ||
37533751
TargetHasNoSDK()) {
37543752
// Create the DWARFImporterDelegate.
@@ -3848,15 +3846,34 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
38483846
m_ast_context_up->addModuleLoader(std::move(memory_buffer_loader_up));
38493847
}
38503848

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

3857-
// 2. Create and install the module interface loader.
3874+
// 3. Create and install the module interface loader.
38583875
//
3859-
// The ordering of 2-4 is the same as the Swift compiler's 1-3,
3876+
// The ordering of 2-4 is the same as the Swift compiler's 2-4,
38603877
// where unintuitively the serialized module loader comes before the
38613878
// module interface loader. The reason for this is that the module
38623879
// interface loader is actually 2-in-1 and secretly attempts to load
@@ -3868,21 +3885,22 @@ ThreadSafeASTContext SwiftASTContext::GetASTContext() {
38683885
if (loading_mode != swift::ModuleLoadingMode::OnlySerialized) {
38693886
std::unique_ptr<swift::ModuleLoader> module_interface_loader_up(
38703887
swift::ModuleInterfaceLoader::create(
3871-
*m_ast_context_up, *static_cast<swift::ModuleInterfaceCheckerImpl*>(
3872-
m_ast_context_up->getModuleInterfaceChecker()), m_dependency_tracker.get(),
3873-
loading_mode));
3888+
*m_ast_context_up,
3889+
*static_cast<swift::ModuleInterfaceCheckerImpl *>(
3890+
m_ast_context_up->getModuleInterfaceChecker()),
3891+
m_dependency_tracker.get(), loading_mode));
38743892
if (module_interface_loader_up)
38753893
m_ast_context_up->addModuleLoader(std::move(module_interface_loader_up));
38763894
}
38773895

3878-
// 3. Create and install the serialized module loader.
3896+
// 4. Create and install the serialized module loader.
38793897
std::unique_ptr<swift::ModuleLoader> serialized_module_loader_up(
38803898
swift::ImplicitSerializedModuleLoader::create(
38813899
*m_ast_context_up, m_dependency_tracker.get(), loading_mode));
38823900
if (serialized_module_loader_up)
38833901
m_ast_context_up->addModuleLoader(std::move(serialized_module_loader_up));
38843902

3885-
// 4. Install the clang importer.
3903+
// 5. Install the clang importer.
38863904
if (clang_importer_up) {
38873905
m_clangimporter = (swift::ClangImporter *)clang_importer_up.get();
38883906
m_ast_context_up->addModuleLoader(std::move(clang_importer_up),
@@ -4080,6 +4098,23 @@ SwiftASTContext::GetModule(const SourceModule &module, bool *cached) {
40804098
// Create a diagnostic consumer for the diagnostics produced by the import.
40814099
auto import_diags = getScopedDiagnosticConsumer();
40824100

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

40854120
// Error handling.
@@ -4102,6 +4137,16 @@ SwiftASTContext::GetModule(const SourceModule &module, bool *cached) {
41024137
LOG_PRINTF(GetLog(LLDBLog::Types), "(\"%s\") -- found %s",
41034138
module_name.c_str(), module_decl->getName().str().str().c_str());
41044139

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

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)