X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FCallSite.h;h=f4b8a8a5a1c93b33edf22359c8de96ed577c5ea4;hb=982aa42a6efd967b7dd0bbb82859f1736072ac56;hp=0270caaaf13743c48a8d8620a7fa03fbf8ad2572;hpb=cf0db29df20d9c665da7e82bb261bdd7cf7f1b2b;p=oota-llvm.git diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index 0270caaaf13..f4b8a8a5a1c 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -38,8 +38,10 @@ class CallInst; class InvokeInst; template () const { return I.getPointer(); } explicit operator bool() const { return I.getPointer(); } + /// Get the basic block containing the call site + BBTy* getParent() const { return getInstruction()->getParent(); } + /// getCalledValue - Return the pointer to function that is being called. /// ValTy *getCalledValue() const { @@ -112,6 +118,43 @@ public: /// Determine whether this Use is the callee operand's Use. bool isCallee(const Use *U) const { return getCallee() == U; } + /// \brief Determine whether the passed iterator points to an argument + /// operand. + bool isArgOperand(Value::const_user_iterator UI) const { + return isArgOperand(&UI.getUse()); + } + + /// \brief Determine whether the passed use points to an argument operand. + bool isArgOperand(const Use *U) const { + assert(getInstruction() == U->getUser()); + return arg_begin() <= U && U < arg_end(); + } + + /// \brief Determine whether the passed iterator points to a bundle operand. + bool isBundleOperand(Value::const_user_iterator UI) const { + return isBundleOperand(&UI.getUse()); + } + + /// \brief Determine whether the passed use points to a bundle operand. + bool isBundleOperand(const Use *U) const { + assert(getInstruction() == U->getUser()); + if (!hasOperandBundles()) + return false; + unsigned OperandNo = U - (*this)->op_begin(); + return getBundleOperandsStartIndex() <= OperandNo && + OperandNo < getBundleOperandsEndIndex(); + } + + /// \brief Determine whether the passed iterator points to a data operand. + bool isDataOperand(Value::const_user_iterator UI) const { + return isDataOperand(&UI.getUse()); + } + + /// \brief Determine whether the passed use points to a data operand. + bool isDataOperand(const Use *U) const { + return data_operands_begin() <= U && U < data_operands_end(); + } + ValTy *getArgument(unsigned ArgNo) const { assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); return *(arg_begin() + ArgNo); @@ -133,8 +176,7 @@ public: /// it. unsigned getArgumentNo(const Use *U) const { assert(getInstruction() && "Not a call or invoke instruction!"); - assert(arg_begin() <= U && U < arg_end() - && "Argument # out of range!"); + assert(isArgOperand(U) && "Argument # out of range!"); return U - arg_begin(); } @@ -142,21 +184,55 @@ public: /// arguments at this call site. typedef IterTy arg_iterator; - /// arg_begin/arg_end - Return iterators corresponding to the actual argument - /// list for a call site. - IterTy arg_begin() const { - assert(getInstruction() && "Not a call or invoke instruction!"); - // Skip non-arguments - return (*this)->op_begin(); - } - - IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } iterator_range args() const { - return iterator_range(arg_begin(), arg_end()); + return make_range(arg_begin(), arg_end()); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } + /// Given a value use iterator, returns the data operand that corresponds to + /// it. + /// Iterator must actually correspond to a data operand. + unsigned getDataOperandNo(Value::const_user_iterator UI) const { + return getDataOperandNo(&UI.getUse()); + } + + /// Given a use for a data operand, get the data operand number that + /// corresponds to it. + unsigned getDataOperandNo(const Use *U) const { + assert(getInstruction() && "Not a call or invoke instruction!"); + assert(isDataOperand(U) && "Data operand # out of range!"); + return U - data_operands_begin(); + } + + /// Type of iterator to use when looping over data operands at this call site + /// (see below). + typedef IterTy data_operand_iterator; + + /// data_operands_begin/data_operands_end - Return iterators iterating over + /// the call / invoke argument list and bundle operands. For invokes, this is + /// the set of instruction operands except the invoke target and the two + /// successor blocks; and for calls this is the set of instruction operands + /// except the call target. + + IterTy data_operands_begin() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + return (*this)->op_begin(); + } + IterTy data_operands_end() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + return (*this)->op_end() - (isCall() ? 1 : 3); + } + iterator_range data_ops() const { + return make_range(data_operands_begin(), data_operands_end()); + } + bool data_operands_empty() const { + return data_operands_end() == data_operands_begin(); + } + unsigned data_operands_size() const { + return std::distance(data_operands_begin(), data_operands_end()); + } + /// getType - Return the type of the instruction that generated this call site /// Type *getType() const { return (*this)->getType(); } @@ -189,6 +265,20 @@ public: else \ cast(II)->METHOD + unsigned getNumArgOperands() const { + CALLSITE_DELEGATE_GETTER(getNumArgOperands()); + } + + ValTy *getArgOperand(unsigned i) const { + CALLSITE_DELEGATE_GETTER(getArgOperand(i)); + } + + bool isInlineAsm() const { + if (isCall()) + return cast(getInstruction())->isInlineAsm(); + return false; + } + /// getCallingConv/setCallingConv - get or set the calling convention of the /// call. CallingConv::ID getCallingConv() const { @@ -225,6 +315,17 @@ public: CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A)); } + /// \brief Return true if the data operand at index \p i directly or + /// indirectly has the attribute \p A. + /// + /// Normal call or invoke arguments have per operand attributes, as specified + /// in the attribute set attached to this instruction, while operand bundle + /// operands may have some attributes implied by the type of its containing + /// operand bundle. + bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const { + CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, A)); + } + /// @brief Extract the alignment for a call or parameter (0=unknown). uint16_t getParamAlignment(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); @@ -235,13 +336,20 @@ public: uint64_t getDereferenceableBytes(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); } - + /// @brief Extract the number of dereferenceable_or_null bytes for a call or /// parameter (0=unknown). uint64_t getDereferenceableOrNullBytes(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i)); } - + + /// @brief Determine if the parameter or return value is marked with NoAlias + /// attribute. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + CALLSITE_DELEGATE_GETTER(doesNotAlias(n)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -272,6 +380,15 @@ public: CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory()); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + CALLSITE_DELEGATE_GETTER(onlyAccessesArgMemory()); + } + void setOnlyAccessesArgMemory() { + CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory()); + } + /// @brief Determine if the call cannot return. bool doesNotReturn() const { CALLSITE_DELEGATE_GETTER(doesNotReturn()); @@ -288,12 +405,62 @@ public: CALLSITE_DELEGATE_SETTER(setDoesNotThrow()); } + unsigned getNumOperandBundles() const { + CALLSITE_DELEGATE_GETTER(getNumOperandBundles()); + } + + bool hasOperandBundles() const { + CALLSITE_DELEGATE_GETTER(hasOperandBundles()); + } + + unsigned getBundleOperandsStartIndex() const { + CALLSITE_DELEGATE_GETTER(getBundleOperandsStartIndex()); + } + + unsigned getBundleOperandsEndIndex() const { + CALLSITE_DELEGATE_GETTER(getBundleOperandsEndIndex()); + } + + unsigned getNumTotalBundleOperands() const { + CALLSITE_DELEGATE_GETTER(getNumTotalBundleOperands()); + } + + OperandBundleUse getOperandBundleAt(unsigned Index) const { + CALLSITE_DELEGATE_GETTER(getOperandBundleAt(Index)); + } + + Optional getOperandBundle(StringRef Name) const { + CALLSITE_DELEGATE_GETTER(getOperandBundle(Name)); + } + + Optional getOperandBundle(uint32_t ID) const { + CALLSITE_DELEGATE_GETTER(getOperandBundle(ID)); + } + + IterTy arg_begin() const { + CALLSITE_DELEGATE_GETTER(arg_begin()); + } + + IterTy arg_end() const { + CALLSITE_DELEGATE_GETTER(arg_end()); + } + #undef CALLSITE_DELEGATE_GETTER #undef CALLSITE_DELEGATE_SETTER - /// @brief Determine whether this argument is not captured. - bool doesNotCapture(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::NoCapture); + void getOperandBundlesAsDefs(SmallVectorImpl &Defs) const { + const Instruction *II = getInstruction(); + // Since this is actually a getter that "looks like" a setter, don't use the + // above macros to avoid confusion. + if (isCall()) + cast(II)->getOperandBundlesAsDefs(Defs); + else + cast(II)->getOperandBundlesAsDefs(Defs); + } + + /// @brief Determine whether this data operand is not captured. + bool doesNotCapture(unsigned OpNo) const { + return dataOperandHasImpliedAttr(OpNo + 1, Attribute::NoCapture); } /// @brief Determine whether this argument is passed by value. @@ -318,13 +485,13 @@ public: return paramHasAttr(arg_size(), Attribute::InAlloca); } - bool doesNotAccessMemory(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::ReadNone); + bool doesNotAccessMemory(unsigned OpNo) const { + return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone); } - bool onlyReadsMemory(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::ReadOnly) || - paramHasAttr(ArgNo + 1, Attribute::ReadNone); + bool onlyReadsMemory(unsigned OpNo) const { + return dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadOnly) || + dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone); } /// @brief Return true if the return value is known to be not null. @@ -351,13 +518,6 @@ public: } private: - unsigned getArgumentEndOffset() const { - if (isCall()) - return 1; // Skip Callee - else - return 3; // Skip BB, BB, Callee - } - IterTy getCallee() const { if (isCall()) // Skip Callee return cast(getInstruction())->op_end() - 1; @@ -366,8 +526,9 @@ private: } }; -class CallSite : public CallSiteBase { +class CallSite : public CallSiteBase { public: CallSite() {} CallSite(CallSiteBase B) : CallSiteBase(B) {} @@ -397,6 +558,6 @@ public: ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} }; -} // namespace llvm +} // End llvm namespace #endif