1e5dd7070Spatrick //===- lib/Tooling/Execution.cpp - Implements tool execution framework. ---===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick
9e5dd7070Spatrick #include "clang/Tooling/Execution.h"
10e5dd7070Spatrick #include "clang/Tooling/ToolExecutorPluginRegistry.h"
11e5dd7070Spatrick #include "clang/Tooling/Tooling.h"
12e5dd7070Spatrick
13e5dd7070Spatrick LLVM_INSTANTIATE_REGISTRY(clang::tooling::ToolExecutorPluginRegistry)
14e5dd7070Spatrick
15e5dd7070Spatrick namespace clang {
16e5dd7070Spatrick namespace tooling {
17e5dd7070Spatrick
18e5dd7070Spatrick llvm::cl::opt<std::string>
19e5dd7070Spatrick ExecutorName("executor", llvm::cl::desc("The name of the executor to use."),
20e5dd7070Spatrick llvm::cl::init("standalone"));
21e5dd7070Spatrick
addResult(StringRef Key,StringRef Value)22e5dd7070Spatrick void InMemoryToolResults::addResult(StringRef Key, StringRef Value) {
23e5dd7070Spatrick KVResults.push_back({Strings.save(Key), Strings.save(Value)});
24e5dd7070Spatrick }
25e5dd7070Spatrick
26e5dd7070Spatrick std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
AllKVResults()27e5dd7070Spatrick InMemoryToolResults::AllKVResults() {
28e5dd7070Spatrick return KVResults;
29e5dd7070Spatrick }
30e5dd7070Spatrick
forEachResult(llvm::function_ref<void (StringRef Key,StringRef Value)> Callback)31e5dd7070Spatrick void InMemoryToolResults::forEachResult(
32e5dd7070Spatrick llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) {
33e5dd7070Spatrick for (const auto &KV : KVResults) {
34e5dd7070Spatrick Callback(KV.first, KV.second);
35e5dd7070Spatrick }
36e5dd7070Spatrick }
37e5dd7070Spatrick
reportResult(StringRef Key,StringRef Value)38e5dd7070Spatrick void ExecutionContext::reportResult(StringRef Key, StringRef Value) {
39e5dd7070Spatrick Results->addResult(Key, Value);
40e5dd7070Spatrick }
41e5dd7070Spatrick
42e5dd7070Spatrick llvm::Error
execute(std::unique_ptr<FrontendActionFactory> Action)43e5dd7070Spatrick ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action) {
44e5dd7070Spatrick return execute(std::move(Action), ArgumentsAdjuster());
45e5dd7070Spatrick }
46e5dd7070Spatrick
execute(std::unique_ptr<FrontendActionFactory> Action,ArgumentsAdjuster Adjuster)47e5dd7070Spatrick llvm::Error ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action,
48e5dd7070Spatrick ArgumentsAdjuster Adjuster) {
49e5dd7070Spatrick std::vector<
50e5dd7070Spatrick std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
51e5dd7070Spatrick Actions;
52e5dd7070Spatrick Actions.emplace_back(std::move(Action), std::move(Adjuster));
53e5dd7070Spatrick return execute(Actions);
54e5dd7070Spatrick }
55e5dd7070Spatrick
56e5dd7070Spatrick namespace internal {
57e5dd7070Spatrick llvm::Expected<std::unique_ptr<ToolExecutor>>
createExecutorFromCommandLineArgsImpl(int & argc,const char ** argv,llvm::cl::OptionCategory & Category,const char * Overview)58e5dd7070Spatrick createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
59e5dd7070Spatrick llvm::cl::OptionCategory &Category,
60e5dd7070Spatrick const char *Overview) {
61e5dd7070Spatrick auto OptionsParser =
62e5dd7070Spatrick CommonOptionsParser::create(argc, argv, Category, llvm::cl::ZeroOrMore,
63e5dd7070Spatrick /*Overview=*/Overview);
64e5dd7070Spatrick if (!OptionsParser)
65e5dd7070Spatrick return OptionsParser.takeError();
66*ec727ea7Spatrick for (const auto &TEPlugin : ToolExecutorPluginRegistry::entries()) {
67*ec727ea7Spatrick if (TEPlugin.getName() != ExecutorName) {
68e5dd7070Spatrick continue;
69e5dd7070Spatrick }
70*ec727ea7Spatrick std::unique_ptr<ToolExecutorPlugin> Plugin(TEPlugin.instantiate());
71e5dd7070Spatrick llvm::Expected<std::unique_ptr<ToolExecutor>> Executor =
72e5dd7070Spatrick Plugin->create(*OptionsParser);
73e5dd7070Spatrick if (!Executor) {
74e5dd7070Spatrick return llvm::make_error<llvm::StringError>(
75*ec727ea7Spatrick llvm::Twine("Failed to create '") + TEPlugin.getName() +
76e5dd7070Spatrick "': " + llvm::toString(Executor.takeError()) + "\n",
77e5dd7070Spatrick llvm::inconvertibleErrorCode());
78e5dd7070Spatrick }
79e5dd7070Spatrick return std::move(*Executor);
80e5dd7070Spatrick }
81e5dd7070Spatrick return llvm::make_error<llvm::StringError>(
82e5dd7070Spatrick llvm::Twine("Executor \"") + ExecutorName + "\" is not registered.",
83e5dd7070Spatrick llvm::inconvertibleErrorCode());
84e5dd7070Spatrick }
85e5dd7070Spatrick } // end namespace internal
86e5dd7070Spatrick
87e5dd7070Spatrick llvm::Expected<std::unique_ptr<ToolExecutor>>
createExecutorFromCommandLineArgs(int & argc,const char ** argv,llvm::cl::OptionCategory & Category,const char * Overview)88e5dd7070Spatrick createExecutorFromCommandLineArgs(int &argc, const char **argv,
89e5dd7070Spatrick llvm::cl::OptionCategory &Category,
90e5dd7070Spatrick const char *Overview) {
91e5dd7070Spatrick return internal::createExecutorFromCommandLineArgsImpl(argc, argv, Category,
92e5dd7070Spatrick Overview);
93e5dd7070Spatrick }
94e5dd7070Spatrick
95e5dd7070Spatrick // This anchor is used to force the linker to link in the generated object file
96e5dd7070Spatrick // and thus register the StandaloneToolExecutorPlugin etc.
97e5dd7070Spatrick extern volatile int StandaloneToolExecutorAnchorSource;
98e5dd7070Spatrick extern volatile int AllTUsToolExecutorAnchorSource;
99e5dd7070Spatrick static int LLVM_ATTRIBUTE_UNUSED StandaloneToolExecutorAnchorDest =
100e5dd7070Spatrick StandaloneToolExecutorAnchorSource;
101e5dd7070Spatrick static int LLVM_ATTRIBUTE_UNUSED AllTUsToolExecutorAnchorDest =
102e5dd7070Spatrick AllTUsToolExecutorAnchorSource;
103e5dd7070Spatrick
104e5dd7070Spatrick } // end namespace tooling
105e5dd7070Spatrick } // end namespace clang
106