Action.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Action.h - Abstract compilation steps --------------------*- 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_ACTION_H
  14. #define LLVM_CLANG_DRIVER_ACTION_H
  15. #include "clang/Basic/LLVM.h"
  16. #include "clang/Driver/Types.h"
  17. #include "clang/Driver/Util.h"
  18. #include "llvm/ADT/ArrayRef.h"
  19. #include "llvm/ADT/STLExtras.h"
  20. #include "llvm/ADT/SmallVector.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/ADT/iterator_range.h"
  23. #include <string>
  24. namespace llvm {
  25. namespace opt {
  26. class Arg;
  27. } // namespace opt
  28. } // namespace llvm
  29. namespace clang {
  30. namespace driver {
  31. class ToolChain;
  32. /// Action - Represent an abstract compilation step to perform.
  33. ///
  34. /// An action represents an edge in the compilation graph; typically
  35. /// it is a job to transform an input using some tool.
  36. ///
  37. /// The current driver is hard wired to expect actions which produce a
  38. /// single primary output, at least in terms of controlling the
  39. /// compilation. Actions can produce auxiliary files, but can only
  40. /// produce a single output to feed into subsequent actions.
  41. ///
  42. /// Actions are usually owned by a Compilation, which creates new
  43. /// actions via MakeAction().
  44. class Action {
  45. public:
  46. using size_type = ActionList::size_type;
  47. using input_iterator = ActionList::iterator;
  48. using input_const_iterator = ActionList::const_iterator;
  49. using input_range = llvm::iterator_range<input_iterator>;
  50. using input_const_range = llvm::iterator_range<input_const_iterator>;
  51. enum ActionClass {
  52. InputClass = 0,
  53. BindArchClass,
  54. OffloadClass,
  55. PreprocessJobClass,
  56. PrecompileJobClass,
  57. ExtractAPIJobClass,
  58. AnalyzeJobClass,
  59. MigrateJobClass,
  60. CompileJobClass,
  61. BackendJobClass,
  62. AssembleJobClass,
  63. LinkJobClass,
  64. IfsMergeJobClass,
  65. LipoJobClass,
  66. DsymutilJobClass,
  67. VerifyDebugInfoJobClass,
  68. VerifyPCHJobClass,
  69. OffloadBundlingJobClass,
  70. OffloadUnbundlingJobClass,
  71. OffloadPackagerJobClass,
  72. LinkerWrapperJobClass,
  73. StaticLibJobClass,
  74. JobClassFirst = PreprocessJobClass,
  75. JobClassLast = StaticLibJobClass
  76. };
  77. // The offloading kind determines if this action is binded to a particular
  78. // programming model. Each entry reserves one bit. We also have a special kind
  79. // to designate the host offloading tool chain.
  80. enum OffloadKind {
  81. OFK_None = 0x00,
  82. // The host offloading tool chain.
  83. OFK_Host = 0x01,
  84. // The device offloading tool chains - one bit for each programming model.
  85. OFK_Cuda = 0x02,
  86. OFK_OpenMP = 0x04,
  87. OFK_HIP = 0x08,
  88. };
  89. static const char *getClassName(ActionClass AC);
  90. private:
  91. ActionClass Kind;
  92. /// The output type of this action.
  93. types::ID Type;
  94. ActionList Inputs;
  95. /// Flag that is set to true if this action can be collapsed with others
  96. /// actions that depend on it. This is true by default and set to false when
  97. /// the action is used by two different tool chains, which is enabled by the
  98. /// offloading support implementation.
  99. bool CanBeCollapsedWithNextDependentAction = true;
  100. protected:
  101. ///
  102. /// Offload information.
  103. ///
  104. /// The host offloading kind - a combination of kinds encoded in a mask.
  105. /// Multiple programming models may be supported simultaneously by the same
  106. /// host.
  107. unsigned ActiveOffloadKindMask = 0u;
  108. /// Offloading kind of the device.
  109. OffloadKind OffloadingDeviceKind = OFK_None;
  110. /// The Offloading architecture associated with this action.
  111. const char *OffloadingArch = nullptr;
  112. /// The Offloading toolchain associated with this device action.
  113. const ToolChain *OffloadingToolChain = nullptr;
  114. Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {}
  115. Action(ActionClass Kind, Action *Input, types::ID Type)
  116. : Action(Kind, ActionList({Input}), Type) {}
  117. Action(ActionClass Kind, Action *Input)
  118. : Action(Kind, ActionList({Input}), Input->getType()) {}
  119. Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
  120. : Kind(Kind), Type(Type), Inputs(Inputs) {}
  121. public:
  122. virtual ~Action();
  123. const char *getClassName() const { return Action::getClassName(getKind()); }
  124. ActionClass getKind() const { return Kind; }
  125. types::ID getType() const { return Type; }
  126. ActionList &getInputs() { return Inputs; }
  127. const ActionList &getInputs() const { return Inputs; }
  128. size_type size() const { return Inputs.size(); }
  129. input_iterator input_begin() { return Inputs.begin(); }
  130. input_iterator input_end() { return Inputs.end(); }
  131. input_range inputs() { return input_range(input_begin(), input_end()); }
  132. input_const_iterator input_begin() const { return Inputs.begin(); }
  133. input_const_iterator input_end() const { return Inputs.end(); }
  134. input_const_range inputs() const {
  135. return input_const_range(input_begin(), input_end());
  136. }
  137. /// Mark this action as not legal to collapse.
  138. void setCannotBeCollapsedWithNextDependentAction() {
  139. CanBeCollapsedWithNextDependentAction = false;
  140. }
  141. /// Return true if this function can be collapsed with others.
  142. bool isCollapsingWithNextDependentActionLegal() const {
  143. return CanBeCollapsedWithNextDependentAction;
  144. }
  145. /// Return a string containing the offload kind of the action.
  146. std::string getOffloadingKindPrefix() const;
  147. /// Return a string that can be used as prefix in order to generate unique
  148. /// files for each offloading kind. By default, no prefix is used for
  149. /// non-device kinds, except if \a CreatePrefixForHost is set.
  150. static std::string
  151. GetOffloadingFileNamePrefix(OffloadKind Kind,
  152. StringRef NormalizedTriple,
  153. bool CreatePrefixForHost = false);
  154. /// Return a string containing a offload kind name.
  155. static StringRef GetOffloadKindName(OffloadKind Kind);
  156. /// Set the device offload info of this action and propagate it to its
  157. /// dependences.
  158. void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
  159. const ToolChain *OToolChain);
  160. /// Append the host offload info of this action and propagate it to its
  161. /// dependences.
  162. void propagateHostOffloadInfo(unsigned OKinds, const char *OArch);
  163. void setHostOffloadInfo(unsigned OKinds, const char *OArch) {
  164. ActiveOffloadKindMask |= OKinds;
  165. OffloadingArch = OArch;
  166. }
  167. /// Set the offload info of this action to be the same as the provided action,
  168. /// and propagate it to its dependences.
  169. void propagateOffloadInfo(const Action *A);
  170. unsigned getOffloadingHostActiveKinds() const {
  171. return ActiveOffloadKindMask;
  172. }
  173. OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; }
  174. const char *getOffloadingArch() const { return OffloadingArch; }
  175. const ToolChain *getOffloadingToolChain() const {
  176. return OffloadingToolChain;
  177. }
  178. /// Check if this action have any offload kinds. Note that host offload kinds
  179. /// are only set if the action is a dependence to a host offload action.
  180. bool isHostOffloading(unsigned int OKind) const {
  181. return ActiveOffloadKindMask & OKind;
  182. }
  183. bool isDeviceOffloading(OffloadKind OKind) const {
  184. return OffloadingDeviceKind == OKind;
  185. }
  186. bool isOffloading(OffloadKind OKind) const {
  187. return isHostOffloading(OKind) || isDeviceOffloading(OKind);
  188. }
  189. };
  190. class InputAction : public Action {
  191. const llvm::opt::Arg &Input;
  192. std::string Id;
  193. virtual void anchor();
  194. public:
  195. InputAction(const llvm::opt::Arg &Input, types::ID Type,
  196. StringRef Id = StringRef());
  197. const llvm::opt::Arg &getInputArg() const { return Input; }
  198. void setId(StringRef _Id) { Id = _Id.str(); }
  199. StringRef getId() const { return Id; }
  200. static bool classof(const Action *A) {
  201. return A->getKind() == InputClass;
  202. }
  203. };
  204. class BindArchAction : public Action {
  205. virtual void anchor();
  206. /// The architecture to bind, or 0 if the default architecture
  207. /// should be bound.
  208. StringRef ArchName;
  209. public:
  210. BindArchAction(Action *Input, StringRef ArchName);
  211. StringRef getArchName() const { return ArchName; }
  212. static bool classof(const Action *A) {
  213. return A->getKind() == BindArchClass;
  214. }
  215. };
  216. /// An offload action combines host or/and device actions according to the
  217. /// programming model implementation needs and propagates the offloading kind to
  218. /// its dependences.
  219. class OffloadAction final : public Action {
  220. virtual void anchor();
  221. public:
  222. /// Type used to communicate device actions. It associates bound architecture,
  223. /// toolchain, and offload kind to each action.
  224. class DeviceDependences final {
  225. public:
  226. using ToolChainList = SmallVector<const ToolChain *, 3>;
  227. using BoundArchList = SmallVector<const char *, 3>;
  228. using OffloadKindList = SmallVector<OffloadKind, 3>;
  229. private:
  230. // Lists that keep the information for each dependency. All the lists are
  231. // meant to be updated in sync. We are adopting separate lists instead of a
  232. // list of structs, because that simplifies forwarding the actions list to
  233. // initialize the inputs of the base Action class.
  234. /// The dependence actions.
  235. ActionList DeviceActions;
  236. /// The offloading toolchains that should be used with the action.
  237. ToolChainList DeviceToolChains;
  238. /// The architectures that should be used with this action.
  239. BoundArchList DeviceBoundArchs;
  240. /// The offload kind of each dependence.
  241. OffloadKindList DeviceOffloadKinds;
  242. public:
  243. /// Add an action along with the associated toolchain, bound arch, and
  244. /// offload kind.
  245. void add(Action &A, const ToolChain &TC, const char *BoundArch,
  246. OffloadKind OKind);
  247. /// Add an action along with the associated toolchain, bound arch, and
  248. /// offload kinds.
  249. void add(Action &A, const ToolChain &TC, const char *BoundArch,
  250. unsigned OffloadKindMask);
  251. /// Get each of the individual arrays.
  252. const ActionList &getActions() const { return DeviceActions; }
  253. const ToolChainList &getToolChains() const { return DeviceToolChains; }
  254. const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; }
  255. const OffloadKindList &getOffloadKinds() const {
  256. return DeviceOffloadKinds;
  257. }
  258. };
  259. /// Type used to communicate host actions. It associates bound architecture,
  260. /// toolchain, and offload kinds to the host action.
  261. class HostDependence final {
  262. /// The dependence action.
  263. Action &HostAction;
  264. /// The offloading toolchain that should be used with the action.
  265. const ToolChain &HostToolChain;
  266. /// The architectures that should be used with this action.
  267. const char *HostBoundArch = nullptr;
  268. /// The offload kind of each dependence.
  269. unsigned HostOffloadKinds = 0u;
  270. public:
  271. HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
  272. const unsigned OffloadKinds)
  273. : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch),
  274. HostOffloadKinds(OffloadKinds) {}
  275. /// Constructor version that obtains the offload kinds from the device
  276. /// dependencies.
  277. HostDependence(Action &A, const ToolChain &TC, const char *BoundArch,
  278. const DeviceDependences &DDeps);
  279. Action *getAction() const { return &HostAction; }
  280. const ToolChain *getToolChain() const { return &HostToolChain; }
  281. const char *getBoundArch() const { return HostBoundArch; }
  282. unsigned getOffloadKinds() const { return HostOffloadKinds; }
  283. };
  284. using OffloadActionWorkTy =
  285. llvm::function_ref<void(Action *, const ToolChain *, const char *)>;
  286. private:
  287. /// The host offloading toolchain that should be used with the action.
  288. const ToolChain *HostTC = nullptr;
  289. /// The tool chains associated with the list of actions.
  290. DeviceDependences::ToolChainList DevToolChains;
  291. public:
  292. OffloadAction(const HostDependence &HDep);
  293. OffloadAction(const DeviceDependences &DDeps, types::ID Ty);
  294. OffloadAction(const HostDependence &HDep, const DeviceDependences &DDeps);
  295. /// Execute the work specified in \a Work on the host dependence.
  296. void doOnHostDependence(const OffloadActionWorkTy &Work) const;
  297. /// Execute the work specified in \a Work on each device dependence.
  298. void doOnEachDeviceDependence(const OffloadActionWorkTy &Work) const;
  299. /// Execute the work specified in \a Work on each dependence.
  300. void doOnEachDependence(const OffloadActionWorkTy &Work) const;
  301. /// Execute the work specified in \a Work on each host or device dependence if
  302. /// \a IsHostDependenceto is true or false, respectively.
  303. void doOnEachDependence(bool IsHostDependence,
  304. const OffloadActionWorkTy &Work) const;
  305. /// Return true if the action has a host dependence.
  306. bool hasHostDependence() const;
  307. /// Return the host dependence of this action. This function is only expected
  308. /// to be called if the host dependence exists.
  309. Action *getHostDependence() const;
  310. /// Return true if the action has a single device dependence. If \a
  311. /// DoNotConsiderHostActions is set, ignore the host dependence, if any, while
  312. /// accounting for the number of dependences.
  313. bool hasSingleDeviceDependence(bool DoNotConsiderHostActions = false) const;
  314. /// Return the single device dependence of this action. This function is only
  315. /// expected to be called if a single device dependence exists. If \a
  316. /// DoNotConsiderHostActions is set, a host dependence is allowed.
  317. Action *
  318. getSingleDeviceDependence(bool DoNotConsiderHostActions = false) const;
  319. static bool classof(const Action *A) { return A->getKind() == OffloadClass; }
  320. };
  321. class JobAction : public Action {
  322. virtual void anchor();
  323. protected:
  324. JobAction(ActionClass Kind, Action *Input, types::ID Type);
  325. JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
  326. public:
  327. static bool classof(const Action *A) {
  328. return (A->getKind() >= JobClassFirst &&
  329. A->getKind() <= JobClassLast);
  330. }
  331. };
  332. class PreprocessJobAction : public JobAction {
  333. void anchor() override;
  334. public:
  335. PreprocessJobAction(Action *Input, types::ID OutputType);
  336. static bool classof(const Action *A) {
  337. return A->getKind() == PreprocessJobClass;
  338. }
  339. };
  340. class PrecompileJobAction : public JobAction {
  341. void anchor() override;
  342. protected:
  343. PrecompileJobAction(ActionClass Kind, Action *Input, types::ID OutputType);
  344. public:
  345. PrecompileJobAction(Action *Input, types::ID OutputType);
  346. static bool classof(const Action *A) {
  347. return A->getKind() == PrecompileJobClass;
  348. }
  349. };
  350. class ExtractAPIJobAction : public JobAction {
  351. void anchor() override;
  352. public:
  353. ExtractAPIJobAction(Action *Input, types::ID OutputType);
  354. static bool classof(const Action *A) {
  355. return A->getKind() == ExtractAPIJobClass;
  356. }
  357. void addHeaderInput(Action *Input) { getInputs().push_back(Input); }
  358. };
  359. class AnalyzeJobAction : public JobAction {
  360. void anchor() override;
  361. public:
  362. AnalyzeJobAction(Action *Input, types::ID OutputType);
  363. static bool classof(const Action *A) {
  364. return A->getKind() == AnalyzeJobClass;
  365. }
  366. };
  367. class MigrateJobAction : public JobAction {
  368. void anchor() override;
  369. public:
  370. MigrateJobAction(Action *Input, types::ID OutputType);
  371. static bool classof(const Action *A) {
  372. return A->getKind() == MigrateJobClass;
  373. }
  374. };
  375. class CompileJobAction : public JobAction {
  376. void anchor() override;
  377. public:
  378. CompileJobAction(Action *Input, types::ID OutputType);
  379. static bool classof(const Action *A) {
  380. return A->getKind() == CompileJobClass;
  381. }
  382. };
  383. class BackendJobAction : public JobAction {
  384. void anchor() override;
  385. public:
  386. BackendJobAction(Action *Input, types::ID OutputType);
  387. static bool classof(const Action *A) {
  388. return A->getKind() == BackendJobClass;
  389. }
  390. };
  391. class AssembleJobAction : public JobAction {
  392. void anchor() override;
  393. public:
  394. AssembleJobAction(Action *Input, types::ID OutputType);
  395. static bool classof(const Action *A) {
  396. return A->getKind() == AssembleJobClass;
  397. }
  398. };
  399. class IfsMergeJobAction : public JobAction {
  400. void anchor() override;
  401. public:
  402. IfsMergeJobAction(ActionList &Inputs, types::ID Type);
  403. static bool classof(const Action *A) {
  404. return A->getKind() == IfsMergeJobClass;
  405. }
  406. };
  407. class LinkJobAction : public JobAction {
  408. void anchor() override;
  409. public:
  410. LinkJobAction(ActionList &Inputs, types::ID Type);
  411. static bool classof(const Action *A) {
  412. return A->getKind() == LinkJobClass;
  413. }
  414. };
  415. class LipoJobAction : public JobAction {
  416. void anchor() override;
  417. public:
  418. LipoJobAction(ActionList &Inputs, types::ID Type);
  419. static bool classof(const Action *A) {
  420. return A->getKind() == LipoJobClass;
  421. }
  422. };
  423. class DsymutilJobAction : public JobAction {
  424. void anchor() override;
  425. public:
  426. DsymutilJobAction(ActionList &Inputs, types::ID Type);
  427. static bool classof(const Action *A) {
  428. return A->getKind() == DsymutilJobClass;
  429. }
  430. };
  431. class VerifyJobAction : public JobAction {
  432. void anchor() override;
  433. public:
  434. VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
  435. static bool classof(const Action *A) {
  436. return A->getKind() == VerifyDebugInfoJobClass ||
  437. A->getKind() == VerifyPCHJobClass;
  438. }
  439. };
  440. class VerifyDebugInfoJobAction : public VerifyJobAction {
  441. void anchor() override;
  442. public:
  443. VerifyDebugInfoJobAction(Action *Input, types::ID Type);
  444. static bool classof(const Action *A) {
  445. return A->getKind() == VerifyDebugInfoJobClass;
  446. }
  447. };
  448. class VerifyPCHJobAction : public VerifyJobAction {
  449. void anchor() override;
  450. public:
  451. VerifyPCHJobAction(Action *Input, types::ID Type);
  452. static bool classof(const Action *A) {
  453. return A->getKind() == VerifyPCHJobClass;
  454. }
  455. };
  456. class OffloadBundlingJobAction : public JobAction {
  457. void anchor() override;
  458. public:
  459. // Offloading bundling doesn't change the type of output.
  460. OffloadBundlingJobAction(ActionList &Inputs);
  461. static bool classof(const Action *A) {
  462. return A->getKind() == OffloadBundlingJobClass;
  463. }
  464. };
  465. class OffloadUnbundlingJobAction final : public JobAction {
  466. void anchor() override;
  467. public:
  468. /// Type that provides information about the actions that depend on this
  469. /// unbundling action.
  470. struct DependentActionInfo final {
  471. /// The tool chain of the dependent action.
  472. const ToolChain *DependentToolChain = nullptr;
  473. /// The bound architecture of the dependent action.
  474. StringRef DependentBoundArch;
  475. /// The offload kind of the dependent action.
  476. const OffloadKind DependentOffloadKind = OFK_None;
  477. DependentActionInfo(const ToolChain *DependentToolChain,
  478. StringRef DependentBoundArch,
  479. const OffloadKind DependentOffloadKind)
  480. : DependentToolChain(DependentToolChain),
  481. DependentBoundArch(DependentBoundArch),
  482. DependentOffloadKind(DependentOffloadKind) {}
  483. };
  484. private:
  485. /// Container that keeps information about each dependence of this unbundling
  486. /// action.
  487. SmallVector<DependentActionInfo, 6> DependentActionInfoArray;
  488. public:
  489. // Offloading unbundling doesn't change the type of output.
  490. OffloadUnbundlingJobAction(Action *Input);
  491. /// Register information about a dependent action.
  492. void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch,
  493. OffloadKind Kind) {
  494. DependentActionInfoArray.push_back({TC, BoundArch, Kind});
  495. }
  496. /// Return the information about all depending actions.
  497. ArrayRef<DependentActionInfo> getDependentActionsInfo() const {
  498. return DependentActionInfoArray;
  499. }
  500. static bool classof(const Action *A) {
  501. return A->getKind() == OffloadUnbundlingJobClass;
  502. }
  503. };
  504. class OffloadPackagerJobAction : public JobAction {
  505. void anchor() override;
  506. public:
  507. OffloadPackagerJobAction(ActionList &Inputs, types::ID Type);
  508. static bool classof(const Action *A) {
  509. return A->getKind() == OffloadPackagerJobClass;
  510. }
  511. };
  512. class LinkerWrapperJobAction : public JobAction {
  513. void anchor() override;
  514. public:
  515. LinkerWrapperJobAction(ActionList &Inputs, types::ID Type);
  516. static bool classof(const Action *A) {
  517. return A->getKind() == LinkerWrapperJobClass;
  518. }
  519. };
  520. class StaticLibJobAction : public JobAction {
  521. void anchor() override;
  522. public:
  523. StaticLibJobAction(ActionList &Inputs, types::ID Type);
  524. static bool classof(const Action *A) {
  525. return A->getKind() == StaticLibJobClass;
  526. }
  527. };
  528. } // namespace driver
  529. } // namespace clang
  530. #endif // LLVM_CLANG_DRIVER_ACTION_H
  531. #ifdef __GNUC__
  532. #pragma GCC diagnostic pop
  533. #endif