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