X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FGlobals.cpp;h=7340f1532f536c4278df179316f968437b123188;hb=719de53742167ca3f0e6b2efafb6eac18bd90452;hp=e49f47766f48fbe67ec497157db8e4b0b8ef5e82;hpb=adc95467e41d6c46793f665168468cbf348c3638;p=oota-llvm.git diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp index e49f47766f4..7340f1532f5 100644 --- a/lib/VMCore/Globals.cpp +++ b/lib/VMCore/Globals.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -12,10 +12,12 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" #include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" -#include "llvm/SymbolTable.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/LeakDetector.h" using namespace llvm; @@ -23,20 +25,18 @@ using namespace llvm; // GlobalValue Class //===----------------------------------------------------------------------===// -/// This could be named "SafeToDestroyGlobalValue". It just makes sure that -/// there are no non-constant uses of this GlobalValue. If there aren't then -/// this and the transitive closure of the constants can be deleted. See the -/// destructor for details. -static bool removeDeadConstantUsers(Constant* C) { +/// removeDeadUsersOfConstant - If the specified constantexpr is dead, remove +/// it. This involves recursively eliminating any dead users of the +/// constantexpr. +static bool removeDeadUsersOfConstant(Constant *C) { if (isa(C)) return false; // Cannot remove this - while (!C->use_empty()) - if (Constant *User = dyn_cast(C->use_back())) { - if (!removeDeadConstantUsers(User)) - return false; // Constant wasn't dead - } else { - return false; // Non-constant usage; - } + while (!C->use_empty()) { + Constant *User = dyn_cast(C->use_back()); + if (!User) return false; // Non-constant usage; + if (!removeDeadUsersOfConstant(User)) + return false; // Constant wasn't dead + } C->destroyConstant(); return true; @@ -46,17 +46,29 @@ static bool removeDeadConstantUsers(Constant* C) { /// off of this global value, remove them. This method is useful for clients /// that want to check to see if a global is unused, but don't want to deal /// with potentially dead constants hanging off of the globals. -/// -/// This function returns true if the global value is now dead. If all -/// users of this global are not dead, this method may return false and -/// leave some of them around. void GlobalValue::removeDeadConstantUsers() { - while(!use_empty()) { - if (Constant* User = dyn_cast(use_back())) { - if (!::removeDeadConstantUsers(User)) - return; // Constant wasn't dead + Value::use_iterator I = use_begin(), E = use_end(); + Value::use_iterator LastNonDeadUser = E; + while (I != E) { + if (Constant *User = dyn_cast(*I)) { + if (!removeDeadUsersOfConstant(User)) { + // If the constant wasn't dead, remember that this was the last live use + // and move on to the next constant. + LastNonDeadUser = I; + ++I; + } else { + // If the constant was dead, then the iterator is invalidated. + if (LastNonDeadUser == E) { + I = use_begin(); + if (I == E) break; + } else { + I = LastNonDeadUser; + ++I; + } + } } else { - return; // Non-constant usage; + LastNonDeadUser = I; + ++I; } } } @@ -67,22 +79,32 @@ void GlobalValue::destroyConstant() { assert(0 && "You can't GV->destroyConstant()!"); abort(); } + +/// copyAttributesFrom - copy all additional attributes (those not needed to +/// create a GlobalValue) from the GlobalValue Src to this one. +void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { + setAlignment(Src->getAlignment()); + setSection(Src->getSection()); + setVisibility(Src->getVisibility()); +} + + //===----------------------------------------------------------------------===// // GlobalVariable Implementation //===----------------------------------------------------------------------===// GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, - Constant *InitVal, - const std::string &Name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, - &Initializer, InitVal != 0, Link, Name), - isConstantGlobal(constant) { + Constant *InitVal, const std::string &Name, + Module *ParentModule, bool ThreadLocal, + unsigned AddressSpace) + : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, + OperandTraits::op_begin(this), + InitVal != 0, Link, Name), + isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) { if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); - Initializer.init(InitVal, this); - } else { - Initializer.init(0, this); + Op<0>() = InitVal; } LeakDetector::addGarbageObject(this); @@ -92,17 +114,17 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, } GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, - Constant *InitVal, - const std::string &Name, GlobalVariable *Before) - : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, - &Initializer, InitVal != 0, Link, Name), - isConstantGlobal(constant) { + Constant *InitVal, const std::string &Name, + GlobalVariable *Before, bool ThreadLocal, + unsigned AddressSpace) + : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, + OperandTraits::op_begin(this), + InitVal != 0, Link, Name), + isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) { if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); - Initializer.init(InitVal, this); - } else { - Initializer.init(0, this); + Op<0>() = InitVal; } LeakDetector::addGarbageObject(this); @@ -111,7 +133,6 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link, Before->getParent()->getGlobalList().insert(Before, this); } - void GlobalVariable::setParent(Module *parent) { if (getParent()) LeakDetector::addGarbageObject(this); @@ -147,3 +168,98 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To, // Okay, preconditions out of the way, replace the constant initializer. this->setOperand(0, cast(To)); } + +/// copyAttributesFrom - copy all additional attributes (those not needed to +/// create a GlobalVariable) from the GlobalVariable Src to this one. +void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { + assert(isa(Src) && "Expected a GlobalVariable!"); + GlobalValue::copyAttributesFrom(Src); + const GlobalVariable *SrcVar = cast(Src); + setThreadLocal(SrcVar->isThreadLocal()); +} + + +//===----------------------------------------------------------------------===// +// GlobalAlias Implementation +//===----------------------------------------------------------------------===// + +GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link, + const std::string &Name, Constant* aliasee, + Module *ParentModule) + : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { + LeakDetector::addGarbageObject(this); + + if (aliasee) + assert(aliasee->getType() == Ty && "Alias and aliasee types should match!"); + Op<0>() = aliasee; + + if (ParentModule) + ParentModule->getAliasList().push_back(this); +} + +void GlobalAlias::setParent(Module *parent) { + if (getParent()) + LeakDetector::addGarbageObject(this); + Parent = parent; + if (getParent()) + LeakDetector::removeGarbageObject(this); +} + +void GlobalAlias::removeFromParent() { + getParent()->getAliasList().remove(this); +} + +void GlobalAlias::eraseFromParent() { + getParent()->getAliasList().erase(this); +} + +bool GlobalAlias::isDeclaration() const { + const GlobalValue* AV = getAliasedGlobal(); + if (AV) + return AV->isDeclaration(); + else + return false; +} + +void GlobalAlias::setAliasee(Constant *Aliasee) +{ + if (Aliasee) + assert(Aliasee->getType() == getType() && + "Alias and aliasee types should match!"); + + setOperand(0, Aliasee); +} + +const GlobalValue *GlobalAlias::getAliasedGlobal() const { + const Constant *C = getAliasee(); + if (C) { + if (const GlobalValue *GV = dyn_cast(C)) + return GV; + else { + const ConstantExpr *CE = 0; + if ((CE = dyn_cast(C)) && + (CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr)) + return dyn_cast(CE->getOperand(0)); + else + assert(0 && "Unsupported aliasee"); + } + } + return 0; +} + +const GlobalValue *GlobalAlias::resolveAliasedGlobal() const { + SmallPtrSet Visited; + + const GlobalValue *GV = getAliasedGlobal(); + Visited.insert(GV); + + while (const GlobalAlias *GA = dyn_cast(GV)) { + GV = GA->getAliasedGlobal(); + + if (!Visited.insert(GV)) + return NULL; + } + + return GV; +}