summaryrefslogtreecommitdiff
path: root/clang-r353983/include/clang/Driver/Action.h
diff options
context:
space:
mode:
authorRalf Luther <luther.ralf@gmail.com>2019-03-27 20:23:17 +0000
committerGerrit Code Review <gerrit2@aicp-server-3>2019-03-27 20:23:17 +0000
commit1ce3a9d272e564b22a1333a1e36a3d3ab7cfab01 (patch)
tree391382eadd4fec5bb480f2e8934fa352770221d1 /clang-r353983/include/clang/Driver/Action.h
parentd1d48b140bafaa8a50107292f5fce95562575765 (diff)
parent4f56932d3416ac03f646bc1a611b3135fec2fe08 (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.h619
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