1 //===--- Execution.h - Executing clang frontend actions -*- C++ ---------*-===// 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 // This file defines framework for executing clang frontend actions. 10 // 11 // The framework can be extended to support different execution plans including 12 // standalone execution on the given TUs or parallel execution on all TUs in 13 // the codebase. 14 // 15 // In order to enable multiprocessing execution, tool actions are expected to 16 // output result into the ToolResults provided by the executor. The 17 // `ToolResults` is an interface that abstracts how results are stored e.g. 18 // in-memory for standalone execution or on-disk for large-scale execution. 19 // 20 // New executors can be registered as ToolExecutorPlugins via the 21 // `ToolExecutorPluginRegistry`. CLI tools can use 22 // `createExecutorFromCommandLineArgs` to create a specific registered executor 23 // according to the command-line arguments. 24 // 25 //===----------------------------------------------------------------------===// 26 27 #ifndef LLVM_CLANG_TOOLING_EXECUTION_H 28 #define LLVM_CLANG_TOOLING_EXECUTION_H 29 30 #include "clang/Tooling/CommonOptionsParser.h" 31 #include "clang/Tooling/Tooling.h" 32 #include "llvm/Support/Error.h" 33 #include "llvm/Support/Registry.h" 34 #include "llvm/Support/StringSaver.h" 35 36 namespace clang { 37 namespace tooling { 38 39 extern llvm::cl::opt<std::string> ExecutorName; 40 41 /// An abstraction for the result of a tool execution. For example, the 42 /// underlying result can be in-memory or on-disk. 43 /// 44 /// Results should be string key-value pairs. For example, a refactoring tool 45 /// can use source location as key and a replacement in YAML format as value. 46 class ToolResults { 47 public: 48 virtual ~ToolResults() = default; 49 virtual void addResult(StringRef Key, StringRef Value) = 0; 50 virtual std::vector<std::pair<llvm::StringRef, llvm::StringRef>> 51 AllKVResults() = 0; 52 virtual void forEachResult( 53 llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0; 54 }; 55 56 /// Stores the key-value results in memory. It maintains the lifetime of 57 /// the result. Clang tools using this class are expected to generate a small 58 /// set of different results, or a large set of duplicated results. 59 class InMemoryToolResults : public ToolResults { 60 public: InMemoryToolResults()61 InMemoryToolResults() : Strings(Arena) {} 62 void addResult(StringRef Key, StringRef Value) override; 63 std::vector<std::pair<llvm::StringRef, llvm::StringRef>> 64 AllKVResults() override; 65 void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)> 66 Callback) override; 67 68 private: 69 llvm::BumpPtrAllocator Arena; 70 llvm::UniqueStringSaver Strings; 71 72 std::vector<std::pair<llvm::StringRef, llvm::StringRef>> KVResults; 73 }; 74 75 /// The context of an execution, including the information about 76 /// compilation and results. 77 class ExecutionContext { 78 public: ~ExecutionContext()79 virtual ~ExecutionContext() {} 80 81 /// Initializes a context. This does not take ownership of `Results`. ExecutionContext(ToolResults * Results)82 explicit ExecutionContext(ToolResults *Results) : Results(Results) {} 83 84 /// Adds a KV pair to the result container of this execution. 85 void reportResult(StringRef Key, StringRef Value); 86 87 // Returns the source control system's revision number if applicable. 88 // Otherwise returns an empty string. getRevision()89 virtual std::string getRevision() { return ""; } 90 91 // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if 92 // applicable. getCorpus()93 virtual std::string getCorpus() { return ""; } 94 95 // Returns the currently processed compilation unit if available. getCurrentCompilationUnit()96 virtual std::string getCurrentCompilationUnit() { return ""; } 97 98 private: 99 ToolResults *Results; 100 }; 101 102 /// Interface for executing clang frontend actions. 103 /// 104 /// This can be extended to support running tool actions in different 105 /// execution mode, e.g. on a specific set of TUs or many TUs in parallel. 106 /// 107 /// New executors can be registered as ToolExecutorPlugins via the 108 /// `ToolExecutorPluginRegistry`. CLI tools can use 109 /// `createExecutorFromCommandLineArgs` to create a specific registered 110 /// executor according to the command-line arguments. 111 class ToolExecutor { 112 public: ~ToolExecutor()113 virtual ~ToolExecutor() {} 114 115 /// Returns the name of a specific executor. 116 virtual StringRef getExecutorName() const = 0; 117 118 /// Executes each action with a corresponding arguments adjuster. 119 virtual llvm::Error 120 execute(llvm::ArrayRef< 121 std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> 122 Actions) = 0; 123 124 /// Convenient functions for the above `execute`. 125 llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action); 126 /// Executes an action with an argument adjuster. 127 llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action, 128 ArgumentsAdjuster Adjuster); 129 130 /// Returns a reference to the execution context. 131 /// 132 /// This should be passed to tool callbacks, and tool callbacks should report 133 /// results via the returned context. 134 virtual ExecutionContext *getExecutionContext() = 0; 135 136 /// Returns a reference to the result container. 137 /// 138 /// NOTE: This should only be used after the execution finishes. Tool 139 /// callbacks should report results via `ExecutionContext` instead. 140 virtual ToolResults *getToolResults() = 0; 141 142 /// Map a virtual file to be used while running the tool. 143 /// 144 /// \param FilePath The path at which the content will be mapped. 145 /// \param Content A buffer of the file's content. 146 virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0; 147 }; 148 149 /// Interface for factories that create specific executors. This is also 150 /// used as a plugin to be registered into ToolExecutorPluginRegistry. 151 class ToolExecutorPlugin { 152 public: ~ToolExecutorPlugin()153 virtual ~ToolExecutorPlugin() {} 154 155 /// Create an `ToolExecutor`. 156 /// 157 /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds. 158 virtual llvm::Expected<std::unique_ptr<ToolExecutor>> 159 create(CommonOptionsParser &OptionsParser) = 0; 160 }; 161 162 /// This creates a ToolExecutor that is in the global registry based on 163 /// commandline arguments. 164 /// 165 /// This picks the right executor based on the `--executor` option. This parses 166 /// the commandline arguments with `CommonOptionsParser`, so caller does not 167 /// need to parse again. 168 /// 169 /// By default, this creates a `StandaloneToolExecutor` ("standalone") if 170 /// `--executor` is not provided. 171 llvm::Expected<std::unique_ptr<ToolExecutor>> 172 createExecutorFromCommandLineArgs(int &argc, const char **argv, 173 llvm::cl::OptionCategory &Category, 174 const char *Overview = nullptr); 175 176 namespace internal { 177 llvm::Expected<std::unique_ptr<ToolExecutor>> 178 createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, 179 llvm::cl::OptionCategory &Category, 180 const char *Overview = nullptr); 181 } // end namespace internal 182 183 } // end namespace tooling 184 } // end namespace clang 185 186 #endif // LLVM_CLANG_TOOLING_EXECUTION_H 187