1 //===- lib/Tooling/AllTUsExecution.cpp - Execute actions on all TUs. ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/Tooling/AllTUsExecution.h"
11 #include "clang/Tooling/ToolExecutorPluginRegistry.h"
12 #include "llvm/Support/ThreadPool.h"
17 const char *AllTUsToolExecutor::ExecutorName = "AllTUsToolExecutor";
20 llvm::Error make_string_error(const llvm::Twine &Message) {
21 return llvm::make_error<llvm::StringError>(Message,
22 llvm::inconvertibleErrorCode());
25 ArgumentsAdjuster getDefaultArgumentsAdjusters() {
26 return combineAdjusters(
27 getClangStripOutputAdjuster(),
28 combineAdjusters(getClangSyntaxOnlyAdjuster(),
29 getClangStripDependencyFileAdjuster()));
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 AllTUsToolExecutor::AllTUsToolExecutor(
57 const CompilationDatabase &Compilations, unsigned ThreadCount,
58 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
59 : Compilations(Compilations), Results(new ThreadSafeToolResults),
60 Context(Results.get()), ThreadCount(ThreadCount) {}
62 AllTUsToolExecutor::AllTUsToolExecutor(
63 CommonOptionsParser Options, unsigned ThreadCount,
64 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
65 : OptionsParser(std::move(Options)),
66 Compilations(OptionsParser->getCompilations()),
67 Results(new ThreadSafeToolResults), Context(Results.get()),
68 ThreadCount(ThreadCount) {}
70 llvm::Error AllTUsToolExecutor::execute(
72 std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
75 return make_string_error("No action to execute.");
77 if (Actions.size() != 1)
78 return make_string_error(
79 "Only support executing exactly 1 action at this point.");
83 auto AppendError = [&](llvm::Twine Err) {
84 std::unique_lock<std::mutex> LockGuard(TUMutex);
85 ErrorMsg += Err.str();
88 auto Log = [&](llvm::Twine Msg) {
89 std::unique_lock<std::mutex> LockGuard(TUMutex);
90 llvm::errs() << Msg.str() << "\n";
93 auto Files = Compilations.getAllFiles();
94 // Add a counter to track the progress.
95 const std::string TotalNumStr = std::to_string(Files.size());
98 std::unique_lock<std::mutex> LockGuard(TUMutex);
102 auto &Action = Actions.front();
105 llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
108 for (std::string File : Files) {
110 [&](std::string Path) {
111 Log("[" + std::to_string(Count()) + "/" + TotalNumStr +
112 "] Processing file " + Path);
113 ClangTool Tool(Compilations, {Path});
114 Tool.appendArgumentsAdjuster(Action.second);
115 Tool.appendArgumentsAdjuster(getDefaultArgumentsAdjusters());
116 for (const auto &FileAndContent : OverlayFiles)
117 Tool.mapVirtualFile(FileAndContent.first(),
118 FileAndContent.second);
119 if (Tool.run(Action.first.get()))
120 AppendError(llvm::Twine("Failed to run action on ") + Path +
127 if (!ErrorMsg.empty())
128 return make_string_error(ErrorMsg);
130 return llvm::Error::success();
133 static llvm::cl::opt<unsigned> ExecutorConcurrency(
134 "execute-concurrency",
135 llvm::cl::desc("The number of threads used to process all files in "
136 "parallel. Set to 0 for hardware concurrency."),
139 class AllTUsToolExecutorPlugin : public ToolExecutorPlugin {
141 llvm::Expected<std::unique_ptr<ToolExecutor>>
142 create(CommonOptionsParser &OptionsParser) override {
143 if (OptionsParser.getSourcePathList().empty())
144 return make_string_error(
145 "[AllTUsToolExecutorPlugin] Please provide a directory/file path in "
146 "the compilation database.");
147 return llvm::make_unique<AllTUsToolExecutor>(std::move(OptionsParser),
148 ExecutorConcurrency);
152 static ToolExecutorPluginRegistry::Add<AllTUsToolExecutorPlugin>
153 X("all-TUs", "Runs FrontendActions on all TUs in the compilation database. "
154 "Tool results are stored in memory.");
156 // This anchor is used to force the linker to link in the generated object file
157 // and thus register the plugin.
158 volatile int AllTUsToolExecutorAnchorSource = 0;
160 } // end namespace tooling
161 } // end namespace clang