#ifndef LLVM_IR_FUNCTION_H
#define LLVM_IR_FUNCTION_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/GlobalObject.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 GlobalObject, 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; AttributeSet AttributeSets;
enum {
IsMaterializableBit = 1 << 0,
HasMetadataHashEntryBit = 1 << 1
};
void setGlobalObjectBit(unsigned Mask, bool Value) {
setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
(Value ? Mask : 0u));
}
friend class SymbolTableListTraits<Function, Module>;
void setParent(Module *parent);
bool hasLazyArguments() const {
return getSubclassDataFromValue() & (1<<0);
}
void CheckLazyArguments() const {
if (hasLazyArguments())
BuildLazyArguments();
}
void BuildLazyArguments() const;
Function(const Function&) LLVM_DELETED_FUNCTION;
void operator=(const Function&) LLVM_DELETED_FUNCTION;
unsigned lookupIntrinsicID() const LLVM_READONLY;
Function(FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = nullptr);
public:
static Function *Create(FunctionType *Ty, LinkageTypes Linkage,
const Twine &N = "", Module *M = nullptr) {
return new(0) Function(Ty, Linkage, N, M);
}
~Function();
Type *getReturnType() const; FunctionType *getFunctionType() const;
LLVMContext &getContext() const;
bool isVarArg() const;
bool isMaterializable() const;
void setIsMaterializable(bool V);
unsigned getIntrinsicID() const LLVM_READONLY;
bool isIntrinsic() const { return getName().startswith("llvm."); }
CallingConv::ID getCallingConv() const {
return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3);
}
void setCallingConv(CallingConv::ID CC) {
setValueSubclassData((getSubclassDataFromValue() & 7) |
(static_cast<unsigned>(CC) << 3));
}
AttributeSet getAttributes() const { return AttributeSets; }
void setAttributes(AttributeSet attrs) { AttributeSets = attrs; }
void addFnAttr(Attribute::AttrKind N) {
setAttributes(AttributeSets.addAttribute(getContext(),
AttributeSet::FunctionIndex, N));
}
void removeFnAttr(Attribute::AttrKind N) {
setAttributes(AttributeSets.removeAttribute(
getContext(), AttributeSet::FunctionIndex, N));
}
void addFnAttr(StringRef Kind) {
setAttributes(
AttributeSets.addAttribute(getContext(),
AttributeSet::FunctionIndex, Kind));
}
void addFnAttr(StringRef Kind, StringRef Value) {
setAttributes(
AttributeSets.addAttribute(getContext(),
AttributeSet::FunctionIndex, Kind, Value));
}
bool hasFnAttribute(Attribute::AttrKind Kind) const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
}
bool hasFnAttribute(StringRef Kind) const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
}
Attribute getFnAttribute(Attribute::AttrKind Kind) const {
return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
}
Attribute getFnAttribute(StringRef Kind) const {
return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
}
unsigned getFnStackAlignment() const {
return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
}
bool hasGC() const;
const char *getGC() const;
void setGC(const char *Str);
void clearGC();
void addAttribute(unsigned i, Attribute::AttrKind attr);
void addAttributes(unsigned i, AttributeSet attrs);
void removeAttributes(unsigned i, AttributeSet attr);
unsigned getParamAlignment(unsigned i) const {
return AttributeSets.getParamAlignment(i);
}
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeSets.getDereferenceableBytes(i);
}
bool doesNotAccessMemory() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
addFnAttr(Attribute::ReadNone);
}
bool onlyReadsMemory() const {
return doesNotAccessMemory() ||
AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
addFnAttr(Attribute::ReadOnly);
}
bool doesNotReturn() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::NoReturn);
}
void setDoesNotReturn() {
addFnAttr(Attribute::NoReturn);
}
bool doesNotThrow() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::NoUnwind);
}
void setDoesNotThrow() {
addFnAttr(Attribute::NoUnwind);
}
bool cannotDuplicate() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::NoDuplicate);
}
void setCannotDuplicate() {
addFnAttr(Attribute::NoDuplicate);
}
bool hasUWTable() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::UWTable);
}
void setHasUWTable() {
addFnAttr(Attribute::UWTable);
}
bool needsUnwindTableEntry() const {
return hasUWTable() || !doesNotThrow();
}
bool hasStructRetAttr() const {
return AttributeSets.hasAttribute(1, Attribute::StructRet) ||
AttributeSets.hasAttribute(2, Attribute::StructRet);
}
bool doesNotAlias(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::NoAlias);
}
void setDoesNotAlias(unsigned n) {
addAttribute(n, Attribute::NoAlias);
}
bool doesNotCapture(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::NoCapture);
}
void setDoesNotCapture(unsigned n) {
addAttribute(n, Attribute::NoCapture);
}
bool doesNotAccessMemory(unsigned n) const {
return AttributeSets.hasAttribute(n, Attribute::ReadNone);
}
void setDoesNotAccessMemory(unsigned n) {
addAttribute(n, Attribute::ReadNone);
}
bool onlyReadsMemory(unsigned n) const {
return doesNotAccessMemory(n) ||
AttributeSets.hasAttribute(n, Attribute::ReadOnly);
}
void setOnlyReadsMemory(unsigned n) {
addAttribute(n, Attribute::ReadOnly);
}
void copyAttributesFrom(const GlobalValue *Src) override;
void deleteBody() {
dropAllReferences();
setLinkage(ExternalLinkage);
}
void removeFromParent() override;
void eraseFromParent() override;
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();
}
iterator_range<arg_iterator> args() {
return iterator_range<arg_iterator>(arg_begin(), arg_end());
}
iterator_range<const_arg_iterator> args() const {
return iterator_range<const_arg_iterator>(arg_begin(), arg_end());
}
size_t arg_size() const;
bool arg_empty() const;
bool hasPrefixData() const {
return getSubclassDataFromValue() & (1<<1);
}
Constant *getPrefixData() const;
void setPrefixData(Constant *PrefixData);
bool hasPrologueData() const {
return getSubclassDataFromValue() & (1<<2);
}
Constant *getPrologueData() const;
void setPrologueData(Constant *PrologueData);
void viewCFG() const;
void viewCFGOnly() const;
static inline bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal;
}
void dropAllReferences();
bool hasAddressTaken(const User** = nullptr) const;
bool isDefTriviallyDead() const;
bool callsFunctionThatReturnsTwice() const;
bool hasMetadata() const { return hasMetadataHashEntry(); }
MDNode *getMetadata(unsigned KindID) const;
MDNode *getMetadata(StringRef Kind) const;
void setMetadata(unsigned KindID, MDNode *MD);
void setMetadata(StringRef Kind, MDNode *MD);
void
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
private:
void setValueSubclassData(unsigned short D) {
Value::setValueSubclassData(D);
}
bool hasMetadataHashEntry() const {
return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
}
void setHasMetadataHashEntry(bool HasEntry) {
setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
}
void clearMetadata();
};
inline ValueSymbolTable *
ilist_traits<BasicBlock>::getSymTab(Function *F) {
return F ? &F->getValueSymbolTable() : nullptr;
}
inline ValueSymbolTable *
ilist_traits<Argument>::getSymTab(Function *F) {
return F ? &F->getValueSymbolTable() : nullptr;
}
void overrideFunctionAttribute(StringRef Kind, StringRef Value, Function &F);
}
#endif