#ifndef LLVM_SUPPORT_CALLSITE_H
#define LLVM_SUPPORT_CALLSITE_H
#include "llvm/Attributes.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/BasicBlock.h"
#include "llvm/CallingConv.h"
#include "llvm/Instructions.h"
namespace llvm {
class CallInst;
class InvokeInst;
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:
CallSiteBase() : I(0, false) {}
CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); }
CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); }
CallSiteBase(ValTy *II) { *this = get(II); }
protected:
static CallSiteBase get(ValTy *V) {
if (InstrTy *II = dyn_cast<InstrTy>(V)) {
if (II->getOpcode() == Instruction::Call)
return CallSiteBase(static_cast<CallTy*>(II));
else if (II->getOpcode() == Instruction::Invoke)
return CallSiteBase(static_cast<InvokeTy*>(II));
}
return CallSiteBase();
}
public:
bool isCall() const { return I.getInt(); }
bool isInvoke() const { return getInstruction() && !I.getInt(); }
InstrTy *getInstruction() const { return I.getPointer(); }
InstrTy *operator->() const { return I.getPointer(); }
operator bool() const { return I.getPointer(); }
ValTy *getCalledValue() const {
assert(getInstruction() && "Not a call or invoke instruction!");
return *getCallee();
}
FunTy *getCalledFunction() const {
return dyn_cast<FunTy>(getCalledValue());
}
void setCalledFunction(Value *V) {
assert(getInstruction() && "Not a call or invoke instruction!");
*getCallee() = V;
}
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);
}
void setArgument(unsigned ArgNo, Value* newVal) {
assert(getInstruction() && "Not a call or invoke instruction!");
assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!");
getInstruction()->setOperand(ArgNo, newVal);
}
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();
}
typedef IterTy arg_iterator;
IterTy arg_begin() const {
assert(getInstruction() && "Not a call or invoke instruction!");
return (*this)->op_begin();
}
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()); }
Type *getType() const { return (*this)->getType(); }
FunTy *getCaller() const { return (*this)->getParent()->getParent(); }
#define CALLSITE_DELEGATE_GETTER(METHOD) \
InstrTy *II = getInstruction(); \
return isCall() \
? cast<CallInst>(II)->METHOD \
: cast<InvokeInst>(II)->METHOD
#define CALLSITE_DELEGATE_SETTER(METHOD) \
InstrTy *II = getInstruction(); \
if (isCall()) \
cast<CallInst>(II)->METHOD; \
else \
cast<InvokeInst>(II)->METHOD
CallingConv::ID getCallingConv() const {
CALLSITE_DELEGATE_GETTER(getCallingConv());
}
void setCallingConv(CallingConv::ID CC) {
CALLSITE_DELEGATE_SETTER(setCallingConv(CC));
}
const AttrListPtr &getAttributes() const {
CALLSITE_DELEGATE_GETTER(getAttributes());
}
void setAttributes(const AttrListPtr &PAL) {
CALLSITE_DELEGATE_SETTER(setAttributes(PAL));
}
bool paramHasAttr(uint16_t i, Attributes attr) const {
CALLSITE_DELEGATE_GETTER(paramHasAttr(i, attr));
}
uint16_t getParamAlignment(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getParamAlignment(i));
}
bool isNoInline() const {
CALLSITE_DELEGATE_GETTER(isNoInline());
}
void setIsNoInline(bool Value = true) {
CALLSITE_DELEGATE_SETTER(setIsNoInline(Value));
}
bool doesNotAccessMemory() const {
CALLSITE_DELEGATE_GETTER(doesNotAccessMemory());
}
void setDoesNotAccessMemory(bool doesNotAccessMemory = true) {
CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory(doesNotAccessMemory));
}
bool onlyReadsMemory() const {
CALLSITE_DELEGATE_GETTER(onlyReadsMemory());
}
void setOnlyReadsMemory(bool onlyReadsMemory = true) {
CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory(onlyReadsMemory));
}
bool doesNotReturn() const {
CALLSITE_DELEGATE_GETTER(doesNotReturn());
}
void setDoesNotReturn(bool doesNotReturn = true) {
CALLSITE_DELEGATE_SETTER(setDoesNotReturn(doesNotReturn));
}
bool doesNotThrow() const {
CALLSITE_DELEGATE_GETTER(doesNotThrow());
}
void setDoesNotThrow(bool doesNotThrow = true) {
CALLSITE_DELEGATE_SETTER(setDoesNotThrow(doesNotThrow));
}
#undef CALLSITE_DELEGATE_GETTER
#undef CALLSITE_DELEGATE_SETTER
bool hasArgument(const Value *Arg) const {
for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E;
++AI)
if (AI->get() == Arg)
return true;
return false;
}
private:
unsigned getArgumentEndOffset() const {
if (isCall())
return 1; else
return 3; }
IterTy getCallee() const {
if (isCall()) return cast<CallInst>(getInstruction())->op_end() - 1;
else return cast<InvokeInst>(getInstruction())->op_end() - 3;
}
};
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(Value* V) : Base(V) {}
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; }
bool operator<(const CallSite &CS) const {
return getInstruction() < CS.getInstruction();
}
private:
User::op_iterator getCallee() const;
};
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) {}
ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {}
};
}
#endif