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