summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEric Liu <ioeric@google.com>2017-10-26 10:38:14 +0000
committerEric Liu <ioeric@google.com>2017-10-26 10:38:14 +0000
commite7a10639e3b56be55f7fa5bf89d82d7b42e6fe3c (patch)
tree9f6ba36aa382414e7c4bdfbc13420e727e0c3a14 /lib
parent9bc9ee5d23d2b0b3c18dd86ce6b8aeae0aeb1bde (diff)
downloadclang-e7a10639e3b56be55f7fa5bf89d82d7b42e6fe3c.tar.gz
[Tooling] A new framework for executing clang frontend actions.
Summary: This defines a `clang::tooling::ToolExecutor` interface that can be extended to support different execution plans including standalone execution on a given set of TUs or parallel execution on all TUs in a codebase. In order to enable multiprocessing execution, tool actions are expected to output result into a `ToolResults` interface provided by executors. The `ToolResults` interface abstracts how results are stored e.g. in-memory for standalone executions or on-disk for large-scale execution. New executors can be registered as `ToolExecutorPlugin`s via the `ToolExecutorPluginRegistry`. CLI tools can use `createExecutorFromCommandLineArgs` to create a specific registered executor according to the command-line arguments. This patch also implements `StandaloneToolExecutor` which has the same behavior as the current `ClangTool` interface, i.e. execute frontend actions on a given set of TUs. At this point, it's simply a wrapper around `ClangTool` at this point. This is still experimental but expected to replace the existing `ClangTool` interface so that specific tools would not need to worry about execution. Reviewers: klimek, arphaman, hokein, sammccall Reviewed By: klimek Subscribers: cfe-commits, djasper, mgorny, omtcyfz Differential Revision: https://reviews.llvm.org/D34272 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316653 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Tooling/ArgumentsAdjusters.cpp4
-rw-r--r--lib/Tooling/CMakeLists.txt2
-rw-r--r--lib/Tooling/CommonOptionsParser.cpp8
-rw-r--r--lib/Tooling/Execution.cpp89
-rw-r--r--lib/Tooling/StandaloneExecution.cpp91
-rw-r--r--lib/Tooling/Tooling.cpp7
6 files changed, 193 insertions, 8 deletions
diff --git a/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp
index ac9fd3c5ca..962ea45258 100644
--- a/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/lib/Tooling/ArgumentsAdjusters.cpp
@@ -96,6 +96,10 @@ ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second) {
+ if (!First)
+ return Second;
+ if (!Second)
+ return First;
return [First, Second](const CommandLineArguments &Args, StringRef File) {
return Second(First(Args, File), File);
};
diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index 32a1935b3f..ee681bbb45 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -11,11 +11,13 @@ add_clang_library(clangTooling
ArgumentsAdjusters.cpp
CommonOptionsParser.cpp
CompilationDatabase.cpp
+ Execution.cpp
FileMatchTrie.cpp
FixIt.cpp
JSONCompilationDatabase.cpp
Refactoring.cpp
RefactoringCallbacks.cpp
+ StandaloneExecution.cpp
Tooling.cpp
DEPENDS
diff --git a/lib/Tooling/CommonOptionsParser.cpp b/lib/Tooling/CommonOptionsParser.cpp
index 9ad15cc8b2..74ad4e83ee 100644
--- a/lib/Tooling/CommonOptionsParser.cpp
+++ b/lib/Tooling/CommonOptionsParser.cpp
@@ -147,10 +147,12 @@ llvm::Error CommonOptionsParser::init(
auto AdjustingCompilations =
llvm::make_unique<ArgumentsAdjustingCompilations>(
std::move(Compilations));
- AdjustingCompilations->appendArgumentsAdjuster(
- getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN));
- AdjustingCompilations->appendArgumentsAdjuster(
+ Adjuster =
+ getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN);
+ Adjuster = combineAdjusters(
+ std::move(Adjuster),
getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
+ AdjustingCompilations->appendArgumentsAdjuster(Adjuster);
Compilations = std::move(AdjustingCompilations);
return llvm::Error::success();
}
diff --git a/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp
new file mode 100644
index 0000000000..1a078ef7e1
--- /dev/null
+++ b/lib/Tooling/Execution.cpp
@@ -0,0 +1,89 @@
+//===- lib/Tooling/Execution.cpp - Implements tool execution framework. ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Execution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+#include "clang/Tooling/Tooling.h"
+
+LLVM_INSTANTIATE_REGISTRY(clang::tooling::ToolExecutorPluginRegistry)
+
+namespace clang {
+namespace tooling {
+
+static llvm::cl::opt<std::string>
+ ExecutorName("executor", llvm::cl::desc("The name of the executor to use."),
+ llvm::cl::init("standalone"));
+
+void InMemoryToolResults::addResult(StringRef Key, StringRef Value) {
+ KVResults.push_back({Key.str(), Value.str()});
+}
+
+std::vector<std::pair<std::string, std::string>>
+InMemoryToolResults::AllKVResults() {
+ return KVResults;
+}
+
+void InMemoryToolResults::forEachResult(
+ llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) {
+ for (const auto &KV : KVResults) {
+ Callback(KV.first, KV.second);
+ }
+}
+
+void ExecutionContext::reportResult(StringRef Key, StringRef Value) {
+ Results->addResult(Key, Value);
+}
+
+llvm::Error
+ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action) {
+ return execute(std::move(Action), ArgumentsAdjuster());
+}
+
+llvm::Error ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action,
+ ArgumentsAdjuster Adjuster) {
+ std::vector<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions;
+ Actions.emplace_back(std::move(Action), std::move(Adjuster));
+ return execute(Actions);
+}
+
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgs(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview) {
+ auto OptionsParser =
+ CommonOptionsParser::create(argc, argv, Category, llvm::cl::ZeroOrMore,
+ /*Overview=*/nullptr);
+ if (!OptionsParser)
+ return OptionsParser.takeError();
+ for (auto I = ToolExecutorPluginRegistry::begin(),
+ E = ToolExecutorPluginRegistry::end();
+ I != E; ++I) {
+ if (I->getName() != ExecutorName) {
+ continue;
+ }
+ std::unique_ptr<ToolExecutorPlugin> Plugin(I->instantiate());
+ llvm::Expected<std::unique_ptr<ToolExecutor>> Executor =
+ Plugin->create(*OptionsParser);
+ if (!Executor) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("Failed to create '") + I->getName() +
+ "': " + llvm::toString(Executor.takeError()) + "\n",
+ llvm::inconvertibleErrorCode());
+ }
+ return std::move(*Executor);
+ }
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("Executor \"") + ExecutorName + "\" is not registered.",
+ llvm::inconvertibleErrorCode());
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/StandaloneExecution.cpp b/lib/Tooling/StandaloneExecution.cpp
new file mode 100644
index 0000000000..aade40b62a
--- /dev/null
+++ b/lib/Tooling/StandaloneExecution.cpp
@@ -0,0 +1,91 @@
+//===- lib/Tooling/Execution.cpp - Standalone clang action execution. -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/StandaloneExecution.h"
+#include "clang/Tooling/ToolExecutorPluginRegistry.h"
+
+namespace clang {
+namespace tooling {
+
+static llvm::Error make_string_error(const llvm::Twine &Message) {
+ return llvm::make_error<llvm::StringError>(Message,
+ llvm::inconvertibleErrorCode());
+}
+
+const char *StandaloneToolExecutor::ExecutorName = "StandaloneToolExecutor";
+
+static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
+ return combineAdjusters(
+ getClangStripOutputAdjuster(),
+ combineAdjusters(getClangSyntaxOnlyAdjuster(),
+ getClangStripDependencyFileAdjuster()));
+}
+
+StandaloneToolExecutor::StandaloneToolExecutor(
+ const CompilationDatabase &Compilations,
+ llvm::ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : Tool(Compilations, SourcePaths), Context(&Results),
+ ArgsAdjuster(getDefaultArgumentsAdjusters()) {
+ // Use self-defined default argument adjusters instead of the default
+ // adjusters that come with the old `ClangTool`.
+ Tool.clearArgumentsAdjusters();
+}
+
+StandaloneToolExecutor::StandaloneToolExecutor(
+ CommonOptionsParser Options,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps)
+ : OptionsParser(std::move(Options)),
+ Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(),
+ PCHContainerOps),
+ Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
+ Tool.clearArgumentsAdjusters();
+}
+
+llvm::Error StandaloneToolExecutor::execute(
+ llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) {
+ if (Actions.empty())
+ return make_string_error("No action to execute.");
+
+ if (Actions.size() != 1)
+ return make_string_error(
+ "Only support executing exactly 1 action at this point.");
+
+ auto &Action = Actions.front();
+ Tool.appendArgumentsAdjuster(Action.second);
+ Tool.appendArgumentsAdjuster(ArgsAdjuster);
+ if (int Ret = Tool.run(Action.first.get()))
+ return make_string_error("Failed to run action.");
+
+ return llvm::Error::success();
+}
+
+class StandaloneToolExecutorPlugin : public ToolExecutorPlugin {
+public:
+ llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) override {
+ if (OptionsParser.getSourcePathList().empty())
+ return make_string_error(
+ "[StandaloneToolExecutorPlugin] No positional argument found.");
+ return llvm::make_unique<StandaloneToolExecutor>(std::move(OptionsParser));
+ }
+};
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the plugin.
+volatile int ToolExecutorPluginAnchorSource = 0;
+
+static ToolExecutorPluginRegistry::Add<StandaloneToolExecutorPlugin>
+ X("standalone", "Runs FrontendActions on a set of files provided "
+ "via positional arguments.");
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index df9d7df694..4fbfa4f004 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -29,6 +29,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -347,11 +348,7 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
}
void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) {
- if (ArgsAdjuster)
- ArgsAdjuster =
- combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
- else
- ArgsAdjuster = std::move(Adjuster);
+ ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster));
}
void ClangTool::clearArgumentsAdjusters() {