#ifndef LLVM_IR_VALUE_H
#define LLVM_IR_VALUE_H
#include "llvm-c/Core.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Use.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class APInt;
class Argument;
class AssemblyAnnotationWriter;
class BasicBlock;
class Constant;
class DataLayout;
class Function;
class GlobalAlias;
class GlobalObject;
class GlobalValue;
class GlobalVariable;
class InlineAsm;
class Instruction;
class LLVMContext;
class MDNode;
class Module;
class StringRef;
class Twine;
class Type;
class ValueHandleBase;
class ValueSymbolTable;
class raw_ostream;
template<typename ValueTy> class StringMapEntry;
typedef StringMapEntry<Value*> ValueName;
class Value {
Type *VTy;
Use *UseList;
friend class ValueSymbolTable; friend class ValueHandleBase;
ValueName *Name;
const unsigned char SubclassID; unsigned char HasValueHandle : 1; protected:
unsigned char SubclassOptionalData : 7;
private:
unsigned short SubclassData;
template <typename UseT> class use_iterator_impl
: public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super;
UseT *U;
explicit use_iterator_impl(UseT *u) : U(u) {}
friend class Value;
public:
typedef typename super::reference reference;
typedef typename super::pointer pointer;
use_iterator_impl() : U() {}
bool operator==(const use_iterator_impl &x) const { return U == x.U; }
bool operator!=(const use_iterator_impl &x) const { return !operator==(x); }
use_iterator_impl &operator++() { assert(U && "Cannot increment end iterator!");
U = U->getNext();
return *this;
}
use_iterator_impl operator++(int) { auto tmp = *this;
++*this;
return tmp;
}
UseT &operator*() const {
assert(U && "Cannot dereference end iterator!");
return *U;
}
UseT *operator->() const { return &operator*(); }
operator use_iterator_impl<const UseT>() const {
return use_iterator_impl<const UseT>(U);
}
};
template <typename UserTy> class user_iterator_impl
: public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> {
typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super;
use_iterator_impl<Use> UI;
explicit user_iterator_impl(Use *U) : UI(U) {}
friend class Value;
public:
typedef typename super::reference reference;
typedef typename super::pointer pointer;
user_iterator_impl() {}
bool operator==(const user_iterator_impl &x) const { return UI == x.UI; }
bool operator!=(const user_iterator_impl &x) const { return !operator==(x); }
bool atEnd() const { return *this == user_iterator_impl(); }
user_iterator_impl &operator++() { ++UI;
return *this;
}
user_iterator_impl operator++(int) { auto tmp = *this;
++*this;
return tmp;
}
UserTy *operator*() const {
return UI->getUser();
}
UserTy *operator->() const { return operator*(); }
operator user_iterator_impl<const UserTy>() const {
return user_iterator_impl<const UserTy>(*UI);
}
Use &getUse() const { return *UI; }
unsigned getOperandNo() const { return UI->getOperandNo(); }
};
void operator=(const Value &) LLVM_DELETED_FUNCTION;
Value(const Value &) LLVM_DELETED_FUNCTION;
protected:
Value(Type *Ty, unsigned scid);
public:
virtual ~Value();
void dump() const;
void print(raw_ostream &O) const;
void printAsOperand(raw_ostream &O, bool PrintType = true,
const Module *M = nullptr) const;
Type *getType() const { return VTy; }
LLVMContext &getContext() const;
bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; }
ValueName *getValueName() const { return Name; }
void setValueName(ValueName *VN) { Name = VN; }
StringRef getName() const;
void setName(const Twine &Name);
void takeName(Value *V);
void replaceAllUsesWith(Value *V);
bool use_empty() const { return UseList == nullptr; }
typedef use_iterator_impl<Use> use_iterator;
typedef use_iterator_impl<const Use> const_use_iterator;
use_iterator use_begin() { return use_iterator(UseList); }
const_use_iterator use_begin() const { return const_use_iterator(UseList); }
use_iterator use_end() { return use_iterator(); }
const_use_iterator use_end() const { return const_use_iterator(); }
iterator_range<use_iterator> uses() {
return iterator_range<use_iterator>(use_begin(), use_end());
}
iterator_range<const_use_iterator> uses() const {
return iterator_range<const_use_iterator>(use_begin(), use_end());
}
typedef user_iterator_impl<User> user_iterator;
typedef user_iterator_impl<const User> const_user_iterator;
user_iterator user_begin() { return user_iterator(UseList); }
const_user_iterator user_begin() const { return const_user_iterator(UseList); }
user_iterator user_end() { return user_iterator(); }
const_user_iterator user_end() const { return const_user_iterator(); }
User *user_back() { return *user_begin(); }
const User *user_back() const { return *user_begin(); }
iterator_range<user_iterator> users() {
return iterator_range<user_iterator>(user_begin(), user_end());
}
iterator_range<const_user_iterator> users() const {
return iterator_range<const_user_iterator>(user_begin(), user_end());
}
bool hasOneUse() const {
const_use_iterator I = use_begin(), E = use_end();
if (I == E) return false;
return ++I == E;
}
bool hasNUses(unsigned N) const;
bool hasNUsesOrMore(unsigned N) const;
bool isUsedInBasicBlock(const BasicBlock *BB) const;
unsigned getNumUses() const;
void addUse(Use &U) { U.addToList(&UseList); }
enum ValueTy {
ArgumentVal, BasicBlockVal, FunctionVal, GlobalAliasVal, GlobalVariableVal, UndefValueVal, BlockAddressVal, ConstantExprVal, ConstantAggregateZeroVal, ConstantDataArrayVal, ConstantDataVectorVal, ConstantIntVal, ConstantFPVal, ConstantArrayVal, ConstantStructVal, ConstantVectorVal, ConstantPointerNullVal, MDNodeVal, MDStringVal, InlineAsmVal, InstructionVal,
ConstantFirstVal = FunctionVal,
ConstantLastVal = ConstantPointerNullVal
};
unsigned getValueID() const {
return SubclassID;
}
unsigned getRawSubclassOptionalData() const {
return SubclassOptionalData;
}
void clearSubclassOptionalData() {
SubclassOptionalData = 0;
}
bool hasSameSubclassOptionalData(const Value *V) const {
return SubclassOptionalData == V->SubclassOptionalData;
}
void intersectOptionalDataWith(const Value *V) {
SubclassOptionalData &= V->SubclassOptionalData;
}
bool hasValueHandle() const { return HasValueHandle; }
Value *stripPointerCasts();
const Value *stripPointerCasts() const {
return const_cast<Value*>(this)->stripPointerCasts();
}
Value *stripPointerCastsNoFollowAliases();
const Value *stripPointerCastsNoFollowAliases() const {
return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
}
Value *stripInBoundsConstantOffsets();
const Value *stripInBoundsConstantOffsets() const {
return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
}
Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
APInt &Offset);
const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
APInt &Offset) const {
return const_cast<Value *>(this)
->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
}
Value *stripInBoundsOffsets();
const Value *stripInBoundsOffsets() const {
return const_cast<Value*>(this)->stripInBoundsOffsets();
}
bool isDereferenceablePointer(const DataLayout *DL = nullptr) const;
Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB);
const Value *DoPHITranslation(const BasicBlock *CurBB,
const BasicBlock *PredBB) const{
return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
}
static const unsigned MaximumAlignment = 1u << 29;
void mutateType(Type *Ty) {
VTy = Ty;
}
template <class Compare> void sortUseList(Compare Cmp);
void reverseUseList();
private:
template <class Compare>
static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) {
Use *Merged;
mergeUseListsImpl(L, R, &Merged, Cmp);
return Merged;
}
template <class Compare>
static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp);
protected:
unsigned short getSubclassDataFromValue() const { return SubclassData; }
void setValueSubclassData(unsigned short D) { SubclassData = D; }
};
inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) {
V.print(OS);
return OS;
}
void Use::set(Value *V) {
if (Val) removeFromList();
Val = V;
if (V) V->addUse(*this);
}
template <class Compare> void Value::sortUseList(Compare Cmp) {
if (!UseList || !UseList->Next)
return;
const unsigned MaxSlots = 32;
Use *Slots[MaxSlots];
Use *Next = UseList->Next;
UseList->Next = nullptr;
unsigned NumSlots = 1;
Slots[0] = UseList;
while (Next->Next) {
Use *Current = Next;
Next = Current->Next;
Current->Next = nullptr;
unsigned I;
for (I = 0; I < NumSlots; ++I) {
if (!Slots[I])
break;
Current = mergeUseLists(Slots[I], Current, Cmp);
Slots[I] = nullptr;
}
if (I == NumSlots) {
++NumSlots;
assert(NumSlots <= MaxSlots && "Use list bigger than 2^32");
}
Slots[I] = Current;
}
assert(Next && "Expected one more Use");
assert(!Next->Next && "Expected only one Use");
UseList = Next;
for (unsigned I = 0; I < NumSlots; ++I)
if (Slots[I])
UseList = mergeUseLists(Slots[I], UseList, Cmp);
for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) {
I->setPrev(Prev);
Prev = &I->Next;
}
}
template <class Compare>
void Value::mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp) {
if (!L) {
*Next = R;
return;
}
if (!R) {
*Next = L;
return;
}
if (Cmp(*R, *L)) {
*Next = R;
mergeUseListsImpl(L, R->Next, &R->Next, Cmp);
return;
}
*Next = L;
mergeUseListsImpl(L->Next, R, &L->Next, Cmp);
}
template <> struct isa_impl<Constant, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() >= Value::ConstantFirstVal &&
Val.getValueID() <= Value::ConstantLastVal;
}
};
template <> struct isa_impl<Argument, Value> {
static inline bool doit (const Value &Val) {
return Val.getValueID() == Value::ArgumentVal;
}
};
template <> struct isa_impl<InlineAsm, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::InlineAsmVal;
}
};
template <> struct isa_impl<Instruction, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() >= Value::InstructionVal;
}
};
template <> struct isa_impl<BasicBlock, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::BasicBlockVal;
}
};
template <> struct isa_impl<Function, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::FunctionVal;
}
};
template <> struct isa_impl<GlobalVariable, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::GlobalVariableVal;
}
};
template <> struct isa_impl<GlobalAlias, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::GlobalAliasVal;
}
};
template <> struct isa_impl<GlobalValue, Value> {
static inline bool doit(const Value &Val) {
return isa<GlobalObject>(Val) || isa<GlobalAlias>(Val);
}
};
template <> struct isa_impl<GlobalObject, Value> {
static inline bool doit(const Value &Val) {
return isa<GlobalVariable>(Val) || isa<Function>(Val);
}
};
template <> struct isa_impl<MDNode, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() == Value::MDNodeVal;
}
};
template<>
class PointerLikeTypeTraits<Value*> {
typedef Value* PT;
public:
static inline void *getAsVoidPointer(PT P) { return P; }
static inline PT getFromVoidPointer(void *P) {
return static_cast<PT>(P);
}
enum { NumLowBitsAvailable = 2 };
};
DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef)
inline Value **unwrap(LLVMValueRef *Vals) {
return reinterpret_cast<Value**>(Vals);
}
template<typename T>
inline T **unwrap(LLVMValueRef *Vals, unsigned Length) {
#ifdef DEBUG
for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I)
cast<T>(*I);
#endif
(void)Length;
return reinterpret_cast<T**>(Vals);
}
inline LLVMValueRef *wrap(const Value **Vals) {
return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals));
}
}
#endif