//===--- SILArgument.h - SIL BasicBlock Argument Representation -*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_SILARGUMENT_H #define SWIFT_SIL_SILARGUMENT_H #include "swift/Basic/Compiler.h" #include "swift/SIL/SILArgumentConvention.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILValue.h" namespace swift { class SILBasicBlock; class SILModule; class SILUndef; // Map an argument index onto a SILArgumentConvention. inline SILArgumentConvention SILFunctionConventions::getSILArgumentConvention(unsigned index) const { assert(index <= getNumSILArguments()); if (index < getNumIndirectSILResults()) { assert(silConv.loweredAddresses); return SILArgumentConvention::Indirect_Out; } else { auto param = funcTy->getParameters()[index - getNumIndirectSILResults()]; return SILArgumentConvention(param.getConvention()); } } class SILArgument : public ValueBase { void operator=(const SILArgument &) = delete; void operator delete(void *Ptr, size_t) SWIFT_DELETE_OPERATOR_DELETED SILBasicBlock *ParentBB; const ValueDecl *Decl; public: ValueOwnershipKind getOwnershipKind() const { return static_cast(Bits.SILArgument.VOKind); } void setOwnershipKind(ValueOwnershipKind NewKind) { Bits.SILArgument.VOKind = static_cast(NewKind); } SILBasicBlock *getParent() { return ParentBB; } const SILBasicBlock *getParent() const { return ParentBB; } SILFunction *getFunction(); const SILFunction *getFunction() const; SILModule &getModule() const; const ValueDecl *getDecl() const { return Decl; } static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; static bool classof(const SILNode *node) { return node->getKind() >= SILNodeKind::First_SILArgument && node->getKind() <= SILNodeKind::Last_SILArgument; } unsigned getIndex() const { ArrayRef Args = getParent()->getArguments(); for (unsigned i = 0, e = Args.size(); i != e; ++i) if (Args[i] == this) return i; llvm_unreachable("SILArgument not argument of its parent BB"); } /// Returns the incoming SILValue from the \p BBIndex predecessor of this /// argument's parent BB. If the routine fails, it returns an empty SILValue. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getIncomingValue(unsigned BBIndex); /// Returns the incoming SILValue for this argument from BB. If the routine /// fails, it returns an empty SILValue. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getIncomingValue(SILBasicBlock *BB); /// Returns true if we were able to find incoming values for each predecessor /// of this arguments basic block. The found values are stored in OutArray. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). bool getIncomingValues(llvm::SmallVectorImpl &OutArray); /// Returns true if we were able to find incoming values for each predecessor /// of this arguments basic block. The found values are stored in OutArray. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). bool getIncomingValues( llvm::SmallVectorImpl> &OutArray); /// If this SILArgument's parent block has one predecessor, return the /// incoming value from that predecessor. Returns SILValue() otherwise. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getSingleIncomingValue() const; protected: SILArgument(ValueKind SubClassKind, SILBasicBlock *ParentBB, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr); SILArgument(ValueKind SubClassKind, SILBasicBlock *ParentBB, SILBasicBlock::arg_iterator Pos, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr); // A special constructor, only intended for use in // SILBasicBlock::replacePHIArg and replaceFunctionArg. explicit SILArgument(ValueKind SubClassKind, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : ValueBase(SubClassKind, Ty, IsRepresentative::Yes), ParentBB(nullptr), Decl(D) { Bits.SILArgument.VOKind = static_cast(OwnershipKind); } void setParent(SILBasicBlock *P) { ParentBB = P; } friend SILBasicBlock; }; class SILPHIArgument : public SILArgument { public: /// Returns the incoming SILValue from the \p BBIndex predecessor of this /// argument's parent BB. If the routine fails, it returns an empty SILValue. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getIncomingValue(unsigned BBIndex); /// Returns the incoming SILValue for this argument from BB. If the routine /// fails, it returns an empty SILValue. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getIncomingValue(SILBasicBlock *BB); /// Returns true if we were able to find incoming values for each predecessor /// of this arguments basic block. The found values are stored in OutArray. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). bool getIncomingValues(llvm::SmallVectorImpl &OutArray); /// Returns true if we were able to find incoming values for each predecessor /// of this arguments basic block. The found values are stored in OutArray. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). bool getIncomingValues( llvm::SmallVectorImpl> &OutArray); /// If this SILArgument's parent block has one predecessor, return the /// incoming value from that predecessor. Returns SILValue() otherwise. /// Note that for some predecessor terminators the incoming value is not /// exactly the argument value. E.g. the incoming value for a switch_enum /// payload argument is the enum itself (the operand of the switch_enum). SILValue getSingleIncomingValue() const; static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::SILPHIArgument; } private: friend SILBasicBlock; SILPHIArgument(SILBasicBlock *ParentBB, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILPHIArgument, ParentBB, Ty, OwnershipKind, D) {} SILPHIArgument(SILBasicBlock *ParentBB, SILBasicBlock::arg_iterator Pos, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILPHIArgument, ParentBB, Pos, Ty, OwnershipKind, D) {} // A special constructor, only intended for use in // SILBasicBlock::replacePHIArg. explicit SILPHIArgument(SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILPHIArgument, Ty, OwnershipKind, D) {} }; class SILFunctionArgument : public SILArgument { public: bool isIndirectResult() const { auto numIndirectResults = getFunction()->getConventions().getNumIndirectSILResults(); return (getIndex() < numIndirectResults); } SILArgumentConvention getArgumentConvention() const { return getFunction()->getConventions().getSILArgumentConvention(getIndex()); } /// Given that this is an entry block argument, and given that it does /// not correspond to an indirect result, return the corresponding /// SILParameterInfo. SILParameterInfo getKnownParameterInfo() const { return getFunction()->getConventions().getParamInfoForSILArg(getIndex()); } /// Returns true if this SILArgument is the self argument of its /// function. This means that this will return false always for SILArguments /// of SILFunctions that do not have self argument and for non-function /// argument SILArguments. bool isSelf() const; /// Returns true if this SILArgument is passed via the given convention. bool hasConvention(SILArgumentConvention P) const { return getArgumentConvention() == P; } static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::SILFunctionArgument; } private: friend SILBasicBlock; SILFunctionArgument(SILBasicBlock *ParentBB, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILFunctionArgument, ParentBB, Ty, OwnershipKind, D) {} SILFunctionArgument(SILBasicBlock *ParentBB, SILBasicBlock::arg_iterator Pos, SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILFunctionArgument, ParentBB, Pos, Ty, OwnershipKind, D) {} // A special constructor, only intended for use in // SILBasicBlock::replaceFunctionArg. explicit SILFunctionArgument(SILType Ty, ValueOwnershipKind OwnershipKind, const ValueDecl *D = nullptr) : SILArgument(ValueKind::SILFunctionArgument, Ty, OwnershipKind, D) {} }; //===----------------------------------------------------------------------===// // Out of line Definitions for SILArgument to avoid Forward Decl issues //===----------------------------------------------------------------------===// inline SILValue SILArgument::getIncomingValue(unsigned BBIndex) { if (isa(this)) return SILValue(); return cast(this)->getIncomingValue(BBIndex); } inline SILValue SILArgument::getIncomingValue(SILBasicBlock *BB) { if (isa(this)) return SILValue(); return cast(this)->getIncomingValue(BB); } inline bool SILArgument::getIncomingValues(llvm::SmallVectorImpl &OutArray) { if (isa(this)) return false; return cast(this)->getIncomingValues(OutArray); } inline bool SILArgument::getIncomingValues( llvm::SmallVectorImpl> &OutArray) { if (isa(this)) return false; return cast(this)->getIncomingValues(OutArray); } inline SILValue SILArgument::getSingleIncomingValue() const { if (isa(this)) return SILValue(); return cast(this)->getSingleIncomingValue(); } } // end swift namespace #endif