Compilation.h 12 KB

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