diff options
author | Gabor Greif <ggreif@gmail.com> | 2010-04-01 08:21:08 +0000 |
---|---|---|
committer | Gabor Greif <ggreif@gmail.com> | 2010-04-01 08:21:08 +0000 |
commit | c8b82ccbcf3b2e2384d2c0b5176e7b0b40b7f82f (patch) | |
tree | f83b4be77578085e4ad3be52f2979d0d7ba5d6c6 /include/llvm/Support | |
parent | 2d7820cb782d6f2ee74b3c9e90438229324f84cd (diff) | |
download | external_llvm-c8b82ccbcf3b2e2384d2c0b5176e7b0b40b7f82f.zip external_llvm-c8b82ccbcf3b2e2384d2c0b5176e7b0b40b7f82f.tar.gz external_llvm-c8b82ccbcf3b2e2384d2c0b5176e7b0b40b7f82f.tar.bz2 |
Introduce ImmutableCallSite, useful for contexts where no mutation
is necessary. Inherits from new templated baseclass CallSiteBase<>
which is highly customizable. Base CallSite on it too, in a configuration
that allows full mutation.
Adapt some call sites in analyses to employ ImmutableCallSite.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100100 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support')
-rw-r--r-- | include/llvm/Support/CallSite.h | 272 |
1 files changed, 160 insertions, 112 deletions
diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 480535f..9f527e2 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -8,15 +8,18 @@ //===----------------------------------------------------------------------===// // // This file defines the CallSite class, which is a handy wrapper for code that -// wants to treat Call and Invoke instructions in a generic way. +// wants to treat Call and Invoke instructions in a generic way. When in non- +// mutation context (e.g. an analysis) ImmutableCallSite should be used. +// Finally, when some degree of customization is necessary between these two +// extremes, CallSiteBase<> can be supplied with fine-tuned parameters. // -// NOTE: This class is supposed to have "value semantics". So it should be -// passed by value, not by reference; it should not be "new"ed or "delete"d. It -// is efficiently copyable, assignable and constructable, with cost equivalent -// to copying a pointer (notice that it has only a single data member). -// The internal representation carries a flag which indicates which of the two -// variants is enclosed. This allows for cheaper checks when various accessors -// of CallSite are employed. +// NOTE: These classes are supposed to have "value semantics". So they should be +// passed by value, not by reference; they should not be "new"ed or "delete"d. +// They are efficiently copyable, assignable and constructable, with cost +// equivalent to copying a pointer (notice that they have only a single data +// member). The internal representation carries a flag which indicates which of +// the two variants is enclosed. This allows for cheaper checks when various +// accessors of CallSite are employed. // //===----------------------------------------------------------------------===// @@ -34,72 +37,42 @@ namespace llvm { class CallInst; class InvokeInst; -class CallSite { - PointerIntPair<Instruction*, 1, bool> I; +template <typename FunTy = const Function, + typename ValTy = const Value, + typename UserTy = const User, + typename InstrTy = const Instruction, + typename CallTy = const CallInst, + typename InvokeTy = const InvokeInst, + typename IterTy = User::const_op_iterator> +class CallSiteBase { +protected: + PointerIntPair<InstrTy*, 1, bool> I; public: - CallSite() : I(0, false) {} - CallSite(CallInst *CI) : I(reinterpret_cast<Instruction*>(CI), true) {} - CallSite(InvokeInst *II) : I(reinterpret_cast<Instruction*>(II), false) {} - CallSite(Instruction *C); - - bool operator==(const CallSite &CS) const { return I == CS.I; } - bool operator!=(const CallSite &CS) const { return I != CS.I; } + CallSiteBase() : I(0, false) {} + CallSiteBase(CallTy *CI) : I(reinterpret_cast<InstrTy*>(CI), true) {} + CallSiteBase(InvokeTy *II) : I(reinterpret_cast<InstrTy*>(II), false) {} + CallSiteBase(ValTy *II) { *this = get(II); } + CallSiteBase(InstrTy *II) { + assert(II && "Null instruction given?"); + *this = get(II); + assert(I.getPointer()); + } - /// CallSite::get - This static method is sort of like a constructor. It will - /// create an appropriate call site for a Call or Invoke instruction, but it - /// can also create a null initialized CallSite object for something which is - /// NOT a call site. + /// CallSiteBase::get - This static method is sort of like a constructor. It + /// will create an appropriate call site for a Call or Invoke instruction, but + /// it can also create a null initialized CallSiteBase object for something + /// which is NOT a call site. /// - static CallSite get(Value *V) { - if (Instruction *I = dyn_cast<Instruction>(V)) { - if (I->getOpcode() == Instruction::Call) - return CallSite(reinterpret_cast<CallInst*>(I)); - else if (I->getOpcode() == Instruction::Invoke) - return CallSite(reinterpret_cast<InvokeInst*>(I)); + static CallSiteBase get(ValTy *V) { + if (InstrTy *II = dyn_cast<InstrTy>(V)) { + if (II->getOpcode() == Instruction::Call) + return CallSiteBase(reinterpret_cast<CallTy*>(II)); + else if (II->getOpcode() == Instruction::Invoke) + return CallSiteBase(reinterpret_cast<InvokeTy*>(II)); } - return CallSite(); + return CallSiteBase(); } - /// getCallingConv/setCallingConv - get or set the calling convention of the - /// call. - CallingConv::ID getCallingConv() const; - void setCallingConv(CallingConv::ID CC); - - /// getAttributes/setAttributes - get or set the parameter attributes of - /// the call. - const AttrListPtr &getAttributes() const; - void setAttributes(const AttrListPtr &PAL); - - /// paramHasAttr - whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, Attributes attr) const; - - /// @brief Extract the alignment for a call or parameter (0=unknown). - uint16_t getParamAlignment(uint16_t i) const; - - /// @brief Return true if the call should not be inlined. - bool isNoInline() const; - void setIsNoInline(bool Value = true); - - /// @brief Determine if the call does not access memory. - bool doesNotAccessMemory() const; - void setDoesNotAccessMemory(bool doesNotAccessMemory = true); - - /// @brief Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const; - void setOnlyReadsMemory(bool onlyReadsMemory = true); - - /// @brief Determine if the call cannot return. - bool doesNotReturn() const; - void setDoesNotReturn(bool doesNotReturn = true); - - /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const; - void setDoesNotThrow(bool doesNotThrow = true); - - /// getType - Return the type of the instruction that generated this call site - /// - const Type *getType() const { return getInstruction()->getType(); } - /// isCall - true if a CallInst is enclosed. /// Note that !isCall() does not mean it is an InvokeInst enclosed, /// it also could signify a NULL Instruction pointer. @@ -109,18 +82,13 @@ public: /// bool isInvoke() const { return getInstruction() && !I.getInt(); } - /// getInstruction - Return the instruction this call site corresponds to - /// - Instruction *getInstruction() const { return I.getPointer(); } - - /// getCaller - Return the caller function for this call site - /// - Function *getCaller() const { return getInstruction() - ->getParent()->getParent(); } + InstrTy *getInstruction() const { return I.getPointer(); } + InstrTy *operator->() const { return I.getPointer(); } + operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called... /// - Value *getCalledValue() const { + ValTy *getCalledValue() const { assert(getInstruction() && "Not a call or invoke instruction!"); return *getCallee(); } @@ -128,8 +96,8 @@ public: /// getCalledFunction - Return the function being called if this is a direct /// call, otherwise return null (if it's an indirect call). /// - Function *getCalledFunction() const { - return dyn_cast<Function>(getCalledValue()); + FunTy *getCalledFunction() const { + return dyn_cast<FunTy>(getCalledValue()); } /// setCalledFunction - Set the callee to the specified value... @@ -139,7 +107,14 @@ public: *getCallee() = V; } - Value *getArgument(unsigned ArgNo) const { + /// isCallee - Determine whether the passed iterator points to the + /// callee operand's Use. + /// + bool isCallee(value_use_iterator<UserTy> UI) const { + return getCallee() == &UI.getUse(); + } + + ValTy *getArgument(unsigned ArgNo) const { assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); return *(arg_begin()+ArgNo); } @@ -152,69 +127,142 @@ public: /// Given a value use iterator, returns the argument that corresponds to it. /// Iterator must actually correspond to an argument. - unsigned getArgumentNo(Value::use_iterator I) const { + unsigned getArgumentNo(value_use_iterator<UserTy> I) const { assert(getInstruction() && "Not a call or invoke instruction!"); assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end() && "Argument # out of range!"); - return &I.getUse() - arg_begin(); } - /// Given an operand number, returns the argument that corresponds to it. - /// OperandNo must be a valid operand number that actually corresponds to an - /// argument. - unsigned getArgumentNo(unsigned OperandNo) const { - assert(OperandNo >= getArgumentOffset() && "Operand number passed was not " - "a valid argument"); - return OperandNo - getArgumentOffset(); - } - - /// hasArgument - Returns true if this CallSite passes the given Value* as an - /// argument to the called function. - bool hasArgument(const Value *Arg) const; - /// arg_iterator - The type of iterator to use when looping over actual /// arguments at this call site... - typedef User::op_iterator arg_iterator; + typedef IterTy arg_iterator; /// arg_begin/arg_end - Return iterators corresponding to the actual argument /// list for a call site. - arg_iterator arg_begin() const { + IterTy arg_begin() const { assert(getInstruction() && "Not a call or invoke instruction!"); // Skip non-arguments - return getInstruction()->op_begin() + getArgumentOffset(); + return (*this)->op_begin() + getArgumentOffset(); } - arg_iterator arg_end() const { return getInstruction()->op_end() - getArgumentEndOffset(); } + IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - - bool operator<(const CallSite &CS) const { - return getInstruction() < CS.getInstruction(); - } - - bool isCallee(Value::use_iterator UI) const { - return getCallee() == &UI.getUse(); - } - bool isCallee(Value::const_use_iterator UI) const { - return getCallee() == &UI.getUse(); - } + private: /// Returns the operand number of the first argument unsigned getArgumentOffset() const { if (isCall()) - return 1; // Skip Function + return 1; // Skip Function (ATM) else return 0; // Args are at the front } unsigned getArgumentEndOffset() const { if (isCall()) - return 0; // Unchanged + return 0; // Unchanged (ATM) else return 3; // Skip BB, BB, Function } + IterTy getCallee() const { + // FIXME: this is slow, since we do not have the fast versions + // of the op_*() functions here. See CallSite::getCallee. + // + if (isCall()) + return getInstruction()->op_begin(); // Unchanged (ATM) + else + return getInstruction()->op_end() - 3; // Skip BB, BB, Function + } +}; + +/// ImmutableCallSite - establish a view to a call site for examination +class ImmutableCallSite : public CallSiteBase<> { + typedef CallSiteBase<> _Base; +public: + ImmutableCallSite(const Value* V) : _Base(V) {} + ImmutableCallSite(const CallInst *CI) : _Base(CI) {} + ImmutableCallSite(const InvokeInst *II) : _Base(II) {} + ImmutableCallSite(const Instruction *II) : _Base(II) {} +}; + +class CallSite : public CallSiteBase<Function, Value, User, Instruction, + CallInst, InvokeInst, User::op_iterator> { + typedef CallSiteBase<Function, Value, User, Instruction, + CallInst, InvokeInst, User::op_iterator> _Base; +public: + CallSite() {} + CallSite(_Base B) : _Base(B) {} + CallSite(CallInst *CI) : _Base(CI) {} + CallSite(InvokeInst *II) : _Base(II) {} + CallSite(Instruction *II) : _Base(II) {} + + bool operator==(const CallSite &CS) const { return I == CS.I; } + bool operator!=(const CallSite &CS) const { return I != CS.I; } + + /// CallSite::get - This static method is sort of like a constructor. It will + /// create an appropriate call site for a Call or Invoke instruction, but it + /// can also create a null initialized CallSite object for something which is + /// NOT a call site. + /// + static CallSite get(Value *V) { + return _Base::get(V); + } + + /// getCallingConv/setCallingConv - get or set the calling convention of the + /// call. + CallingConv::ID getCallingConv() const; + void setCallingConv(CallingConv::ID CC); + + /// getAttributes/setAttributes - get or set the parameter attributes of + /// the call. + const AttrListPtr &getAttributes() const; + void setAttributes(const AttrListPtr &PAL); + + /// paramHasAttr - whether the call or the callee has the given attribute. + bool paramHasAttr(uint16_t i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + uint16_t getParamAlignment(uint16_t i) const; + + /// @brief Return true if the call should not be inlined. + bool isNoInline() const; + void setIsNoInline(bool Value = true); + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const; + void setDoesNotAccessMemory(bool doesNotAccessMemory = true); + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const; + void setOnlyReadsMemory(bool onlyReadsMemory = true); + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const; + void setDoesNotReturn(bool doesNotReturn = true); + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const; + void setDoesNotThrow(bool doesNotThrow = true); + + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType() const { return (*this)->getType(); } + + /// getCaller - Return the caller function for this call site + /// + Function *getCaller() const { return (*this)->getParent()->getParent(); } + + /// hasArgument - Returns true if this CallSite passes the given Value* as an + /// argument to the called function. + bool hasArgument(const Value *Arg) const; + + bool operator<(const CallSite &CS) const { + return getInstruction() < CS.getInstruction(); + } + +private: User::op_iterator getCallee() const; }; |