diff options
Diffstat (limited to 'include/clang/Driver/Action.h')
-rw-r--r-- | include/clang/Driver/Action.h | 219 |
1 files changed, 186 insertions, 33 deletions
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index c5b0f4755092f..3fe6510fec98c 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -10,8 +10,10 @@ #ifndef LLVM_CLANG_DRIVER_ACTION_H #define LLVM_CLANG_DRIVER_ACTION_H +#include "clang/Basic/Cuda.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" namespace llvm { @@ -26,6 +28,8 @@ namespace opt { namespace clang { namespace driver { +class ToolChain; + /// Action - Represent an abstract compilation step to perform. /// /// An action represents an edge in the compilation graph; typically @@ -41,14 +45,15 @@ namespace driver { class Action { public: typedef ActionList::size_type size_type; - typedef ActionList::iterator iterator; - typedef ActionList::const_iterator const_iterator; + typedef ActionList::iterator input_iterator; + typedef ActionList::const_iterator input_const_iterator; + typedef llvm::iterator_range<input_iterator> input_range; + typedef llvm::iterator_range<input_const_iterator> input_const_range; enum ActionClass { InputClass = 0, BindArchClass, - CudaDeviceClass, - CudaHostClass, + OffloadClass, PreprocessJobClass, PrecompileJobClass, AnalyzeJobClass, @@ -62,8 +67,19 @@ public: VerifyDebugInfoJobClass, VerifyPCHJobClass, - JobClassFirst=PreprocessJobClass, - JobClassLast=VerifyPCHJobClass + JobClassFirst = PreprocessJobClass, + JobClassLast = VerifyPCHJobClass + }; + + // The offloading kind determines if this action is binded to a particular + // programming model. Each entry reserves one bit. We also have a special kind + // to designate the host offloading tool chain. + enum OffloadKind { + OFK_None = 0x00, + // The host offloading tool chain. + OFK_Host = 0x01, + // The device offloading tool chains - one bit for each programming model. + OFK_Cuda = 0x02, }; static const char *getClassName(ActionClass AC); @@ -77,6 +93,19 @@ private: ActionList Inputs; protected: + /// + /// Offload information. + /// + + /// The host offloading kind - a combination of kinds encoded in a mask. + /// Multiple programming models may be supported simultaneously by the same + /// host. + unsigned ActiveOffloadKindMask = 0u; + /// Offloading kind of the device. + OffloadKind OffloadingDeviceKind = OFK_None; + /// The Offloading architecture associated with this action. + const char *OffloadingArch = nullptr; + Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {} Action(ActionClass Kind, Action *Input, types::ID Type) : Action(Kind, ActionList({Input}), Type) {} @@ -98,10 +127,49 @@ public: size_type size() const { return Inputs.size(); } - iterator begin() { return Inputs.begin(); } - iterator end() { return Inputs.end(); } - const_iterator begin() const { return Inputs.begin(); } - const_iterator end() const { return Inputs.end(); } + input_iterator input_begin() { return Inputs.begin(); } + input_iterator input_end() { return Inputs.end(); } + input_range inputs() { return input_range(input_begin(), input_end()); } + input_const_iterator input_begin() const { return Inputs.begin(); } + input_const_iterator input_end() const { return Inputs.end(); } + input_const_range inputs() const { + return input_const_range(input_begin(), input_end()); + } + + /// Return a string containing the offload kind of the action. + std::string getOffloadingKindPrefix() const; + /// Return a string that can be used as prefix in order to generate unique + /// files for each offloading kind. + std::string + getOffloadingFileNamePrefix(llvm::StringRef NormalizedTriple) const; + + /// Set the device offload info of this action and propagate it to its + /// dependences. + void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch); + /// Append the host offload info of this action and propagate it to its + /// dependences. + void propagateHostOffloadInfo(unsigned OKinds, const char *OArch); + /// Set the offload info of this action to be the same as the provided action, + /// and propagate it to its dependences. + void propagateOffloadInfo(const Action *A); + + unsigned getOffloadingHostActiveKinds() const { + return ActiveOffloadKindMask; + } + OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; } + const char *getOffloadingArch() const { return OffloadingArch; } + + /// Check if this action have any offload kinds. Note that host offload kinds + /// are only set if the action is a dependence to a host offload action. + bool isHostOffloading(OffloadKind OKind) const { + return ActiveOffloadKindMask & OKind; + } + bool isDeviceOffloading(OffloadKind OKind) const { + return OffloadingDeviceKind == OKind; + } + bool isOffloading(OffloadKind OKind) const { + return isHostOffloading(OKind) || isDeviceOffloading(OKind); + } }; class InputAction : public Action { @@ -134,41 +202,126 @@ public: } }; -class CudaDeviceAction : public Action { +/// An offload action combines host or/and device actions according to the +/// programming model implementation needs and propagates the offloading kind to +/// its dependences. +class OffloadAction final : public Action { virtual void anchor(); - /// GPU architecture to bind. Always of the form /sm_\d+/. - const char *GpuArchName; - /// True when action results are not consumed by the host action (e.g when - /// -fsyntax-only or --cuda-device-only options are used). - bool AtTopLevel; public: - CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel); + /// Type used to communicate device actions. It associates bound architecture, + /// toolchain, and offload kind to each action. + class DeviceDependences final { + public: + typedef SmallVector<const ToolChain *, 3> ToolChainList; + typedef SmallVector<const char *, 3> BoundArchList; + typedef SmallVector<OffloadKind, 3> OffloadKindList; + + private: + // Lists that keep the information for each dependency. All the lists are + // meant to be updated in sync. We are adopting separate lists instead of a + // list of structs, because that simplifies forwarding the actions list to + // initialize the inputs of the base Action class. + + /// The dependence actions. + ActionList DeviceActions; + /// The offloading toolchains that should be used with the action. + ToolChainList DeviceToolChains; + /// The architectures that should be used with this action. + BoundArchList DeviceBoundArchs; + /// The offload kind of each dependence. + OffloadKindList DeviceOffloadKinds; + + public: + /// Add a action along with the associated toolchain, bound arch, and + /// offload kind. + void add(Action &A, const ToolChain &TC, const char *BoundArch, + OffloadKind OKind); + + /// Get each of the individual arrays. + const ActionList &getActions() const { return DeviceActions; }; + const ToolChainList &getToolChains() const { return DeviceToolChains; }; + const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; }; + const OffloadKindList &getOffloadKinds() const { + return DeviceOffloadKinds; + }; + }; - const char *getGpuArchName() const { return GpuArchName; } + /// Type used to communicate host actions. It associates bound architecture, + /// toolchain, and offload kinds to the host action. + class HostDependence final { + /// The dependence action. + Action &HostAction; + /// The offloading toolchain that should be used with the action. + const ToolChain &HostToolChain; + /// The architectures that should be used with this action. + const char *HostBoundArch = nullptr; + /// The offload kind of each dependence. + unsigned HostOffloadKinds = 0u; + + public: + HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, + const unsigned OffloadKinds) + : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch), + HostOffloadKinds(OffloadKinds){}; + /// Constructor version that obtains the offload kinds from the device + /// dependencies. + HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, + const DeviceDependences &DDeps); + Action *getAction() const { return &HostAction; }; + const ToolChain *getToolChain() const { return &HostToolChain; }; + const char *getBoundArch() const { return HostBoundArch; }; + unsigned getOffloadKinds() const { return HostOffloadKinds; }; + }; - /// Gets the compute_XX that corresponds to getGpuArchName(). - const char *getComputeArchName() const; + typedef llvm::function_ref<void(Action *, const ToolChain *, const char *)> + OffloadActionWorkTy; - bool isAtTopLevel() const { return AtTopLevel; } +private: + /// The host offloading toolchain that should be used with the action. + const ToolChain *HostTC = nullptr; - static bool IsValidGpuArchName(llvm::StringRef ArchName); + /// The tool chains associated with the list of actions. + DeviceDependences::ToolChainList DevToolChains; - static bool classof(const Action *A) { - return A->getKind() == CudaDeviceClass; - } -}; +public: + OffloadAction(const HostDependence &HDep); + OffloadAction(const DeviceDependences &DDeps, types::ID Ty); + OffloadAction(const HostDependence &HDep, const DeviceDependences &DDeps); -class CudaHostAction : public Action { - virtual void anchor(); - ActionList DeviceActions; + /// Execute the work specified in \a Work on the host dependence. + void doOnHostDependence(const OffloadActionWorkTy &Work) const; -public: - CudaHostAction(Action *Input, const ActionList &DeviceActions); + /// Execute the work specified in \a Work on each device dependence. + void doOnEachDeviceDependence(const OffloadActionWorkTy &Work) const; + + /// Execute the work specified in \a Work on each dependence. + void doOnEachDependence(const OffloadActionWorkTy &Work) const; + + /// Execute the work specified in \a Work on each host or device dependence if + /// \a IsHostDependenceto is true or false, respectively. + void doOnEachDependence(bool IsHostDependence, + const OffloadActionWorkTy &Work) const; + + /// Return true if the action has a host dependence. + bool hasHostDependence() const; + + /// Return the host dependence of this action. This function is only expected + /// to be called if the host dependence exists. + Action *getHostDependence() const; + + /// Return true if the action has a single device dependence. If \a + /// DoNotConsiderHostActions is set, ignore the host dependence, if any, while + /// accounting for the number of dependences. + bool hasSingleDeviceDependence(bool DoNotConsiderHostActions = false) const; - const ActionList &getDeviceActions() const { return DeviceActions; } + /// Return the single device dependence of this action. This function is only + /// expected to be called if a single device dependence exists. If \a + /// DoNotConsiderHostActions is set, a host dependence is allowed. + Action * + getSingleDeviceDependence(bool DoNotConsiderHostActions = false) const; - static bool classof(const Action *A) { return A->getKind() == CudaHostClass; } + static bool classof(const Action *A) { return A->getKind() == OffloadClass; } }; class JobAction : public Action { |