Destroy allocated resources on exception.
[oota-llvm.git] / lib / VMCore / Module.cpp
index e0a6fb271ceabbe5d95959cc7d7b8c1ab49cb5a0..b7fe5693fb239f996ed614145f204cccc71ce074 100644 (file)
@@ -12,6 +12,7 @@
 #include "Support/LeakDetector.h"
 #include "SymbolTableListTraitsImpl.h"
 #include <algorithm>
+#include <cstdarg>
 #include <map>
 
 Function *ilist_traits<Function>::createNode() {
@@ -52,7 +53,8 @@ struct GlobalValueRefMap {
 };
 
 
-Module::Module() {
+Module::Module(const std::string &MID)
+  : ModuleID(MID), Endian(AnyEndianness), PtrSize(AnyPointerSize) {
   FunctionList.setItemParent(this);
   FunctionList.setParent(this);
   GlobalList.setItemParent(this);
@@ -94,6 +96,29 @@ Function *Module::getOrInsertFunction(const std::string &Name,
   }
 }
 
+// getOrInsertFunction - Look up the specified function in the module symbol
+// table.  If it does not exist, add a prototype for the function and return it.
+// This version of the method takes a null terminated list of function
+// arguments, which makes it easier for clients to use.
+//
+Function *Module::getOrInsertFunction(const std::string &Name,
+                                      const Type *RetTy, ...) {
+  va_list Args;
+  va_start(Args, RetTy);
+
+  // Build the list of argument types...
+  std::vector<const Type*> ArgTys;
+  while (const Type *ArgTy = va_arg(Args, const Type*))
+    ArgTys.push_back(ArgTy);
+
+  va_end(Args);
+
+  // Build the function type and chain to the other getOrInsertFunction...
+  return getOrInsertFunction(Name, FunctionType::get(RetTy, ArgTys, false));
+}
+
+
+
 // getFunction - Look up the specified function in the module symbol table.
 // If it does not exist, return null.
 //
@@ -171,10 +196,14 @@ Function *Module::getMainFunction() {
 ///
 Function *Module::getNamedFunction(const std::string &Name) {
   // Loop over all of the functions, looking for the function desired
+  Function *Found = 0;
   for (iterator I = begin(), E = end(); I != E; ++I)
     if (I->getName() == Name)
-      return I;
-  return 0; // function not found...
+      if (I->isExternal())
+        Found = I;
+      else
+        return I;
+  return Found; // Non-external function not found...
 }
 
 
@@ -249,6 +278,7 @@ void Module::destroyConstantPointerRef(ConstantPointerRef *CPR) {
 }
 
 void Module::mutateConstantPointerRef(GlobalValue *OldGV, GlobalValue *NewGV) {
+  assert(OldGV != NewGV && "Cannot mutate to the same global!");
   GlobalValueRefMap::iterator I = GVRefMap->Map.find(OldGV);
   assert(I != GVRefMap->Map.end() && 
         "mutateConstantPointerRef; OldGV not in table!");
@@ -257,6 +287,16 @@ void Module::mutateConstantPointerRef(GlobalValue *OldGV, GlobalValue *NewGV) {
   // Remove the old entry...
   GVRefMap->Map.erase(I);
 
-  // Insert the new entry...
-  GVRefMap->Map.insert(std::make_pair(NewGV, Ref));
+  // Check to see if a CPR already exists for NewGV
+  I = GVRefMap->Map.lower_bound(NewGV);
+
+  if (I == GVRefMap->Map.end() || I->first != NewGV) {
+    // Insert the new entry...
+    GVRefMap->Map.insert(I, std::make_pair(NewGV, Ref));
+  } else {
+    // Otherwise, an entry already exists for the current global value.
+    // Completely replace the old CPR with the existing one...
+    Ref->replaceAllUsesWith(I->second);
+    delete Ref;
+  }
 }