12 #include "llvm/Support/ThreadPool.h" 21 return llvm::make_error<llvm::StringError>(Message,
22 llvm::inconvertibleErrorCode());
32 class ThreadSafeToolResults :
public ToolResults {
34 void addResult(StringRef Key, StringRef
Value)
override {
35 std::unique_lock<std::mutex> LockGuard(Mutex);
36 Results.addResult(Key, Value);
39 std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
40 AllKVResults()
override {
41 return Results.AllKVResults();
44 void forEachResult(llvm::function_ref<
void(StringRef Key, StringRef Value)>
46 Results.forEachResult(Callback);
50 InMemoryToolResults Results;
56 llvm::cl::opt<std::string>
58 llvm::cl::desc(
"Only process files that match this filter. " 59 "This flag only applies to all-TUs."),
60 llvm::cl::init(
".*"));
64 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
65 : Compilations(Compilations), Results(new ThreadSafeToolResults),
66 Context(Results.get()), ThreadCount(ThreadCount) {}
70 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
71 : OptionsParser(
std::move(Options)),
72 Compilations(OptionsParser->getCompilations()),
73 Results(new ThreadSafeToolResults), Context(Results.get()),
74 ThreadCount(ThreadCount) {}
83 if (Actions.size() != 1)
85 "Only support executing exactly 1 action at this point.");
89 auto AppendError = [&](llvm::Twine Err) {
90 std::unique_lock<std::mutex> LockGuard(TUMutex);
91 ErrorMsg += Err.str();
94 auto Log = [&](llvm::Twine Msg) {
95 std::unique_lock<std::mutex> LockGuard(TUMutex);
96 llvm::errs() << Msg.str() <<
"\n";
99 std::vector<std::string> Files;
100 llvm::Regex RegexFilter(
Filter);
101 for (
const auto& File : Compilations.
getAllFiles()) {
102 if (RegexFilter.match(File))
103 Files.push_back(File);
106 const std::string TotalNumStr = std::to_string(Files.size());
107 unsigned Counter = 0;
109 std::unique_lock<std::mutex> LockGuard(TUMutex);
113 auto &Action = Actions.front();
116 llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
119 if (
auto EC = llvm::sys::fs::current_path(InitialWorkingDir)) {
120 InitialWorkingDir =
"";
121 llvm::errs() <<
"Error while getting current working directory: " 122 << EC.message() <<
"\n";
124 for (std::string File : Files) {
126 [&](std::string Path) {
127 Log(
"[" + std::to_string(Count()) +
"/" + TotalNumStr +
128 "] Processing file " + Path);
132 for (
const auto &FileAndContent : OverlayFiles)
133 Tool.mapVirtualFile(FileAndContent.first(),
134 FileAndContent.second);
136 Tool.setRestoreWorkingDir(
false);
137 if (Tool.run(Action.first.get()))
138 AppendError(llvm::Twine(
"Failed to run action on ") + Path +
145 if (!InitialWorkingDir.empty()) {
146 if (
auto EC = llvm::sys::fs::set_current_path(InitialWorkingDir))
147 llvm::errs() <<
"Error while restoring working directory: " 148 << EC.message() <<
"\n";
152 if (!ErrorMsg.empty())
155 return llvm::Error::success();
159 "execute-concurrency",
160 llvm::cl::desc(
"The number of threads used to process all files in " 161 "parallel. Set to 0 for hardware concurrency. " 162 "This flag only applies to all-TUs."),
171 "[AllTUsToolExecutorPlugin] Please provide a directory/file path in " 172 "the compilation database.");
173 return llvm::make_unique<AllTUsToolExecutor>(std::move(OptionsParser),
178 static ToolExecutorPluginRegistry::Add<AllTUsToolExecutorPlugin>
179 X(
"all-TUs",
"Runs FrontendActions on all TUs in the compilation database. " 180 "Tool results are stored in memory.");
Dataflow Directional Tag Classes.