#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/InstrTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/ADT/DenseMap.h"
#include <algorithm>
using namespace llvm;
static inline const Type *checkType(const Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
return Ty;
}
Value::Value(const Type *ty, unsigned scid)
: SubclassID(scid), HasValueHandle(0), SubclassData(0), VTy(checkType(ty)),
UseList(0), Name(0) {
if (isa<CallInst>(this) || isa<InvokeInst>(this))
assert((VTy->isFirstClassType() || VTy == Type::VoidTy ||
isa<OpaqueType>(ty) || VTy->getTypeID() == Type::StructTyID) &&
"invalid CallInst type!");
else if (!isa<Constant>(this) && !isa<BasicBlock>(this))
assert((VTy->isFirstClassType() || VTy == Type::VoidTy ||
isa<OpaqueType>(ty)) &&
"Cannot create non-first-class values except for constants!");
}
Value::~Value() {
if (HasValueHandle)
ValueHandleBase::ValueIsDeleted(this);
#ifndef NDEBUG // Only in -g mode...
if (!use_empty()) {
cerr << "While deleting: " << *VTy << " %" << getNameStr() << "\n";
for (use_iterator I = use_begin(), E = use_end(); I != E; ++I)
cerr << "Use still stuck around after Def is destroyed:"
<< **I << "\n";
}
#endif
assert(use_empty() && "Uses remain when a value is destroyed!");
if (Name)
Name->Destroy();
LeakDetector::removeGarbageObject(this);
}
bool Value::hasNUses(unsigned N) const {
use_const_iterator UI = use_begin(), E = use_end();
for (; N; --N, ++UI)
if (UI == E) return false; return UI == E;
}
bool Value::hasNUsesOrMore(unsigned N) const {
use_const_iterator UI = use_begin(), E = use_end();
for (; N; --N, ++UI)
if (UI == E) return false;
return true;
}
bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
for (use_const_iterator I = use_begin(), E = use_end(); I != E; ++I) {
const Instruction *User = dyn_cast<Instruction>(*I);
if (User && User->getParent() == BB)
return true;
}
return false;
}
unsigned Value::getNumUses() const {
return (unsigned)std::distance(use_begin(), use_end());
}
static bool getSymTab(Value *V, ValueSymbolTable *&ST) {
ST = 0;
if (Instruction *I = dyn_cast<Instruction>(V)) {
if (BasicBlock *P = I->getParent())
if (Function *PP = P->getParent())
ST = &PP->getValueSymbolTable();
} else if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
if (Function *P = BB->getParent())
ST = &P->getValueSymbolTable();
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
if (Module *P = GV->getParent())
ST = &P->getValueSymbolTable();
} else if (Argument *A = dyn_cast<Argument>(V)) {
if (Function *P = A->getParent())
ST = &P->getValueSymbolTable();
} else {
assert(isa<Constant>(V) && "Unknown value type!");
return true; }
return false;
}
const char *Value::getNameStart() const {
if (Name == 0) return "";
return Name->getKeyData();
}
unsigned Value::getNameLen() const {
return Name ? Name->getKeyLength() : 0;
}
bool Value::isName(const char *N) const {
unsigned InLen = strlen(N);
return InLen == getNameLen() && memcmp(getNameStart(), N, InLen) == 0;
}
std::string Value::getNameStr() const {
if (Name == 0) return "";
return std::string(Name->getKeyData(),
Name->getKeyData()+Name->getKeyLength());
}
void Value::setName(const std::string &name) {
setName(&name[0], name.size());
}
void Value::setName(const char *Name) {
setName(Name, Name ? strlen(Name) : 0);
}
void Value::setName(const char *NameStr, unsigned NameLen) {
if (NameLen == 0 && !hasName()) return;
assert(getType() != Type::VoidTy && "Cannot assign a name to void values!");
ValueSymbolTable *ST;
if (getSymTab(this, ST))
return;
if (!ST) { if (NameLen == 0) {
Name->Destroy();
Name = 0;
return;
}
if (Name) {
if (NameLen == Name->getKeyLength() &&
!memcmp(Name->getKeyData(), NameStr, NameLen))
return;
Name->Destroy();
}
Name = ValueName::Create(NameStr, NameStr+NameLen);
Name->setValue(this);
return;
}
if (hasName()) {
if (NameLen == Name->getKeyLength() &&
!memcmp(Name->getKeyData(), NameStr, NameLen))
return;
ST->removeValueName(Name);
Name->Destroy();
Name = 0;
if (NameLen == 0)
return;
}
Name = ST->createValueName(NameStr, NameLen, this);
}
void Value::takeName(Value *V) {
ValueSymbolTable *ST = 0;
if (hasName()) {
if (getSymTab(this, ST)) {
if (V->hasName()) V->setName(0, 0);
return; }
if (ST)
ST->removeValueName(Name);
Name->Destroy();
Name = 0;
}
if (!V->hasName()) return;
if (!ST) {
if (getSymTab(this, ST)) {
V->setName(0, 0);
return; }
}
ValueSymbolTable *VST;
bool Failure = getSymTab(V, VST);
assert(!Failure && "V has a name, so it should have a ST!"); Failure=Failure;
if (ST == VST) {
Name = V->Name;
V->Name = 0;
Name->setValue(this);
return;
}
if (VST)
VST->removeValueName(V->Name);
Name = V->Name;
V->Name = 0;
Name->setValue(this);
if (ST)
ST->reinsertValue(this);
}
void Value::uncheckedReplaceAllUsesWith(Value *New) {
if (HasValueHandle)
ValueHandleBase::ValueIsRAUWd(this, New);
while (!use_empty()) {
Use &U = *UseList;
if (Constant *C = dyn_cast<Constant>(U.getUser())) {
if (!isa<GlobalValue>(C)) {
C->replaceUsesOfWithOnConstant(this, New, &U);
continue;
}
}
U.set(New);
}
}
void Value::replaceAllUsesWith(Value *New) {
assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!");
assert(New->getType() == getType() &&
"replaceAllUses of value with new value of different type!");
uncheckedReplaceAllUsesWith(New);
}
Value *Value::stripPointerCasts() {
if (!isa<PointerType>(getType()))
return this;
Value *V = this;
do {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
if (!CE->getOperand(i)->isNullValue())
return V;
V = CE->getOperand(0);
} else if (CE->getOpcode() == Instruction::BitCast) {
V = CE->getOperand(0);
} else {
return V;
}
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V)) {
if (!GEP->hasAllZeroIndices())
return V;
V = GEP->getOperand(0);
} else if (BitCastInst *CI = dyn_cast<BitCastInst>(V)) {
V = CI->getOperand(0);
} else {
return V;
}
assert(isa<PointerType>(V->getType()) && "Unexpected operand type!");
} while (1);
}
Value *Value::getUnderlyingObject() {
if (!isa<PointerType>(getType()))
return this;
Value *V = this;
unsigned MaxLookup = 6;
do {
if (Instruction *I = dyn_cast<Instruction>(V)) {
if (!isa<BitCastInst>(I) && !isa<GetElementPtrInst>(I))
return V;
V = I->getOperand(0);
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() != Instruction::BitCast &&
CE->getOpcode() != Instruction::GetElementPtr)
return V;
V = CE->getOperand(0);
} else {
return V;
}
assert(isa<PointerType>(V->getType()) && "Unexpected operand type!");
} while (--MaxLookup);
return V;
}
Value *Value::DoPHITranslation(const BasicBlock *CurBB,
const BasicBlock *PredBB) {
PHINode *PN = dyn_cast<PHINode>(this);
if (PN && PN->getParent() == CurBB)
return PN->getIncomingValueForBlock(PredBB);
return this;
}
typedef DenseMap<Value*, ValueHandleBase*> ValueHandlesTy;
static ManagedStatic<ValueHandlesTy> ValueHandles;
void ValueHandleBase::AddToExistingUseList(ValueHandleBase **List) {
assert(List && "Handle list is null?");
Next = *List;
*List = this;
setPrevPtr(List);
if (Next) {
Next->setPrevPtr(&Next);
assert(VP == Next->VP && "Added to wrong list?");
}
}
void ValueHandleBase::AddToUseList() {
assert(VP && "Null pointer doesn't have a use list!");
if (VP->HasValueHandle) {
ValueHandleBase *&Entry = (*ValueHandles)[VP];
assert(Entry != 0 && "Value doesn't have any handles?");
return AddToExistingUseList(&Entry);
}
ValueHandlesTy &Handles = *ValueHandles;
const void *OldBucketPtr = Handles.getPointerIntoBucketsArray();
ValueHandleBase *&Entry = Handles[VP];
assert(Entry == 0 && "Value really did already have handles?");
AddToExistingUseList(&Entry);
VP->HasValueHandle = 1;
if (Handles.isPointerIntoBucketsArray(OldBucketPtr) ||
Handles.size() == 1)
return;
for (ValueHandlesTy::iterator I = Handles.begin(), E = Handles.end();
I != E; ++I) {
assert(I->second && I->first == I->second->VP && "List invariant broken!");
I->second->setPrevPtr(&I->second);
}
}
void ValueHandleBase::RemoveFromUseList() {
assert(VP && VP->HasValueHandle && "Pointer doesn't have a use list!");
ValueHandleBase **PrevPtr = getPrevPtr();
assert(*PrevPtr == this && "List invariant broken");
*PrevPtr = Next;
if (Next) {
assert(Next->getPrevPtr() == &Next && "List invariant broken");
Next->setPrevPtr(PrevPtr);
return;
}
ValueHandlesTy &Handles = *ValueHandles;
if (Handles.isPointerIntoBucketsArray(PrevPtr)) {
Handles.erase(VP);
VP->HasValueHandle = false;
}
}
void ValueHandleBase::ValueIsDeleted(Value *V) {
assert(V->HasValueHandle && "Should only be called if ValueHandles present");
ValueHandleBase *Entry = (*ValueHandles)[V];
assert(Entry && "Value bit set but no entries exist");
while (Entry) {
ValueHandleBase *ThisNode = Entry;
Entry = Entry->Next;
switch (ThisNode->getKind()) {
case Assert:
#ifndef NDEBUG // Only in -g mode...
cerr << "While deleting: " << *V->getType() << " %" << V->getNameStr()
<< "\n";
#endif
cerr << "An asserting value handle still pointed to this value!\n";
abort();
case Weak:
ThisNode->operator=(0);
break;
case Callback:
assert(0 && "Callback not implemented yet!");
}
}
assert(!V->HasValueHandle && "All references to V were not removed?");
}
void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) {
assert(Old->HasValueHandle &&"Should only be called if ValueHandles present");
assert(Old != New && "Changing value into itself!");
ValueHandleBase *Entry = (*ValueHandles)[Old];
assert(Entry && "Value bit set but no entries exist");
while (Entry) {
ValueHandleBase *ThisNode = Entry;
Entry = Entry->Next;
switch (ThisNode->getKind()) {
case Assert:
break;
case Weak:
ThisNode->operator=(New);
break;
case Callback:
assert(0 && "Callback not implemented yet!");
}
}
}
void User::replaceUsesOfWith(Value *From, Value *To) {
if (From == To) return;
assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
"Cannot call User::replaceUsesofWith on a constant!");
for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
if (getOperand(i) == From) { setOperand(i, To); }
}