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  /// Redirection for stdout, stderr, etc.
103  const StringRef **Redirects;
104
105  /// Whether we're compiling for diagnostic purposes.
106  bool ForDiagnostics;
107
108public:
109  Compilation(const Driver &D, const ToolChain &DefaultToolChain,
110              llvm::opt::InputArgList *Args,
111              llvm::opt::DerivedArgList *TranslatedArgs);
112  ~Compilation();
113
114  const Driver &getDriver() const { return TheDriver; }
115
116  const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
117
118  unsigned isOffloadingHostKind(Action::OffloadKind Kind) const {
119    return ActiveOffloadMask & Kind;
120  }
121
122  /// Iterator that visits device toolchains of a given kind.
123  typedef const std::multimap<Action::OffloadKind,
124                              const ToolChain *>::const_iterator
125      const_offload_toolchains_iterator;
126  typedef std::pair<const_offload_toolchains_iterator,
127                    const_offload_toolchains_iterator>
128      const_offload_toolchains_range;
129
130  template <Action::OffloadKind Kind>
131  const_offload_toolchains_range getOffloadToolChains() const {
132    return OrderedOffloadingToolchains.equal_range(Kind);
133  }
134
135  /// Return true if an offloading tool chain of a given kind exists.
136  template <Action::OffloadKind Kind> bool hasOffloadToolChain() const {
137    return OrderedOffloadingToolchains.find(Kind) !=
138           OrderedOffloadingToolchains.end();
139  }
140
141  /// Return an offload toolchain of the provided kind. Only one is expected to
142  /// exist.
143  template <Action::OffloadKind Kind>
144  const ToolChain *getSingleOffloadToolChain() const {
145    auto TCs = getOffloadToolChains<Kind>();
146
147    assert(TCs.first != TCs.second &&
148           "No tool chains of the selected kind exist!");
149    assert(std::next(TCs.first) == TCs.second &&
150           "More than one tool chain of the this kind exist.");
151    return TCs.first->second;
152  }
153
154  void addOffloadDeviceToolChain(const ToolChain *DeviceToolChain,
155                                 Action::OffloadKind OffloadKind) {
156    assert(OffloadKind != Action::OFK_Host && OffloadKind != Action::OFK_None &&
157           "This is not a device tool chain!");
158
159    // Update the host offload kind to also contain this kind.
160    ActiveOffloadMask |= OffloadKind;
161    OrderedOffloadingToolchains.insert(
162        std::make_pair(OffloadKind, DeviceToolChain));
163  }
164
165  const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
166
167  const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
168
169  llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
170
171  ActionList &getActions() { return Actions; }
172  const ActionList &getActions() const { return Actions; }
173
174  /// Creates a new Action owned by this Compilation.
175  ///
176  /// The new Action is *not* added to the list returned by getActions().
177  template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
178    T *RawPtr = new T(std::forward<Args>(Arg)...);
179    AllActions.push_back(std::unique_ptr<Action>(RawPtr));
180    return RawPtr;
181  }
182
183  JobList &getJobs() { return Jobs; }
184  const JobList &getJobs() const { return Jobs; }
185
186  void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); }
187
188  const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
189
190  const ArgStringMap &getResultFiles() const { return ResultFiles; }
191
192  const ArgStringMap &getFailureResultFiles() const {
193    return FailureResultFiles;
194  }
195
196  /// Returns the sysroot path.
197  StringRef getSysRoot() const;
198
199  /// getArgsForToolChain - Return the derived argument list for the
200  /// tool chain \p TC (or the default tool chain, if TC is not specified).
201  /// If a device offloading kind is specified, a translation specific for that
202  /// kind is performed, if any.
203  ///
204  /// \param BoundArch - The bound architecture name, or 0.
205  /// \param DeviceOffloadKind - The offload device kind that should be used in
206  /// the translation, if any.
207  const llvm::opt::DerivedArgList &
208  getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
209                      Action::OffloadKind DeviceOffloadKind);
210
211  /// addTempFile - Add a file to remove on exit, and returns its
212  /// argument.
213  const char *addTempFile(const char *Name) {
214    TempFiles.push_back(Name);
215    return Name;
216  }
217
218  /// addResultFile - Add a file to remove on failure, and returns its
219  /// argument.
220  const char *addResultFile(const char *Name, const JobAction *JA) {
221    ResultFiles[JA] = Name;
222    return Name;
223  }
224
225  /// addFailureResultFile - Add a file to remove if we crash, and returns its
226  /// argument.
227  const char *addFailureResultFile(const char *Name, const JobAction *JA) {
228    FailureResultFiles[JA] = Name;
229    return Name;
230  }
231
232  /// CleanupFile - Delete a given file.
233  ///
234  /// \param IssueErrors - Report failures as errors.
235  /// \return Whether the file was removed successfully.
236  bool CleanupFile(const char *File, bool IssueErrors = false) const;
237
238  /// CleanupFileList - Remove the files in the given list.
239  ///
240  /// \param IssueErrors - Report failures as errors.
241  /// \return Whether all files were removed successfully.
242  bool CleanupFileList(const llvm::opt::ArgStringList &Files,
243                       bool IssueErrors = false) const;
244
245  /// CleanupFileMap - Remove the files in the given map.
246  ///
247  /// \param JA - If specified, only delete the files associated with this
248  /// JobAction.  Otherwise, delete all files in the map.
249  /// \param IssueErrors - Report failures as errors.
250  /// \return Whether all files were removed successfully.
251  bool CleanupFileMap(const ArgStringMap &Files,
252                      const JobAction *JA,
253                      bool IssueErrors = false) const;
254
255  /// ExecuteCommand - Execute an actual command.
256  ///
257  /// \param FailingCommand - For non-zero results, this will be set to the
258  /// Command which failed, if any.
259  /// \return The result code of the subprocess.
260  int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
261
262  /// ExecuteJob - Execute a single job.
263  ///
264  /// \param FailingCommands - For non-zero results, this will be a vector of
265  /// failing commands and their associated result code.
266  void ExecuteJobs(
267      const JobList &Jobs,
268      SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
269
270  /// initCompilationForDiagnostics - Remove stale state and suppress output
271  /// so compilation can be reexecuted to generate additional diagnostic
272  /// information (e.g., preprocessed source(s)).
273  void initCompilationForDiagnostics();
274
275  /// Return true if we're compiling for diagnostics.
276  bool isForDiagnostics() const { return ForDiagnostics; }
277
278  /// Redirect - Redirect output of this compilation. Can only be done once.
279  ///
280  /// \param Redirects - array of pointers to paths. The array
281  /// should have a size of three. The inferior process's
282  /// stdin(0), stdout(1), and stderr(2) will be redirected to the
283  /// corresponding paths. This compilation instance becomes
284  /// the owner of Redirects and will delete the array and StringRef's.
285  void Redirect(const StringRef** Redirects);
286};
287
288} // end namespace driver
289} // end namespace clang
290
291#endif
292