#ifndef LLVM_IR_FUNCTION_H
#define LLVM_IR_FUNCTION_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.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/IR/OperandTraits.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class FunctionType;
class LLVMContext;
class DISubprogram;
template <>
struct SymbolTableListSentinelTraits<Argument>
: public ilist_half_embedded_sentinel_traits<Argument> {};
class Function : public GlobalObject, public ilist_node<Function> {
public:
typedef SymbolTableList<Argument> ArgumentListType;
typedef SymbolTableList<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; FunctionType *Ty;
enum {
IsMaterializableBit = 1 << 0,
HasMetadataHashEntryBit = 1 << 1
};
void setGlobalObjectBit(unsigned Mask, bool Value) {
setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
(Value ? Mask : 0u));
}
friend class SymbolTableListTraits<Function>;
void setParent(Module *parent);
bool hasLazyArguments() const {
return getSubclassDataFromValue() & (1<<0);
}
void CheckLazyArguments() const {
if (hasLazyArguments())
BuildLazyArguments();
}
void BuildLazyArguments() const;
Function(const Function&) = delete;
void operator=(const Function&) = delete;
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(1) Function(Ty, Linkage, N, M);
}
~Function() override;
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
bool hasPersonalityFn() const { return getNumOperands() != 0; }
Constant *getPersonalityFn() const {
assert(hasPersonalityFn());
return cast<Constant>(Op<0>());
}
void setPersonalityFn(Constant *C);
Type *getReturnType() const; FunctionType *getFunctionType() const;
LLVMContext &getContext() const;
bool isVarArg() const;
bool isMaterializable() const;
void setIsMaterializable(bool V);
Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; }
bool isIntrinsic() const { return getName().startswith("llvm."); }
void recalculateIntrinsicID();
CallingConv::ID getCallingConv() const {
return static_cast<CallingConv::ID>((getSubclassDataFromValue() >> 4) &
CallingConv::MaxID);
}
void setCallingConv(CallingConv::ID CC) {
auto ID = static_cast<unsigned>(CC);
assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention");
setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4));
}
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));
}
void setEntryCount(uint64_t Count);
Optional<uint64_t> getEntryCount() const;
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);
void addDereferenceableAttr(unsigned i, uint64_t Bytes);
void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes);
unsigned getParamAlignment(unsigned i) const {
return AttributeSets.getParamAlignment(i);
}
uint64_t getDereferenceableBytes(unsigned i) const {
return AttributeSets.getDereferenceableBytes(i);
}
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
return AttributeSets.getDereferenceableOrNullBytes(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 onlyAccessesArgMemory() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); }
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 isConvergent() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Convergent);
}
void setConvergent() {
addFnAttr(Attribute::Convergent);
}
bool doesNotRecurse() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::NoRecurse);
}
void setDoesNotRecurse() {
addFnAttr(Attribute::NoRecurse);
}
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);
}
bool optForMinSize() const { return hasFnAttribute(Attribute::MinSize); };
bool optForSize() const {
return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize();
}
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 ArgumentListType Function::*getSublistAccess(Argument*) {
return &Function::ArgumentList;
}
const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; }
BasicBlockListType &getBasicBlockList() { return BasicBlocks; }
static BasicBlockListType 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);
void setSubprogram(DISubprogram *SP);
DISubprogram *getSubprogram() const;
private:
void setValueSubclassData(unsigned short D) {
Value::setValueSubclassData(D);
}
bool hasMetadataHashEntry() const {
return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
}
void setHasMetadataHashEntry(bool HasEntry) {
setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
}
void clearMetadata();
};
template <>
struct OperandTraits<Function> : public OptionalOperandTraits<Function> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value)
}
#endif