//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_DRIVER_ACTION_H #define SWIFT_DRIVER_ACTION_H #include "swift/Basic/LLVM.h" #include "swift/Driver/Types.h" #include "swift/Driver/Util.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/TimeValue.h" namespace llvm { namespace opt { class Arg; } } namespace swift { namespace driver { class Action; class Action { public: typedef ActionList::size_type size_type; typedef ActionList::iterator iterator; typedef ActionList::const_iterator const_iterator; enum ActionClass { Input = 0, CompileJob, BackendJob, MergeModuleJob, AutolinkExtractJob, REPLJob, LinkJob, GenerateDSYMJob, JobFirst=CompileJob, JobLast=GenerateDSYMJob }; static const char *getClassName(ActionClass AC); private: ActionClass Kind; types::ID Type; ActionList Inputs; unsigned OwnsInputs : 1; protected: Action(ActionClass Kind, types::ID Type) : Kind(Kind), Type(Type), OwnsInputs(true) {} Action(ActionClass Kind, ArrayRef Inputs, types::ID Type) : Kind(Kind), Type(Type), Inputs(Inputs.begin(), Inputs.end()), OwnsInputs(true) {} public: virtual ~Action(); const char *getClassName() const { return Action::getClassName(getKind()); } bool getOwnsInputs() const { return OwnsInputs; } void setOwnsInputs(bool Value) { OwnsInputs = Value; } ActionClass getKind() const { return Kind; } types::ID getType() const { return Type; } ArrayRef getInputs() const { return Inputs; } void addInput(Action *Input) { Inputs.push_back(Input); } 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(); } }; class InputAction : public Action { virtual void anchor(); const llvm::opt::Arg &Input; public: InputAction(const llvm::opt::Arg &Input, types::ID Type) : Action(Action::Input, Type), Input(Input) {} const llvm::opt::Arg &getInputArg() const { return Input; } static bool classof(const Action *A) { return A->getKind() == Action::Input; } }; class JobAction : public Action { virtual void anchor(); protected: JobAction(ActionClass Kind, ArrayRef Inputs, types::ID Type) : Action(Kind, Inputs, Type) {} public: static bool classof(const Action *A) { return (A->getKind() >= ActionClass::JobFirst && A->getKind() <= ActionClass::JobLast); } // Returns the index of the Input action's output file which is used as // (single) input to this action. Most actions produce only a single output // file, so we return 0 by default. virtual int getInputIndex() const { return 0; } }; class CompileJobAction : public JobAction { public: struct InputInfo { enum Status { UpToDate, NeedsCascadingBuild, NeedsNonCascadingBuild, NewlyAdded }; Status status = UpToDate; llvm::sys::TimeValue previousModTime; InputInfo() = default; InputInfo(Status stat, llvm::sys::TimeValue time) : status(stat), previousModTime(time) {} static InputInfo makeNewlyAdded() { return InputInfo(Status::NewlyAdded, llvm::sys::TimeValue::MaxTime()); } }; private: virtual void anchor(); InputInfo inputInfo; public: CompileJobAction(types::ID OutputType) : JobAction(Action::CompileJob, llvm::None, OutputType), inputInfo(InputInfo()) {} CompileJobAction(Action *Input, types::ID OutputType, InputInfo info) : JobAction(Action::CompileJob, Input, OutputType), inputInfo(info) {} InputInfo getInputInfo() const { return inputInfo; } static bool classof(const Action *A) { return A->getKind() == Action::CompileJob; } }; class BackendJobAction : public JobAction { private: virtual void anchor(); // In case of multi-threaded compilation, the compile-action produces multiple // output bitcode-files. For each bitcode-file a BackendJobAction is created. // This index specifies which of the files to select for the input. int InputIndex; public: BackendJobAction(Action *Input, types::ID OutputType, int InputIndex) : JobAction(Action::BackendJob, Input, OutputType), InputIndex(InputIndex) {} static bool classof(const Action *A) { return A->getKind() == Action::BackendJob; } virtual int getInputIndex() const { return InputIndex; } }; class REPLJobAction : public JobAction { public: enum class Mode { Integrated, PreferLLDB, RequireLLDB }; private: virtual void anchor(); Mode RequestedMode; public: REPLJobAction(Mode mode) : JobAction(Action::REPLJob, llvm::None, types::TY_Nothing), RequestedMode(mode) {} Mode getRequestedMode() const { return RequestedMode; } static bool classof(const Action *A) { return A->getKind() == Action::REPLJob; } }; class MergeModuleJobAction : public JobAction { virtual void anchor(); public: MergeModuleJobAction(ArrayRef Inputs) : JobAction(Action::MergeModuleJob, Inputs, types::TY_SwiftModuleFile) {} static bool classof(const Action *A) { return A->getKind() == Action::MergeModuleJob; } }; class AutolinkExtractJobAction : public JobAction { virtual void anchor(); public: AutolinkExtractJobAction(ArrayRef Inputs) : JobAction(Action::AutolinkExtractJob, Inputs, types::TY_AutolinkFile) {} static bool classof(const Action *A) { return A->getKind() == Action::AutolinkExtractJob; } }; class GenerateDSYMJobAction : public JobAction { virtual void anchor(); public: explicit GenerateDSYMJobAction(Action *Input) : JobAction(Action::GenerateDSYMJob, Input, types::TY_dSYM) {} static bool classof(const Action *A) { return A->getKind() == Action::GenerateDSYMJob; } }; class LinkJobAction : public JobAction { virtual void anchor(); LinkKind Kind; public: LinkJobAction(ArrayRef Inputs, LinkKind K) : JobAction(Action::LinkJob, Inputs, types::TY_Image), Kind(K) { assert(Kind != LinkKind::None); } LinkKind getKind() const { return Kind; } static bool classof(const Action *A) { return A->getKind() == Action::LinkJob; } }; } // end namespace driver } // end namespace swift #endif