1//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_CLANG_DRIVER_COMPILATION_H
11#define LLVM_CLANG_DRIVER_COMPILATION_H
12
13#include "clang/Driver/Action.h"
14#include "clang/Driver/Job.h"
15#include "clang/Driver/Util.h"
16#include "llvm/ADT/DenseMap.h"
17#include <map>
18
19namespace llvm {
20namespace opt {
21  class DerivedArgList;
22  class InputArgList;
23}
24}
25
26namespace clang {
27namespace driver {
28  class Driver;
29  class JobList;
30  class ToolChain;
31
32/// Compilation - A set of tasks to perform for a single driver
33/// invocation.
34class Compilation {
35  /// The driver we were created by.
36  const Driver &TheDriver;
37
38  /// The default tool chain.
39  const ToolChain &DefaultToolChain;
40
41  /// A mask of all the programming models the host has to support in the
42  /// current compilation.
43  unsigned ActiveOffloadMask;
44
45  /// Array with the toolchains of offloading host and devices in the order they
46  /// were requested by the user. We are preserving that order in case the code
47  /// generation needs to derive a programming-model-specific semantic out of
48  /// it.
49  std::multimap<Action::OffloadKind, const ToolChain *>
50      OrderedOffloadingToolchains;
51
52  /// The original (untranslated) input argument list.
53  llvm::opt::InputArgList *Args;
54
55  /// The driver translated arguments. Note that toolchains may perform their
56  /// own argument translation.
57  llvm::opt::DerivedArgList *TranslatedArgs;
58
59  /// The list of actions we've created via MakeAction.  This is not accessible
60  /// to consumers; it's here just to manage ownership.
61  std::vector<std::unique_ptr<Action>> AllActions;
62
63  /// The list of actions.  This is maintained and modified by consumers, via
64  /// getActions().
65  ActionList Actions;
66
67  /// The root list of jobs.
68  JobList Jobs;
69
70  /// Cache of translated arguments for a particular tool chain, bound
71  /// architecture, and device offload kind.
72  struct TCArgsKey final {
73    const ToolChain *TC = nullptr;
74    StringRef BoundArch;
75    Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
76    bool operator<(const TCArgsKey &K) const {
77      if (TC < K.TC)
78        return true;
79      else if (TC == K.TC && BoundArch < K.BoundArch)
80        return true;
81      else if (TC == K.TC && BoundArch == K.BoundArch &&
82               DeviceOffloadKind < K.DeviceOffloadKind)
83        return true;
84      return false;
85    }
86    TCArgsKey(const ToolChain *TC, StringRef BoundArch,
87              Action::OffloadKind DeviceOffloadKind)
88        : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
89  };
90  std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
91
92  /// Temporary files which should be removed on exit.
93  llvm::opt::ArgStringList TempFiles;
94
95  /// Result files which should be removed on failure.
96  ArgStringMap ResultFiles;
97
98  /// Result files which are generated correctly on failure, and which should
99  /// only be removed if we crash.
100  ArgStringMap FailureResultFiles;
101
102  /// Optional redirection for stdin, stdout, stderr.
103  std::vector<Optional<StringRef>> Redirects;
104
105  /// Whether we're compiling for diagnostic purposes.
106  bool ForDiagnostics;
107
108  /// Whether an error during the parsing of the input args.
109  bool ContainsError;
110
111public:
112  Compilation(const Driver &D, const ToolChain &DefaultToolChain,
113              llvm::opt::InputArgList *Args,
114              llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError);
115  ~Compilation();
116
117  const Driver &getDriver() const { return TheDriver; }
118
119  const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
120
121  unsigned isOffloadingHostKind(Action::OffloadKind Kind) const {
122    return ActiveOffloadMask & Kind;
123  }
124
125  /// Iterator that visits device toolchains of a given kind.
126  typedef const std::multimap<Action::OffloadKind,
127                              const ToolChain *>::const_iterator
128      const_offload_toolchains_iterator;
129  typedef std::pair<const_offload_toolchains_iterator,
130                    const_offload_toolchains_iterator>
131      const_offload_toolchains_range;
132
133  template <Action::OffloadKind Kind>
134  const_offload_toolchains_range getOffloadToolChains() const {
135    return OrderedOffloadingToolchains.equal_range(Kind);
136  }
137
138  /// Return true if an offloading tool chain of a given kind exists.
139  template <Action::OffloadKind Kind> bool hasOffloadToolChain() const {
140    return OrderedOffloadingToolchains.find(Kind) !=
141           OrderedOffloadingToolchains.end();
142  }
143
144  /// Return an offload toolchain of the provided kind. Only one is expected to
145  /// exist.
146  template <Action::OffloadKind Kind>
147  const ToolChain *getSingleOffloadToolChain() const {
148    auto TCs = getOffloadToolChains<Kind>();
149
150    assert(TCs.first != TCs.second &&
151           "No tool chains of the selected kind exist!");
152    assert(std::next(TCs.first) == TCs.second &&
153           "More than one tool chain of the this kind exist.");
154    return TCs.first->second;
155  }
156
157  void addOffloadDeviceToolChain(const ToolChain *DeviceToolChain,
158                                 Action::OffloadKind OffloadKind) {
159    assert(OffloadKind != Action::OFK_Host && OffloadKind != Action::OFK_None &&
160           "This is not a device tool chain!");
161
162    // Update the host offload kind to also contain this kind.
163    ActiveOffloadMask |= OffloadKind;
164    OrderedOffloadingToolchains.insert(
165        std::make_pair(OffloadKind, DeviceToolChain));
166  }
167
168  const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
169
170  const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
171
172  llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
173
174  ActionList &getActions() { return Actions; }
175  const ActionList &getActions() const { return Actions; }
176
177  /// Creates a new Action owned by this Compilation.
178  ///
179  /// The new Action is *not* added to the list returned by getActions().
180  template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
181    T *RawPtr = new T(std::forward<Args>(Arg)...);
182    AllActions.push_back(std::unique_ptr<Action>(RawPtr));
183    return RawPtr;
184  }
185
186  JobList &getJobs() { return Jobs; }
187  const JobList &getJobs() const { return Jobs; }
188
189  void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); }
190
191  const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
192
193  const ArgStringMap &getResultFiles() const { return ResultFiles; }
194
195  const ArgStringMap &getFailureResultFiles() const {
196    return FailureResultFiles;
197  }
198
199  /// Returns the sysroot path.
200  StringRef getSysRoot() const;
201
202  /// getArgsForToolChain - Return the derived argument list for the
203  /// tool chain \p TC (or the default tool chain, if TC is not specified).
204  /// If a device offloading kind is specified, a translation specific for that
205  /// kind is performed, if any.
206  ///
207  /// \param BoundArch - The bound architecture name, or 0.
208  /// \param DeviceOffloadKind - The offload device kind that should be used in
209  /// the translation, if any.
210  const llvm::opt::DerivedArgList &
211  getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
212                      Action::OffloadKind DeviceOffloadKind);
213
214  /// addTempFile - Add a file to remove on exit, and returns its
215  /// argument.
216  const char *addTempFile(const char *Name) {
217    TempFiles.push_back(Name);
218    return Name;
219  }
220
221  /// addResultFile - Add a file to remove on failure, and returns its
222  /// argument.
223  const char *addResultFile(const char *Name, const JobAction *JA) {
224    ResultFiles[JA] = Name;
225    return Name;
226  }
227
228  /// addFailureResultFile - Add a file to remove if we crash, and returns its
229  /// argument.
230  const char *addFailureResultFile(const char *Name, const JobAction *JA) {
231    FailureResultFiles[JA] = Name;
232    return Name;
233  }
234
235  /// CleanupFile - Delete a given file.
236  ///
237  /// \param IssueErrors - Report failures as errors.
238  /// \return Whether the file was removed successfully.
239  bool CleanupFile(const char *File, bool IssueErrors = false) const;
240
241  /// CleanupFileList - Remove the files in the given list.
242  ///
243  /// \param IssueErrors - Report failures as errors.
244  /// \return Whether all files were removed successfully.
245  bool CleanupFileList(const llvm::opt::ArgStringList &Files,
246                       bool IssueErrors = false) const;
247
248  /// CleanupFileMap - Remove the files in the given map.
249  ///
250  /// \param JA - If specified, only delete the files associated with this
251  /// JobAction.  Otherwise, delete all files in the map.
252  /// \param IssueErrors - Report failures as errors.
253  /// \return Whether all files were removed successfully.
254  bool CleanupFileMap(const ArgStringMap &Files,
255                      const JobAction *JA,
256                      bool IssueErrors = false) const;
257
258  /// ExecuteCommand - Execute an actual command.
259  ///
260  /// \param FailingCommand - For non-zero results, this will be set to the
261  /// Command which failed, if any.
262  /// \return The result code of the subprocess.
263  int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
264
265  /// ExecuteJob - Execute a single job.
266  ///
267  /// \param FailingCommands - For non-zero results, this will be a vector of
268  /// failing commands and their associated result code.
269  void ExecuteJobs(
270      const JobList &Jobs,
271      SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
272
273  /// initCompilationForDiagnostics - Remove stale state and suppress output
274  /// so compilation can be reexecuted to generate additional diagnostic
275  /// information (e.g., preprocessed source(s)).
276  void initCompilationForDiagnostics();
277
278  /// Return true if we're compiling for diagnostics.
279  bool isForDiagnostics() const { return ForDiagnostics; }
280
281  /// Return whether an error during the parsing of the input args.
282  bool containsError() const { return ContainsError; }
283
284  /// Redirect - Redirect output of this compilation. Can only be done once.
285  ///
286  /// \param Redirects - array of optional paths. The array should have a size
287  /// of three. The inferior process's stdin(0), stdout(1), and stderr(2) will
288  /// be redirected to the corresponding paths, if provided (not llvm::None).
289  void Redirect(ArrayRef<Optional<StringRef>> Redirects);
290};
291
292} // end namespace driver
293} // end namespace clang
294
295#endif
296