#ifndef LLVM_FUNCTION_H
#define LLVM_FUNCTION_H
#include "llvm/GlobalValue.h"
#include "llvm/CallingConv.h"
#include "llvm/BasicBlock.h"
#include "llvm/Argument.h"
#include "llvm/Attributes.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class FunctionType;
class LLVMContext;
template<> struct ilist_traits<BasicBlock>
: public SymbolTableListTraits<BasicBlock, Function> {
BasicBlock *createSentinel() const {
return static_cast<BasicBlock*>(&Sentinel);
}
static void destroySentinel(BasicBlock*) {}
BasicBlock *provideInitialHead() const { return createSentinel(); }
BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
static void noteHead(BasicBlock*, BasicBlock*) {}
static ValueSymbolTable *getSymTab(Function *ItemParent);
private:
mutable ilist_half_node<BasicBlock> Sentinel;
};
template<> struct ilist_traits<Argument>
: public SymbolTableListTraits<Argument, Function> {
Argument *createSentinel() const {
return static_cast<Argument*>(&Sentinel);
}
static void destroySentinel(Argument*) {}
Argument *provideInitialHead() const { return createSentinel(); }
Argument *ensureHead(Argument*) const { return createSentinel(); }
static void noteHead(Argument*, Argument*) {}
static ValueSymbolTable *getSymTab(Function *ItemParent);
private:
mutable ilist_half_node<Argument> Sentinel;
};
class Function : public GlobalValue,
public ilist_node<Function> {
public:
typedef iplist<Argument> ArgumentListType;
typedef iplist<BasicBlock> BasicBlockListType;
typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator;
typedef ArgumentListType::iterator arg_iterator;
typedef ArgumentListType::const_iterator const_arg_iterator;
private:
BasicBlockListType BasicBlocks; mutable ArgumentListType ArgumentList; ValueSymbolTable *SymTab; AttrListPtr AttributeList;
friend class SymbolTableListTraits<Function, Module>;
void setParent(Module *parent);
bool hasLazyArguments() const {
return getSubclassDataFromValue() & 1;
}
void CheckLazyArguments() const {
if (hasLazyArguments())
BuildLazyArguments();
}
void BuildLazyArguments() const;
Function(const Function&); void operator=(const Function&);
Function(const FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = 0);
public:
static Function *Create(const FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = 0) {
return new(0) Function(Ty, Linkage, N, M);
}
~Function();
const Type *getReturnType() const; const FunctionType *getFunctionType() const;
LLVMContext &getContext() const;
bool isVarArg() const;
virtual bool isDeclaration() const { return BasicBlocks.empty(); }
unsigned getIntrinsicID() const ATTRIBUTE_READONLY;
bool isIntrinsic() const { return getIntrinsicID() != 0; }
CallingConv::ID getCallingConv() const {
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1);
}
void setCallingConv(CallingConv::ID CC) {
setValueSubclassData((getSubclassDataFromValue() & 1) |
(static_cast<unsigned>(CC) << 1));
}
const AttrListPtr &getAttributes() const { return AttributeList; }
void setAttributes(const AttrListPtr &attrs) { AttributeList = attrs; }
bool hasFnAttr(Attributes N) const {
return AttributeList.paramHasAttr(~0U, N);
}
void addFnAttr(Attributes N) {
addAttribute(~0U, N);
}
void removeFnAttr(Attributes N) {
removeAttribute(~0U, N);
}
bool hasGC() const;
const char *getGC() const;
void setGC(const char *Str);
void clearGC();
bool paramHasAttr(unsigned i, Attributes attr) const {
return AttributeList.paramHasAttr(i, attr);
}
void addAttribute(unsigned i, Attributes attr);
void removeAttribute(unsigned i, Attributes attr);
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
}
bool doesNotAccessMemory() const {
return hasFnAttr(Attribute::ReadNone);
}
void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) {
if (DoesNotAccessMemory) addFnAttr(Attribute::ReadNone);
else removeFnAttr(Attribute::ReadNone);
}
bool onlyReadsMemory() const {
return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
}
void setOnlyReadsMemory(bool OnlyReadsMemory = true) {
if (OnlyReadsMemory) addFnAttr(Attribute::ReadOnly);
else removeFnAttr(Attribute::ReadOnly | Attribute::ReadNone);
}
bool doesNotReturn() const {
return hasFnAttr(Attribute::NoReturn);
}
void setDoesNotReturn(bool DoesNotReturn = true) {
if (DoesNotReturn) addFnAttr(Attribute::NoReturn);
else removeFnAttr(Attribute::NoReturn);
}
bool doesNotThrow() const {
return hasFnAttr(Attribute::NoUnwind);
}
void setDoesNotThrow(bool DoesNotThrow = true) {
if (DoesNotThrow) addFnAttr(Attribute::NoUnwind);
else removeFnAttr(Attribute::NoUnwind);
}
bool hasStructRetAttr() const {
return paramHasAttr(1, Attribute::StructRet);
}
bool doesNotAlias(unsigned n) const {
return paramHasAttr(n, Attribute::NoAlias);
}
void setDoesNotAlias(unsigned n, bool DoesNotAlias = true) {
if (DoesNotAlias) addAttribute(n, Attribute::NoAlias);
else removeAttribute(n, Attribute::NoAlias);
}
bool doesNotCapture(unsigned n) const {
return paramHasAttr(n, Attribute::NoCapture);
}
void setDoesNotCapture(unsigned n, bool DoesNotCapture = true) {
if (DoesNotCapture) addAttribute(n, Attribute::NoCapture);
else removeAttribute(n, Attribute::NoCapture);
}
void copyAttributesFrom(const GlobalValue *Src);
void deleteBody() {
dropAllReferences();
setLinkage(ExternalLinkage);
}
virtual void removeFromParent();
virtual void eraseFromParent();
const ArgumentListType &getArgumentList() const {
CheckLazyArguments();
return ArgumentList;
}
ArgumentListType &getArgumentList() {
CheckLazyArguments();
return ArgumentList;
}
static iplist<Argument> Function::*getSublistAccess(Argument*) {
return &Function::ArgumentList;
}
const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; }
BasicBlockListType &getBasicBlockList() { return BasicBlocks; }
static iplist<BasicBlock> Function::*getSublistAccess(BasicBlock*) {
return &Function::BasicBlocks;
}
const BasicBlock &getEntryBlock() const { return front(); }
BasicBlock &getEntryBlock() { return front(); }
inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; }
inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; }
iterator begin() { return BasicBlocks.begin(); }
const_iterator begin() const { return BasicBlocks.begin(); }
iterator end () { return BasicBlocks.end(); }
const_iterator end () const { return BasicBlocks.end(); }
size_t size() const { return BasicBlocks.size(); }
bool empty() const { return BasicBlocks.empty(); }
const BasicBlock &front() const { return BasicBlocks.front(); }
BasicBlock &front() { return BasicBlocks.front(); }
const BasicBlock &back() const { return BasicBlocks.back(); }
BasicBlock &back() { return BasicBlocks.back(); }
arg_iterator arg_begin() {
CheckLazyArguments();
return ArgumentList.begin();
}
const_arg_iterator arg_begin() const {
CheckLazyArguments();
return ArgumentList.begin();
}
arg_iterator arg_end() {
CheckLazyArguments();
return ArgumentList.end();
}
const_arg_iterator arg_end() const {
CheckLazyArguments();
return ArgumentList.end();
}
size_t arg_size() const;
bool arg_empty() const;
void viewCFG() const;
void viewCFGOnly() const;
static inline bool classof(const Function *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal;
}
void dropAllReferences();
bool hasAddressTaken() const;
private:
void setValueSubclassData(unsigned short D) {
Value::setValueSubclassData(D);
}
};
inline ValueSymbolTable *
ilist_traits<BasicBlock>::getSymTab(Function *F) {
return F ? &F->getValueSymbolTable() : 0;
}
inline ValueSymbolTable *
ilist_traits<Argument>::getSymTab(Function *F) {
return F ? &F->getValueSymbolTable() : 0;
}
}
#endif