1 //===- Compilation.h - Compilation Task Data Structure ----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_DRIVER_COMPILATION_H
10 #define LLVM_CLANG_DRIVER_COMPILATION_H
12 #include "clang/Basic/LLVM.h"
13 #include "clang/Driver/Action.h"
14 #include "clang/Driver/Job.h"
15 #include "clang/Driver/Util.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Option/Option.h"
43 /// Compilation - A set of tasks to perform for a single driver
46 /// The driver we were created by.
47 const Driver &TheDriver;
49 /// The default tool chain.
50 const ToolChain &DefaultToolChain;
52 /// A mask of all the programming models the host has to support in the
53 /// current compilation.
54 unsigned ActiveOffloadMask = 0;
56 /// Array with the toolchains of offloading host and devices in the order they
57 /// were requested by the user. We are preserving that order in case the code
58 /// generation needs to derive a programming-model-specific semantic out of
60 std::multimap<Action::OffloadKind, const ToolChain *>
61 OrderedOffloadingToolchains;
63 /// The original (untranslated) input argument list.
64 llvm::opt::InputArgList *Args;
66 /// The driver translated arguments. Note that toolchains may perform their
67 /// own argument translation.
68 llvm::opt::DerivedArgList *TranslatedArgs;
70 /// The list of actions we've created via MakeAction. This is not accessible
71 /// to consumers; it's here just to manage ownership.
72 std::vector<std::unique_ptr<Action>> AllActions;
74 /// The list of actions. This is maintained and modified by consumers, via
78 /// The root list of jobs.
81 /// Cache of translated arguments for a particular tool chain, bound
82 /// architecture, and device offload kind.
83 struct TCArgsKey final {
84 const ToolChain *TC = nullptr;
86 Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
88 TCArgsKey(const ToolChain *TC, StringRef BoundArch,
89 Action::OffloadKind DeviceOffloadKind)
90 : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
92 bool operator<(const TCArgsKey &K) const {
95 else if (TC == K.TC && BoundArch < K.BoundArch)
97 else if (TC == K.TC && BoundArch == K.BoundArch &&
98 DeviceOffloadKind < K.DeviceOffloadKind)
103 std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
105 /// Temporary files which should be removed on exit.
106 llvm::opt::ArgStringList TempFiles;
108 /// Result files which should be removed on failure.
109 ArgStringMap ResultFiles;
111 /// Result files which are generated correctly on failure, and which should
112 /// only be removed if we crash.
113 ArgStringMap FailureResultFiles;
115 /// Optional redirection for stdin, stdout, stderr.
116 std::vector<Optional<StringRef>> Redirects;
118 /// Whether we're compiling for diagnostic purposes.
119 bool ForDiagnostics = false;
121 /// Whether an error during the parsing of the input args.
124 /// Whether to keep temporary files regardless of -save-temps.
125 bool ForceKeepTempFiles = false;
128 Compilation(const Driver &D, const ToolChain &DefaultToolChain,
129 llvm::opt::InputArgList *Args,
130 llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError);
133 const Driver &getDriver() const { return TheDriver; }
135 const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
137 unsigned isOffloadingHostKind(Action::OffloadKind Kind) const {
138 return ActiveOffloadMask & Kind;
141 /// Iterator that visits device toolchains of a given kind.
142 using const_offload_toolchains_iterator =
143 const std::multimap<Action::OffloadKind,
144 const ToolChain *>::const_iterator;
145 using const_offload_toolchains_range =
146 std::pair<const_offload_toolchains_iterator,
147 const_offload_toolchains_iterator>;
149 template <Action::OffloadKind Kind>
150 const_offload_toolchains_range getOffloadToolChains() const {
151 return OrderedOffloadingToolchains.equal_range(Kind);
154 /// Return true if an offloading tool chain of a given kind exists.
155 template <Action::OffloadKind Kind> bool hasOffloadToolChain() const {
156 return OrderedOffloadingToolchains.find(Kind) !=
157 OrderedOffloadingToolchains.end();
160 /// Return an offload toolchain of the provided kind. Only one is expected to
162 template <Action::OffloadKind Kind>
163 const ToolChain *getSingleOffloadToolChain() const {
164 auto TCs = getOffloadToolChains<Kind>();
166 assert(TCs.first != TCs.second &&
167 "No tool chains of the selected kind exist!");
168 assert(std::next(TCs.first) == TCs.second &&
169 "More than one tool chain of the this kind exist.");
170 return TCs.first->second;
173 void addOffloadDeviceToolChain(const ToolChain *DeviceToolChain,
174 Action::OffloadKind OffloadKind) {
175 assert(OffloadKind != Action::OFK_Host && OffloadKind != Action::OFK_None &&
176 "This is not a device tool chain!");
178 // Update the host offload kind to also contain this kind.
179 ActiveOffloadMask |= OffloadKind;
180 OrderedOffloadingToolchains.insert(
181 std::make_pair(OffloadKind, DeviceToolChain));
184 const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
186 const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
188 llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
190 ActionList &getActions() { return Actions; }
191 const ActionList &getActions() const { return Actions; }
193 /// Creates a new Action owned by this Compilation.
195 /// The new Action is *not* added to the list returned by getActions().
196 template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
197 T *RawPtr = new T(std::forward<Args>(Arg)...);
198 AllActions.push_back(std::unique_ptr<Action>(RawPtr));
202 JobList &getJobs() { return Jobs; }
203 const JobList &getJobs() const { return Jobs; }
205 void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); }
207 const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
209 const ArgStringMap &getResultFiles() const { return ResultFiles; }
211 const ArgStringMap &getFailureResultFiles() const {
212 return FailureResultFiles;
215 /// Returns the sysroot path.
216 StringRef getSysRoot() const;
218 /// getArgsForToolChain - Return the derived argument list for the
219 /// tool chain \p TC (or the default tool chain, if TC is not specified).
220 /// If a device offloading kind is specified, a translation specific for that
221 /// kind is performed, if any.
223 /// \param BoundArch - The bound architecture name, or 0.
224 /// \param DeviceOffloadKind - The offload device kind that should be used in
225 /// the translation, if any.
226 const llvm::opt::DerivedArgList &
227 getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
228 Action::OffloadKind DeviceOffloadKind);
230 /// addTempFile - Add a file to remove on exit, and returns its
232 const char *addTempFile(const char *Name) {
233 TempFiles.push_back(Name);
237 /// addResultFile - Add a file to remove on failure, and returns its
239 const char *addResultFile(const char *Name, const JobAction *JA) {
240 ResultFiles[JA] = Name;
244 /// addFailureResultFile - Add a file to remove if we crash, and returns its
246 const char *addFailureResultFile(const char *Name, const JobAction *JA) {
247 FailureResultFiles[JA] = Name;
251 /// CleanupFile - Delete a given file.
253 /// \param IssueErrors - Report failures as errors.
254 /// \return Whether the file was removed successfully.
255 bool CleanupFile(const char *File, bool IssueErrors = false) const;
257 /// CleanupFileList - Remove the files in the given list.
259 /// \param IssueErrors - Report failures as errors.
260 /// \return Whether all files were removed successfully.
261 bool CleanupFileList(const llvm::opt::ArgStringList &Files,
262 bool IssueErrors = false) const;
264 /// CleanupFileMap - Remove the files in the given map.
266 /// \param JA - If specified, only delete the files associated with this
267 /// JobAction. Otherwise, delete all files in the map.
268 /// \param IssueErrors - Report failures as errors.
269 /// \return Whether all files were removed successfully.
270 bool CleanupFileMap(const ArgStringMap &Files,
272 bool IssueErrors = false) const;
274 /// ExecuteCommand - Execute an actual command.
276 /// \param FailingCommand - For non-zero results, this will be set to the
277 /// Command which failed, if any.
278 /// \return The result code of the subprocess.
279 int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
281 /// ExecuteJob - Execute a single job.
283 /// \param FailingCommands - For non-zero results, this will be a vector of
284 /// failing commands and their associated result code.
287 SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
289 /// initCompilationForDiagnostics - Remove stale state and suppress output
290 /// so compilation can be reexecuted to generate additional diagnostic
291 /// information (e.g., preprocessed source(s)).
292 void initCompilationForDiagnostics();
294 /// Return true if we're compiling for diagnostics.
295 bool isForDiagnostics() const { return ForDiagnostics; }
297 /// Return whether an error during the parsing of the input args.
298 bool containsError() const { return ContainsError; }
300 /// Redirect - Redirect output of this compilation. Can only be done once.
302 /// \param Redirects - array of optional paths. The array should have a size
303 /// of three. The inferior process's stdin(0), stdout(1), and stderr(2) will
304 /// be redirected to the corresponding paths, if provided (not llvm::None).
305 void Redirect(ArrayRef<Optional<StringRef>> Redirects);
308 } // namespace driver
311 #endif // LLVM_CLANG_DRIVER_COMPILATION_H