Skip to content

Commit

Permalink
[lldb] Fix clang importer for swift caching debugging (attempt swiftl…
Browse files Browse the repository at this point in the history
…ang#2)

Further improve how lldb constructing clang importer to utilize explicit
modules:
* Add logics to initialize the swift ASTContext from direct cc1
  arguments embedded in the swiftmodule
* Make sure the direct cc1 arguments are not repeated constructed. It
  should only be constructed as a fresh invocation
* Make sure the lldb doesn't overwrite the explicit module build
  settings when filter arguments. This ensures the already built
  explicit modules are used.
* Use the newly added clang option that ignore CAS info when loading
  PCMs. This allows lldb to load CAS enabled PCM directly from disk.

rdar://135611011
(cherry picked from commit d3b9f2c)
  • Loading branch information
cachemeifyoucan committed Sep 17, 2024
1 parent 68db689 commit 87f13f5
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
45 changes: 31 additions & 14 deletions lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1752,24 +1752,32 @@ static void applyOverrideOptions(std::vector<std::string> &args,

void SwiftASTContext::AddExtraClangArgs(
const std::vector<std::string> &ExtraArgs, StringRef overrideOpts) {
if (ExtraArgs.empty())
return;

swift::ClangImporterOptions &importer_options = GetClangImporterOptions();

// Detect cc1 flags. When DirectClangCC1ModuleBuild is on then the
// clang arguments in the serialized invocation are clang cc1 flags,
// which are very specific to one compiler version and cannot
// be merged with driver options.
bool fresh_invocation = importer_options.ExtraArgs.empty();
if (fresh_invocation && !ExtraArgs.empty() && ExtraArgs.front() == "-cc1")
importer_options.DirectClangCC1ModuleBuild = true;
if (!importer_options.DirectClangCC1ModuleBuild && !ExtraArgs.empty() &&
ExtraArgs.front() == "-cc1")
bool invocation_direct_cc1 = ExtraArgs.front() == "-cc1";

// If it is not a fresh invocation, make sure the cc1 option matches.
if (!fresh_invocation &&
(importer_options.DirectClangCC1ModuleBuild != invocation_direct_cc1))
AddDiagnostic(
eSeverityWarning,
"Mixing and matching of driver and cc1 Clang options detected");

importer_options.DirectClangCC1ModuleBuild = invocation_direct_cc1;

// If using direct cc1 flags, compute the arguments and return.
// Since this is cc1 flags, no driver overwrite can be applied.
// Since this is cc1 flags, override options are driver flags and don't apply.
if (importer_options.DirectClangCC1ModuleBuild) {
if (!fresh_invocation)
importer_options.ExtraArgs.clear();
AddExtraClangCC1Args(ExtraArgs, importer_options.ExtraArgs);
return;
}
Expand Down Expand Up @@ -1821,12 +1829,17 @@ void SwiftASTContext::AddExtraClangCC1Args(
invocation.getFrontendOpts().ModuleCacheKeys.clear();
invocation.getCASOpts() = clang::CASOptions();

// Ignore CAS info inside modules when loading.
invocation.getFrontendOpts().ModuleLoadIgnoreCAS = true;

// Remove non-existing modules in a systematic way.
bool module_missing = false;
auto CheckFileExists = [&](const char *file) {
if (!llvm::sys::fs::exists(file)) {
std::string m_description;
HEALTH_LOG_PRINTF("Nonexistent explicit module file %s", file);
std::string warn;
llvm::raw_string_ostream(warn)
<< "Nonexistent explicit module file " << file;
AddDiagnostic(eSeverityWarning, warn);
module_missing = true;
}
};
Expand All @@ -1835,8 +1848,8 @@ void SwiftASTContext::AddExtraClangCC1Args(
llvm::for_each(invocation.getFrontendOpts().ModuleFiles,
[&](const auto &mod) { CheckFileExists(mod.c_str()); });

// If missing, clear all the prebuilt module options and use implicit module
// build.
// If missing, clear all the prebuilt module options and switch to implicit
// modules build.
if (module_missing) {
invocation.getHeaderSearchOpts().PrebuiltModuleFiles.clear();
invocation.getFrontendOpts().ModuleFiles.clear();
Expand Down Expand Up @@ -1944,6 +1957,10 @@ void SwiftASTContext::RemapClangImporterOptions(

void SwiftASTContext::FilterClangImporterOptions(
std::vector<std::string> &extra_args, SwiftASTContext *ctx) {
// The direct cc1 mode do not need any extra audit.
if (ctx && ctx->GetClangImporterOptions().DirectClangCC1ModuleBuild)
return;

std::string ivfs_arg;
// Copy back a filtered version of ExtraArgs.
std::vector<std::string> orig_args(std::move(extra_args));
Expand All @@ -1954,11 +1971,6 @@ void SwiftASTContext::FilterClangImporterOptions(
arg_sr == "-fno-implicit-module-maps")
continue;

// This is not a cc1 option.
if (arg_sr.starts_with("--target=") && ctx &&
ctx->GetClangImporterOptions().DirectClangCC1ModuleBuild)
continue;

// The VFS options turn into fatal errors when the referenced file
// is not found. Since the Xcode build system tends to create a
// lot of VFS overlays by default, stat them and emit a warning if
Expand Down Expand Up @@ -2245,6 +2257,11 @@ ProcessModule(Module &module, std::string m_description,
for (auto path : opts.getFrameworkSearchPaths())
framework_search_paths.push_back({path.Path, path.IsSystem});
auto &clang_opts = invocation.getClangImporterOptions().ExtraArgs;
// If the args embedded are cc1 args, they are not compatible with existing
// setting. Clear the previous args.
if (!clang_opts.empty() && clang_opts.front() == "-cc1")
extra_clang_args.clear();

for (const std::string &arg : clang_opts) {
extra_clang_args.push_back(arg);
LOG_VERBOSE_PRINTF(GetLog(LLDBLog::Types), "adding Clang argument \"%s\".",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import unittest2

class TestSwiftClangImporterCaching(TestBase):

Expand All @@ -27,5 +28,7 @@ def test(self):
self.filecheck('platform shell cat "%s"' % log, __file__)
### -cc1 should be round-tripped so there is no more `-cc1` in the extra args. Look for `-triple` which is a cc1 flag.
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift")::LogConfiguration() -- -triple
# CHECK: SwiftASTContextForExpressions(module: "a", cu: "main.swift") Module import remark: loaded module 'ClangA'
# CHECK-NOT: -cc1
# CHECK-NOT: -fmodule-file-cache-key
# CHECK-NOT: Clang error:
30 changes: 30 additions & 0 deletions lldb/test/Shell/Swift/caching.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# REQUIRES: swift
# REQUIRES: system-darwin

# RUN: rm -rf %t && mkdir %t
# RUN: split-file %s %t
# RUN: %target-swiftc -g -Onone -save-temps \
# RUN: -module-cache-path %t/cache %t/main.swift \
# RUN: -cache-compile-job -cas-path %t/cas -explicit-module-build \
# RUN: -module-name main -o %t/main

# RUN: %lldb %t/main -s %t/lldb.script 2>&1 | FileCheck %s
# CHECK: LogConfiguration() -- Extra clang arguments
# CHECK-COUNT-1: LogConfiguration() -- -triple
# CHECK: (Int) ${{.*}} = 1

//--- main.swift
func test() {
print("break here")
}
test()

//--- lldb.script
# Force loading from interface to simulate no binary module available.
settings set symbols.swift-module-loading-mode prefer-interface
log enable lldb types
b test
run
# Create a SwiftASTContext
expr 1
quit

0 comments on commit 87f13f5

Please sign in to comment.