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: |
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: |
79 | virtual ~ExecutionContext() {} |
80 | |
81 | /// Initializes a context. This does not take ownership of `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. |
89 | virtual std::string getRevision() { return ""; } |
90 | |
91 | // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if |
92 | // applicable. |
93 | virtual std::string getCorpus() { return ""; } |
94 | |
95 | // Returns the currently processed compilation unit if available. |
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: |
113 | virtual ~ToolExecutor() {} |
114 | |
115 | /// Returns the name of a specific executor. |
116 | virtual StringRef getExecutorName() const = 0; |
117 | |
118 | /// Should return true iff executor runs all actions in a single process. |
119 | /// Clients can use this signal to find out if they can collect results |
120 | /// in-memory (e.g. to avoid serialization costs of using ToolResults). |
121 | /// The single-process executors can still run multiple threads, but all |
122 | /// executions are guaranteed to share the same memory. |
123 | virtual bool isSingleProcess() const = 0; |
124 | |
125 | /// Executes each action with a corresponding arguments adjuster. |
126 | virtual llvm::Error |
127 | execute(llvm::ArrayRef< |
128 | std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> |
129 | Actions) = 0; |
130 | |
131 | /// Convenient functions for the above `execute`. |
132 | llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action); |
133 | /// Executes an action with an argument adjuster. |
134 | llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action, |
135 | ArgumentsAdjuster Adjuster); |
136 | |
137 | /// Returns a reference to the execution context. |
138 | /// |
139 | /// This should be passed to tool callbacks, and tool callbacks should report |
140 | /// results via the returned context. |
141 | virtual ExecutionContext *getExecutionContext() = 0; |
142 | |
143 | /// Returns a reference to the result container. |
144 | /// |
145 | /// NOTE: This should only be used after the execution finishes. Tool |
146 | /// callbacks should report results via `ExecutionContext` instead. |
147 | virtual ToolResults *getToolResults() = 0; |
148 | |
149 | /// Map a virtual file to be used while running the tool. |
150 | /// |
151 | /// \param FilePath The path at which the content will be mapped. |
152 | /// \param Content A buffer of the file's content. |
153 | virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0; |
154 | }; |
155 | |
156 | /// Interface for factories that create specific executors. This is also |
157 | /// used as a plugin to be registered into ToolExecutorPluginRegistry. |
158 | class ToolExecutorPlugin { |
159 | public: |
160 | virtual ~ToolExecutorPlugin() {} |
161 | |
162 | /// Create an `ToolExecutor`. |
163 | /// |
164 | /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds. |
165 | virtual llvm::Expected<std::unique_ptr<ToolExecutor>> |
166 | create(CommonOptionsParser &OptionsParser) = 0; |
167 | }; |
168 | |
169 | /// This creates a ToolExecutor that is in the global registry based on |
170 | /// commandline arguments. |
171 | /// |
172 | /// This picks the right executor based on the `--executor` option. This parses |
173 | /// the commandline arguments with `CommonOptionsParser`, so caller does not |
174 | /// need to parse again. |
175 | /// |
176 | /// By default, this creates a `StandaloneToolExecutor` ("standalone") if |
177 | /// `--executor` is not provided. |
178 | llvm::Expected<std::unique_ptr<ToolExecutor>> |
179 | createExecutorFromCommandLineArgs(int &argc, const char **argv, |
180 | llvm::cl::OptionCategory &Category, |
181 | const char *Overview = nullptr); |
182 | |
183 | namespace internal { |
184 | llvm::Expected<std::unique_ptr<ToolExecutor>> |
185 | createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, |
186 | llvm::cl::OptionCategory &Category, |
187 | const char *Overview = nullptr); |
188 | } // end namespace internal |
189 | |
190 | } // end namespace tooling |
191 | } // end namespace clang |
192 | |
193 | #endif // LLVM_CLANG_TOOLING_EXECUTION_H |
194 |