diff options
| author | Ralf Luther <luther.ralf@gmail.com> | 2019-03-27 20:23:17 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit2@aicp-server-3> | 2019-03-27 20:23:17 +0000 |
| commit | 1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch) | |
| tree | 391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/clang/Driver/Action.h | |
| parent | d1d48b140bafaa8a50107292f5fce95562575765 (diff) | |
| parent | 4f56932d3416ac03f646bc1a611b3135fec2fe08 (diff) | |
Merge "Update prebuilt Clang to r353983." into p9.0HEADp9.0-backupp9.0
Diffstat (limited to 'clang-r353983/include/clang/Driver/Action.h')
| -rw-r--r-- | clang-r353983/include/clang/Driver/Action.h | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/Driver/Action.h b/clang-r353983/include/clang/Driver/Action.h new file mode 100644 index 00000000..c1ff0b1a --- /dev/null +++ b/clang-r353983/include/clang/Driver/Action.h @@ -0,0 +1,619 @@ +//===- Action.h - Abstract compilation steps --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_ACTION_H +#define LLVM_CLANG_DRIVER_ACTION_H + +#include "clang/Basic/LLVM.h" +#include "clang/Driver/Types.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include <string> + +namespace llvm { +namespace opt { + +class Arg; + +} // namespace opt +} // namespace llvm + +namespace clang { +namespace driver { + +class ToolChain; + +/// Action - Represent an abstract compilation step to perform. +/// +/// An action represents an edge in the compilation graph; typically +/// it is a job to transform an input using some tool. +/// +/// The current driver is hard wired to expect actions which produce a +/// single primary output, at least in terms of controlling the +/// compilation. Actions can produce auxiliary files, but can only +/// produce a single output to feed into subsequent actions. +/// +/// Actions are usually owned by a Compilation, which creates new +/// actions via MakeAction(). +class Action { +public: + using size_type = ActionList::size_type; + using input_iterator = ActionList::iterator; + using input_const_iterator = ActionList::const_iterator; + using input_range = llvm::iterator_range<input_iterator>; + using input_const_range = llvm::iterator_range<input_const_iterator>; + + enum ActionClass { + InputClass = 0, + BindArchClass, + OffloadClass, + PreprocessJobClass, + PrecompileJobClass, + HeaderModulePrecompileJobClass, + AnalyzeJobClass, + MigrateJobClass, + CompileJobClass, + BackendJobClass, + AssembleJobClass, + LinkJobClass, + LipoJobClass, + DsymutilJobClass, + VerifyDebugInfoJobClass, + VerifyPCHJobClass, + OffloadBundlingJobClass, + OffloadUnbundlingJobClass, + + JobClassFirst = PreprocessJobClass, + JobClassLast = OffloadUnbundlingJobClass + }; + + // 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, + OFK_OpenMP = 0x04, + OFK_HIP = 0x08, + }; + + static const char *getClassName(ActionClass AC); + +private: + ActionClass Kind; + + /// The output type of this action. + types::ID Type; + + ActionList Inputs; + + /// Flag that is set to true if this action can be collapsed with others + /// actions that depend on it. This is true by default and set to false when + /// the action is used by two different tool chains, which is enabled by the + /// offloading support implementation. + bool CanBeCollapsedWithNextDependentAction = true; + +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) {} + Action(ActionClass Kind, Action *Input) + : Action(Kind, ActionList({Input}), Input->getType()) {} + Action(ActionClass Kind, const ActionList &Inputs, types::ID Type) + : Kind(Kind), Type(Type), Inputs(Inputs) {} + +public: + virtual ~Action(); + + const char *getClassName() const { return Action::getClassName(getKind()); } + + ActionClass getKind() const { return Kind; } + types::ID getType() const { return Type; } + + ActionList &getInputs() { return Inputs; } + const ActionList &getInputs() const { return Inputs; } + + size_type size() const { return Inputs.size(); } + + 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()); + } + + /// Mark this action as not legal to collapse. + void setCannotBeCollapsedWithNextDependentAction() { + CanBeCollapsedWithNextDependentAction = false; + } + + /// Return true if this function can be collapsed with others. + bool isCollapsingWithNextDependentActionLegal() const { + return CanBeCollapsedWithNextDependentAction; + } + + /// 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. By default, no prefix is used for + /// non-device kinds, except if \a CreatePrefixForHost is set. + static std::string + GetOffloadingFileNamePrefix(OffloadKind Kind, + StringRef NormalizedTriple, + bool CreatePrefixForHost = false); + + /// Return a string containing a offload kind name. + static StringRef GetOffloadKindName(OffloadKind Kind); + + /// 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 { + const llvm::opt::Arg &Input; + + virtual void anchor(); + +public: + InputAction(const llvm::opt::Arg &Input, types::ID Type); + + const llvm::opt::Arg &getInputArg() const { return Input; } + + static bool classof(const Action *A) { + return A->getKind() == InputClass; + } +}; + +class BindArchAction : public Action { + virtual void anchor(); + + /// The architecture to bind, or 0 if the default architecture + /// should be bound. + StringRef ArchName; + +public: + BindArchAction(Action *Input, StringRef ArchName); + + StringRef getArchName() const { return ArchName; } + + static bool classof(const Action *A) { + return A->getKind() == BindArchClass; + } +}; + +/// 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(); + +public: + /// Type used to communicate device actions. It associates bound architecture, + /// toolchain, and offload kind to each action. + class DeviceDependences final { + public: + using ToolChainList = SmallVector<const ToolChain *, 3>; + using BoundArchList = SmallVector<const char *, 3>; + using OffloadKindList = SmallVector<OffloadKind, 3>; + + 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; + } + }; + + /// 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; } + }; + + using OffloadActionWorkTy = + llvm::function_ref<void(Action *, const ToolChain *, const char *)>; + +private: + /// The host offloading toolchain that should be used with the action. + const ToolChain *HostTC = nullptr; + + /// The tool chains associated with the list of actions. + DeviceDependences::ToolChainList DevToolChains; + +public: + OffloadAction(const HostDependence &HDep); + OffloadAction(const DeviceDependences &DDeps, types::ID Ty); + OffloadAction(const HostDependence &HDep, const DeviceDependences &DDeps); + + /// Execute the work specified in \a Work on the host dependence. + void doOnHostDependence(const OffloadActionWorkTy &Work) const; + + /// 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; + + /// 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() == OffloadClass; } +}; + +class JobAction : public Action { + virtual void anchor(); + +protected: + JobAction(ActionClass Kind, Action *Input, types::ID Type); + JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); + +public: + static bool classof(const Action *A) { + return (A->getKind() >= JobClassFirst && + A->getKind() <= JobClassLast); + } +}; + +class PreprocessJobAction : public JobAction { + void anchor() override; + +public: + PreprocessJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == PreprocessJobClass; + } +}; + +class PrecompileJobAction : public JobAction { + void anchor() override; + +protected: + PrecompileJobAction(ActionClass Kind, Action *Input, types::ID OutputType); + +public: + PrecompileJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == PrecompileJobClass || + A->getKind() == HeaderModulePrecompileJobClass; + } +}; + +class HeaderModulePrecompileJobAction : public PrecompileJobAction { + void anchor() override; + + const char *ModuleName; + +public: + HeaderModulePrecompileJobAction(Action *Input, types::ID OutputType, + const char *ModuleName); + + static bool classof(const Action *A) { + return A->getKind() == HeaderModulePrecompileJobClass; + } + + void addModuleHeaderInput(Action *Input) { + getInputs().push_back(Input); + } + + const char *getModuleName() const { return ModuleName; } +}; + +class AnalyzeJobAction : public JobAction { + void anchor() override; + +public: + AnalyzeJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == AnalyzeJobClass; + } +}; + +class MigrateJobAction : public JobAction { + void anchor() override; + +public: + MigrateJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == MigrateJobClass; + } +}; + +class CompileJobAction : public JobAction { + void anchor() override; + +public: + CompileJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == CompileJobClass; + } +}; + +class BackendJobAction : public JobAction { + void anchor() override; + +public: + BackendJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == BackendJobClass; + } +}; + +class AssembleJobAction : public JobAction { + void anchor() override; + +public: + AssembleJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == AssembleJobClass; + } +}; + +class LinkJobAction : public JobAction { + void anchor() override; + +public: + LinkJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == LinkJobClass; + } +}; + +class LipoJobAction : public JobAction { + void anchor() override; + +public: + LipoJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == LipoJobClass; + } +}; + +class DsymutilJobAction : public JobAction { + void anchor() override; + +public: + DsymutilJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == DsymutilJobClass; + } +}; + +class VerifyJobAction : public JobAction { + void anchor() override; + +public: + VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == VerifyDebugInfoJobClass || + A->getKind() == VerifyPCHJobClass; + } +}; + +class VerifyDebugInfoJobAction : public VerifyJobAction { + void anchor() override; + +public: + VerifyDebugInfoJobAction(Action *Input, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == VerifyDebugInfoJobClass; + } +}; + +class VerifyPCHJobAction : public VerifyJobAction { + void anchor() override; + +public: + VerifyPCHJobAction(Action *Input, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == VerifyPCHJobClass; + } +}; + +class OffloadBundlingJobAction : public JobAction { + void anchor() override; + +public: + // Offloading bundling doesn't change the type of output. + OffloadBundlingJobAction(ActionList &Inputs); + + static bool classof(const Action *A) { + return A->getKind() == OffloadBundlingJobClass; + } +}; + +class OffloadUnbundlingJobAction final : public JobAction { + void anchor() override; + +public: + /// Type that provides information about the actions that depend on this + /// unbundling action. + struct DependentActionInfo final { + /// The tool chain of the dependent action. + const ToolChain *DependentToolChain = nullptr; + + /// The bound architecture of the dependent action. + StringRef DependentBoundArch; + + /// The offload kind of the dependent action. + const OffloadKind DependentOffloadKind = OFK_None; + + DependentActionInfo(const ToolChain *DependentToolChain, + StringRef DependentBoundArch, + const OffloadKind DependentOffloadKind) + : DependentToolChain(DependentToolChain), + DependentBoundArch(DependentBoundArch), + DependentOffloadKind(DependentOffloadKind) {} + }; + +private: + /// Container that keeps information about each dependence of this unbundling + /// action. + SmallVector<DependentActionInfo, 6> DependentActionInfoArray; + +public: + // Offloading unbundling doesn't change the type of output. + OffloadUnbundlingJobAction(Action *Input); + + /// Register information about a dependent action. + void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch, + OffloadKind Kind) { + DependentActionInfoArray.push_back({TC, BoundArch, Kind}); + } + + /// Return the information about all depending actions. + ArrayRef<DependentActionInfo> getDependentActionsInfo() const { + return DependentActionInfoArray; + } + + static bool classof(const Action *A) { + return A->getKind() == OffloadUnbundlingJobClass; + } +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_ACTION_H |
