[Caching] Don't parse LLVMArgs in cache replay instance

`llvm::cl::ParseCommandLineOptions()` is not thread-safe to be called
from libSwiftScan so replaying multiple commands in parallel can crash
the build system. Since the replay instance is not used for compilation
and only need information from command-line arguments to create outputs
and diagnostics, ignore LLVMArgs when replaying.

rdar://120423882
This commit is contained in:
Steven Wu
2024-01-03 09:49:44 -08:00
parent e2f888b311
commit f232ebb286
3 changed files with 56 additions and 10 deletions

View File

@@ -0,0 +1,25 @@
// RUN: %empty-directory(%t)
// RUN: %swift-scan-test -action compute_cache_key -cas-path %t/cas -input %s -- %target-swift-frontend -cache-compile-job -Rcache-compile-job %s \
// RUN: -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies -module-name Test -o %t/test.o -cas-path %t/cas \
// RUN: -allow-unstable-cache-key-for-testing -Xllvm -aarch64-use-tbi > %t/key.casid
// RUN: not %swift-scan-test -action cache_query -id @%t/key.casid -cas-path %t/cas 2>&1 | %FileCheck %s --check-prefix=CHECK-QUERY-NOT-FOUND
// RUN: %target-swift-frontend -cache-compile-job -Rcache-compile-job %s -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas -allow-unstable-cache-key-for-testing -Xllvm -aarch64-use-tbi
// RUN: %swift-scan-test -action cache_query -id @%t/key.casid -cas-path %t/cas | %FileCheck %s --check-prefix=CHECK-QUERY
// RUN: %swift-scan-test -action replay_result -cas-path %t/cas -id @%t/key.casid -threads 10 -- %target-swift-frontend -cache-compile-job -Rcache-compile-job %s \
// RUN: -emit-module -emit-module-path %t/Test2.swiftmodule -c -emit-dependencies -module-name Test -o %t/test2.o -cas-path %t/cas \
// RUN: -allow-unstable-cache-key-for-testing -Xllvm -aarch64-use-tbi
// CHECK-QUERY-NOT-FOUND: cached output not found
// CHECK-QUERY: Cached Compilation for key "llvmcas://{{.*}}" has 4 outputs:
// CHECK-QUERY-NEXT: object: llvmcas://
// CHECK-QUERY-NEXT: dependencies: llvmcas://
// CHECK-QUERY-NEXT: swiftmodule: llvmcas://
// CHECK-QUERY-NEXT: cached-diagnostics: llvmcas://
func testFunc() {}

View File

@@ -778,6 +778,12 @@ swiftscan_cache_replay_instance_create(int argc, const char **argv,
return nullptr;
}
// Clear the LLVMArgs as `llvm::cl::ParseCommandLineOptions` is not
// thread-safe to be called in libSwiftScan. The replay instance should not be
// used to do compilation so clearing `-Xllvm` should not affect replay
// result.
Instance->Invocation.getFrontendOptions().LLVMArgs.clear();
return wrap(Instance);
}

View File

@@ -21,6 +21,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/ThreadPool.h"
using namespace llvm;
@@ -39,6 +40,9 @@ llvm::cl::opt<std::string> CASID("id", llvm::cl::desc("<casid>"),
llvm::cl::cat(Category));
llvm::cl::opt<std::string> Input("input", llvm::cl::desc("<file|index>"),
llvm::cl::cat(Category));
llvm::cl::opt<unsigned> Threads("threads",
llvm::cl::desc("<number of threads>"),
llvm::cl::cat(Category), cl::init(1));
llvm::cl::opt<Actions>
Action("action", llvm::cl::desc("<action>"),
llvm::cl::values(clEnumVal(compute_cache_key, "compute cache key"),
@@ -216,16 +220,27 @@ int main(int argc, char *argv[]) {
llvm::StringSaver Saver(Alloc);
auto Args = createArgs(SwiftCommands, Saver);
std::atomic<int> Ret = 0;
llvm::ThreadPool Pool(llvm::hardware_concurrency(Threads));
for (unsigned i = 0; i < Threads; ++i) {
Pool.async([&]() {
switch (Action) {
case compute_cache_key:
return action_compute_cache_key(cas, Input, Args);
Ret += action_compute_cache_key(cas, Input, Args);
break;
case compute_cache_key_from_index:
return action_compute_cache_key_from_index(cas, Input, Args);
Ret += action_compute_cache_key_from_index(cas, Input, Args);
break;
case cache_query:
return action_cache_query(cas, CASID.c_str());
Ret += action_cache_query(cas, CASID.c_str());
break;
case replay_result:
return action_replay_result(cas, CASID.c_str(), Args);
Ret += action_replay_result(cas, CASID.c_str(), Args);
break;
}
});
}
Pool.wait();
return EXIT_SUCCESS;
return Ret;
}