summaryrefslogtreecommitdiff
path: root/lib/VMCore
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2004-07-18 00:06:26 +0000
committerReid Spencer <rspencer@reidspencer.com>2004-07-18 00:06:26 +0000
commite253cf60fde678c428d69327b1ed43232893079c (patch)
tree6937a7dadd44ed8e7b192b81680db8d1f1a48b20 /lib/VMCore
parenta31fdda2759f6d28cdb49595fb71245179c0d391 (diff)
downloadllvm-e253cf60fde678c428d69327b1ed43232893079c.tar.gz
llvm-e253cf60fde678c428d69327b1ed43232893079c.tar.bz2
llvm-e253cf60fde678c428d69327b1ed43232893079c.tar.xz
bug 122:
- Move these functions from other places - Provide implementations of Constant class overrides in GlobalValue git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14936 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/Globals.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
new file mode 100644
index 0000000000..0e8227bdeb
--- /dev/null
+++ b/lib/VMCore/Globals.cpp
@@ -0,0 +1,139 @@
+//===-- Globals.cpp - Implement the Global object classes -----------------===//
+//
+// 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 implements the GlobalValue & GlobalVariable classes for the VMCore
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Module.h"
+#include "llvm/SymbolTable.h"
+#include "Support/LeakDetector.h"
+
+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.
+namespace {
+bool removeDeadConstantUsers(Constant* C) {
+ while (!C->use_empty()) {
+ if (Constant *User = dyn_cast<Constant>(C->use_back())) {
+ if (!removeDeadConstantUsers(User))
+ return false; // Constant wasn't dead
+ } else {
+ return false; // Non-constant usage;
+ }
+ }
+ if (!isa<GlobalValue>(C))
+ C->destroyConstant();
+ return true;
+}
+}
+
+/// removeDeadConstantUsers - If there are any dead constant users dangling
+/// 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.
+bool GlobalValue::removeDeadConstantUsers() {
+ while(!use_empty()) {
+ if (Constant* User = dyn_cast<Constant>(use_back())) {
+ if (!::removeDeadConstantUsers(User))
+ return false; // Constant wasn't dead
+ } else {
+ return false; // Non-constant usage;
+ }
+ }
+ return true;
+}
+
+/// This virtual destructor is responsible for deleting any transitively dead
+/// Constants that are using the GlobalValue.
+GlobalValue::~GlobalValue() {
+ // Its an error to attempt destruction with non-constant uses remaining.
+ bool okay_to_destruct = removeDeadConstantUsers();
+ assert(okay_to_destruct &&
+ "Can't destroy GlobalValue with non-constant uses.");
+}
+
+/// Override destroyConstant to make sure it doesn't get called on
+/// GlobalValue's because they shouldn't be treated like other constants.
+void GlobalValue::destroyConstant() {
+ assert(0 && "You can't GV->destroyConstant()!");
+ abort();
+}
+//===----------------------------------------------------------------------===//
+// GlobalVariable Implementation
+//===----------------------------------------------------------------------===//
+
+GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
+ Constant *Initializer,
+ const std::string &Name, Module *ParentModule)
+ : GlobalValue(PointerType::get(Ty), Value::GlobalVariableVal, Link, Name),
+ isConstantGlobal(constant) {
+ if (Initializer) Operands.push_back(Use((Value*)Initializer, this));
+
+ LeakDetector::addGarbageObject(this);
+
+ if (ParentModule)
+ ParentModule->getGlobalList().push_back(this);
+}
+
+void GlobalVariable::setParent(Module *parent) {
+ if (getParent())
+ LeakDetector::addGarbageObject(this);
+ Parent = parent;
+ if (getParent())
+ LeakDetector::removeGarbageObject(this);
+}
+
+// Specialize setName to take care of symbol table majik
+void GlobalVariable::setName(const std::string &name, SymbolTable *ST) {
+ Module *P;
+ assert((ST == 0 || (!getParent() || ST == &getParent()->getSymbolTable())) &&
+ "Invalid symtab argument!");
+ if ((P = getParent()) && hasName()) P->getSymbolTable().remove(this);
+ Value::setName(name);
+ if (P && hasName()) P->getSymbolTable().insert(this);
+}
+
+void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To,
+ bool DisableChecking )
+{
+ // If you call this, then you better know this GVar has a constant
+ // initializer worth replacing. Enforce that here.
+ assert(getNumOperands() == 1 &&
+ "Attempt to replace uses of Constants on a GVar with no initializer");
+
+ // And, since you know it has an initializer, the From value better be
+ // the initializer :)
+ assert(getOperand(0) == From &&
+ "Attempt to replace wrong constant initializer in GVar");
+
+ // And, you better have a constant for the replacement value
+ assert(isa<Constant>(To) &&
+ "Attempt to replace GVar initializer with non-constant");
+
+ // Okay, preconditions out of the way, replace the constant initializer.
+ this->setOperand(0,To);
+}
+
+// vim: sw=2 ai
+