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