123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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,
- ExtractAPIJobClass,
- AnalyzeJobClass,
- MigrateJobClass,
- CompileJobClass,
- BackendJobClass,
- AssembleJobClass,
- LinkJobClass,
- IfsMergeJobClass,
- LipoJobClass,
- DsymutilJobClass,
- VerifyDebugInfoJobClass,
- VerifyPCHJobClass,
- OffloadBundlingJobClass,
- OffloadUnbundlingJobClass,
- OffloadPackagerJobClass,
- LinkerWrapperJobClass,
- StaticLibJobClass,
- JobClassFirst = PreprocessJobClass,
- JobClassLast = StaticLibJobClass
- };
- // 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;
- /// The Offloading toolchain associated with this device action.
- const ToolChain *OffloadingToolChain = 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,
- const ToolChain *OToolChain);
- /// Append the host offload info of this action and propagate it to its
- /// dependences.
- void propagateHostOffloadInfo(unsigned OKinds, const char *OArch);
- void setHostOffloadInfo(unsigned OKinds, const char *OArch) {
- ActiveOffloadKindMask |= OKinds;
- OffloadingArch = 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; }
- const ToolChain *getOffloadingToolChain() const {
- return OffloadingToolChain;
- }
- /// 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(unsigned int 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;
- std::string Id;
- virtual void anchor();
- public:
- InputAction(const llvm::opt::Arg &Input, types::ID Type,
- StringRef Id = StringRef());
- const llvm::opt::Arg &getInputArg() const { return Input; }
- void setId(StringRef _Id) { Id = _Id.str(); }
- StringRef getId() const { return Id; }
- 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 an action along with the associated toolchain, bound arch, and
- /// offload kind.
- void add(Action &A, const ToolChain &TC, const char *BoundArch,
- OffloadKind OKind);
- /// Add an action along with the associated toolchain, bound arch, and
- /// offload kinds.
- void add(Action &A, const ToolChain &TC, const char *BoundArch,
- unsigned OffloadKindMask);
- /// 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;
- }
- };
- class ExtractAPIJobAction : public JobAction {
- void anchor() override;
- public:
- ExtractAPIJobAction(Action *Input, types::ID OutputType);
- static bool classof(const Action *A) {
- return A->getKind() == ExtractAPIJobClass;
- }
- void addHeaderInput(Action *Input) { getInputs().push_back(Input); }
- };
- 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 IfsMergeJobAction : public JobAction {
- void anchor() override;
- public:
- IfsMergeJobAction(ActionList &Inputs, types::ID Type);
- static bool classof(const Action *A) {
- return A->getKind() == IfsMergeJobClass;
- }
- };
- 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;
- }
- };
- class OffloadPackagerJobAction : public JobAction {
- void anchor() override;
- public:
- OffloadPackagerJobAction(ActionList &Inputs, types::ID Type);
- static bool classof(const Action *A) {
- return A->getKind() == OffloadPackagerJobClass;
- }
- };
- class LinkerWrapperJobAction : public JobAction {
- void anchor() override;
- public:
- LinkerWrapperJobAction(ActionList &Inputs, types::ID Type);
- static bool classof(const Action *A) {
- return A->getKind() == LinkerWrapperJobClass;
- }
- };
- class StaticLibJobAction : public JobAction {
- void anchor() override;
- public:
- StaticLibJobAction(ActionList &Inputs, types::ID Type);
- static bool classof(const Action *A) {
- return A->getKind() == StaticLibJobClass;
- }
- };
- } // namespace driver
- } // namespace clang
- #endif // LLVM_CLANG_DRIVER_ACTION_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|