Fix undefined behavior in the Mips backend.
[oota-llvm.git] / lib / VMCore / LLVMContextImpl.cpp
index 8e6c7778b9599d36c0ff73f8169161ce64d36156..6279bb823dbf23b1e5823713296e992848c319b3 100644 (file)
@@ -1,4 +1,4 @@
-//===--------------- LLVMContextImpl.cpp - Implementation ------*- C++ -*--===//
+//===-- LLVMContextImpl.cpp - Implement LLVMContextImpl -------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 //
 //===----------------------------------------------------------------------===//
 //
-//  This file implements LLVMContextImpl, the opaque implementation 
-//  of LLVMContext.
+//  This file implements the opaque LLVMContextImpl.
 //
 //===----------------------------------------------------------------------===//
 
 #include "LLVMContextImpl.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/MDNode.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/STLExtras.h"
+#include <algorithm>
 using namespace llvm;
 
-static char getValType(ConstantAggregateZero *CPZ) { return 0; }
-
-static std::vector<Constant*> getValType(ConstantArray *CA) {
-  std::vector<Constant*> Elements;
-  Elements.reserve(CA->getNumOperands());
-  for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
-    Elements.push_back(cast<Constant>(CA->getOperand(i)));
-  return Elements;
-}
-
-static std::vector<Constant*> getValType(ConstantStruct *CS) {
-  std::vector<Constant*> Elements;
-  Elements.reserve(CS->getNumOperands());
-  for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
-    Elements.push_back(cast<Constant>(CS->getOperand(i)));
-  return Elements;
-}
-
-static std::vector<Constant*> getValType(ConstantVector *CP) {
-  std::vector<Constant*> Elements;
-  Elements.reserve(CP->getNumOperands());
-  for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
-    Elements.push_back(CP->getOperand(i));
-  return Elements;
-}
-
-
-LLVMContextImpl::LLVMContextImpl(LLVMContext &C) :
-    Context(C), TheTrueVal(0), TheFalseVal(0) { }
-
-
-ConstantFP *LLVMContextImpl::getConstantFP(const APFloat &V) {
-  DenseMapAPFloatKeyInfo::KeyTy Key(V);
-  
-  ConstantsLock.reader_acquire();
-  ConstantFP *&Slot = FPConstants[Key];
-  ConstantsLock.reader_release();
-    
-  if (!Slot) {
-    sys::SmartScopedWriter<true> Writer(ConstantsLock);
-    ConstantFP *&NewSlot = FPConstants[Key];
-    if (!NewSlot) {
-      const Type *Ty;
-      if (&V.getSemantics() == &APFloat::IEEEsingle)
-        Ty = Type::FloatTy;
-      else if (&V.getSemantics() == &APFloat::IEEEdouble)
-        Ty = Type::DoubleTy;
-      else if (&V.getSemantics() == &APFloat::x87DoubleExtended)
-        Ty = Type::X86_FP80Ty;
-      else if (&V.getSemantics() == &APFloat::IEEEquad)
-        Ty = Type::FP128Ty;
-      else {
-        assert(&V.getSemantics() == &APFloat::PPCDoubleDouble && 
-               "Unknown FP format");
-        Ty = Type::PPC_FP128Ty;
-      }
-      NewSlot = new ConstantFP(Ty, V);
-    }
-    
-    return NewSlot;
+LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
+  : TheTrueVal(0), TheFalseVal(0),
+    VoidTy(C, Type::VoidTyID),
+    LabelTy(C, Type::LabelTyID),
+    HalfTy(C, Type::HalfTyID),
+    FloatTy(C, Type::FloatTyID),
+    DoubleTy(C, Type::DoubleTyID),
+    MetadataTy(C, Type::MetadataTyID),
+    X86_FP80Ty(C, Type::X86_FP80TyID),
+    FP128Ty(C, Type::FP128TyID),
+    PPC_FP128Ty(C, Type::PPC_FP128TyID),
+    X86_MMXTy(C, Type::X86_MMXTyID),
+    Int1Ty(C, 1),
+    Int8Ty(C, 8),
+    Int16Ty(C, 16),
+    Int32Ty(C, 32),
+    Int64Ty(C, 64) {
+  InlineAsmDiagHandler = 0;
+  InlineAsmDiagContext = 0;
+  NamedStructTypesUniqueID = 0;
+}
+
+namespace {
+struct DropReferences {
+  // Takes the value_type of a ConstantUniqueMap's internal map, whose 'second'
+  // is a Constant*.
+  template<typename PairT>
+  void operator()(const PairT &P) {
+    P.second->dropAllReferences();
   }
-  
-  return Slot;
-}
-
-MDString *LLVMContextImpl::getMDString(const char *StrBegin,
-                                       unsigned StrLength) {
-  sys::SmartScopedWriter<true> Writer(ConstantsLock);
-  StringMapEntry<MDString *> &Entry = 
-    MDStringCache.GetOrCreateValue(StringRef(StrBegin, StrLength));
-  MDString *&S = Entry.getValue();
-  if (!S) S = new MDString(Entry.getKeyData(),
-                           Entry.getKeyLength());
-
-  return S;
-}
-
-MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) {
-  FoldingSetNodeID ID;
-  for (unsigned i = 0; i != NumVals; ++i)
-    ID.AddPointer(Vals[i]);
-
-  ConstantsLock.reader_acquire();
-  void *InsertPoint;
-  MDNode *N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
-  ConstantsLock.reader_release();
-  
-  if (!N) {
-    sys::SmartScopedWriter<true> Writer(ConstantsLock);
-    N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
-    if (!N) {
-      // InsertPoint will have been set by the FindNodeOrInsertPos call.
-      N = new MDNode(Vals, NumVals);
-      MDNodeSet.InsertNode(N, InsertPoint);
-    }
+};
+
+// Temporary - drops pair.first instead of second.
+struct DropFirst {
+  // Takes the value_type of a ConstantUniqueMap's internal map, whose 'second'
+  // is a Constant*.
+  template<typename PairT>
+  void operator()(const PairT &P) {
+    P.first->dropAllReferences();
   }
-
-  return N;
-}
-
-ConstantAggregateZero*
-LLVMContextImpl::getConstantAggregateZero(const Type *Ty) {
-  assert((isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) &&
-         "Cannot create an aggregate zero of non-aggregate type!");
-
-  // Implicitly locked.
-  return AggZeroConstants.getOrCreate(Ty, 0);
+};
 }
 
-Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty,
-                             const std::vector<Constant*> &V) {
-  // If this is an all-zero array, return a ConstantAggregateZero object
-  if (!V.empty()) {
-    Constant *C = V[0];
-    if (!C->isNullValue()) {
-      // Implicitly locked.
-      return ArrayConstants.getOrCreate(Ty, V);
-    }
-    for (unsigned i = 1, e = V.size(); i != e; ++i)
-      if (V[i] != C) {
-        // Implicitly locked.
-        return ArrayConstants.getOrCreate(Ty, V);
-      }
-  }
+LLVMContextImpl::~LLVMContextImpl() {
+  // NOTE: We need to delete the contents of OwnedModules, but we have to
+  // duplicate it into a temporary vector, because the destructor of Module
+  // will try to remove itself from OwnedModules set.  This would cause
+  // iterator invalidation if we iterated on the set directly.
+  std::vector<Module*> Modules(OwnedModules.begin(), OwnedModules.end());
+  DeleteContainerPointers(Modules);
   
-  return Context.getConstantAggregateZero(Ty);
-}
-
-Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty,
-                              const std::vector<Constant*> &V) {
-  // Create a ConstantAggregateZero value if all elements are zeros...
-  for (unsigned i = 0, e = V.size(); i != e; ++i)
-    if (!V[i]->isNullValue())
-      // Implicitly locked.
-      return StructConstants.getOrCreate(Ty, V);
-
-  return Context.getConstantAggregateZero(Ty);
-}
-
-Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty,
-                              const std::vector<Constant*> &V) {
-  assert(!V.empty() && "Vectors can't be empty");
-  // If this is an all-undef or alll-zero vector, return a
-  // ConstantAggregateZero or UndefValue.
-  Constant *C = V[0];
-  bool isZero = C->isNullValue();
-  bool isUndef = isa<UndefValue>(C);
-
-  if (isZero || isUndef) {
-    for (unsigned i = 1, e = V.size(); i != e; ++i)
-      if (V[i] != C) {
-        isZero = isUndef = false;
-        break;
-      }
-  }
+  // Free the constants.  This is important to do here to ensure that they are
+  // freed before the LeakDetector is torn down.
+  std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
+                DropReferences());
+  std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(),
+                DropFirst());
+  std::for_each(StructConstants.map_begin(), StructConstants.map_end(),
+                DropFirst());
+  std::for_each(VectorConstants.map_begin(), VectorConstants.map_end(),
+                DropFirst());
+  ExprConstants.freeConstants();
+  ArrayConstants.freeConstants();
+  StructConstants.freeConstants();
+  VectorConstants.freeConstants();
+  DeleteContainerSeconds(CAZConstants);
+  DeleteContainerSeconds(CPNConstants);
+  DeleteContainerSeconds(UVConstants);
+  InlineAsms.freeConstants();
+  DeleteContainerSeconds(IntConstants);
+  DeleteContainerSeconds(FPConstants);
   
-  if (isZero)
-    return Context.getConstantAggregateZero(Ty);
-  if (isUndef)
-    return Context.getUndef(Ty);
-    
-  // Implicitly locked.
-  return VectorConstants.getOrCreate(Ty, V);
-}
-
-// *** erase methods ***
-
-void LLVMContextImpl::erase(MDString *M) {
-  sys::SmartScopedWriter<true> Writer(ConstantsLock);
-  MDStringCache.erase(MDStringCache.find(StringRef(M->StrBegin, 
-                                                   M->length())));
-}
-
-void LLVMContextImpl::erase(MDNode *M) {
-  sys::SmartScopedWriter<true> Writer(ConstantsLock);
-  MDNodeSet.RemoveNode(M);
-}
-
-void LLVMContextImpl::erase(ConstantAggregateZero *Z) {
-  AggZeroConstants.remove(Z);
-}
-
-void LLVMContextImpl::erase(ConstantArray *C) {
-  ArrayConstants.remove(C);
+  for (StringMap<ConstantDataSequential*>::iterator I = CDSConstants.begin(),
+       E = CDSConstants.end(); I != E; ++I)
+    delete I->second;
+  CDSConstants.clear();
+  
+  // Destroy MDNodes.  ~MDNode can move and remove nodes between the MDNodeSet
+  // and the NonUniquedMDNodes sets, so copy the values out first.
+  SmallVector<MDNode*, 8> MDNodes;
+  MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size());
+  for (FoldingSetIterator<MDNode> I = MDNodeSet.begin(), E = MDNodeSet.end();
+       I != E; ++I)
+    MDNodes.push_back(&*I);
+  MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end());
+  for (SmallVectorImpl<MDNode *>::iterator I = MDNodes.begin(),
+         E = MDNodes.end(); I != E; ++I)
+    (*I)->destroy();
+  assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() &&
+         "Destroying all MDNodes didn't empty the Context's sets.");
+  // Destroy MDStrings.
+  DeleteContainerSeconds(MDStringCache);
 }
 
-void LLVMContextImpl::erase(ConstantStruct *S) {
-  StructConstants.remove(S);
-}
+// ConstantsContext anchors
+void UnaryConstantExpr::anchor() { }
 
-void LLVMContextImpl::erase(ConstantVector *V) {
-  VectorConstants.remove(V);
-}
+void BinaryConstantExpr::anchor() { }
 
-// *** RAUW helpers ***
+void SelectConstantExpr::anchor() { }
 
-Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA,
-                                               Value *From, Value *To, Use *U) {
-  assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
-  Constant *ToC = cast<Constant>(To);
+void ExtractElementConstantExpr::anchor() { }
 
-  std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup;
-  Lookup.first.first = CA->getType();
-  Lookup.second = CA;
+void InsertElementConstantExpr::anchor() { }
 
-  std::vector<Constant*> &Values = Lookup.first.second;
-  Values.reserve(CA->getNumOperands());  // Build replacement array.
+void ShuffleVectorConstantExpr::anchor() { }
 
-  // Fill values with the modified operands of the constant array.  Also, 
-  // compute whether this turns into an all-zeros array.
-  bool isAllZeros = false;
-  unsigned NumUpdated = 0;
-  if (!ToC->isNullValue()) {
-    for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
-         O != E; ++O) {
-      Constant *Val = cast<Constant>(O->get());
-      if (Val == From) {
-        Val = ToC;
-        ++NumUpdated;
-      }
-      Values.push_back(Val);
-    }
-  } else {
-    isAllZeros = true;
-    for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
-         O != E; ++O) {
-      Constant *Val = cast<Constant>(O->get());
-      if (Val == From) {
-        Val = ToC;
-        ++NumUpdated;
-      }
-      Values.push_back(Val);
-      if (isAllZeros) isAllZeros = Val->isNullValue();
-    }
-  }
-  
-  Constant *Replacement = 0;
-  if (isAllZeros) {
-    Replacement = Context.getConstantAggregateZero(CA->getType());
-  } else {
-    // Check to see if we have this array type already.
-    sys::SmartScopedWriter<true> Writer(ConstantsLock);
-    bool Exists;
-    ArrayConstantsTy::MapTy::iterator I =
-      ArrayConstants.InsertOrGetItem(Lookup, Exists);
-    
-    if (Exists) {
-      Replacement = I->second;
-    } else {
-      // Okay, the new shape doesn't exist in the system yet.  Instead of
-      // creating a new constant array, inserting it, replaceallusesof'ing the
-      // old with the new, then deleting the old... just update the current one
-      // in place!
-      ArrayConstants.MoveConstantToNewSlot(CA, I);
-      
-      // Update to the new value.  Optimize for the case when we have a single
-      // operand that we're changing, but handle bulk updates efficiently.
-      if (NumUpdated == 1) {
-        unsigned OperandToUpdate = U - CA->OperandList;
-        assert(CA->getOperand(OperandToUpdate) == From &&
-               "ReplaceAllUsesWith broken!");
-        CA->setOperand(OperandToUpdate, ToC);
-      } else {
-        for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
-          if (CA->getOperand(i) == From)
-            CA->setOperand(i, ToC);
-      }
-      return 0;
-    }
-  }
-  
-  return Replacement;
-}
+void ExtractValueConstantExpr::anchor() { }
 
-Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS,
-                                               Value *From, Value *To, Use *U) {
-  assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
-  Constant *ToC = cast<Constant>(To);
+void InsertValueConstantExpr::anchor() { }
 
-  unsigned OperandToUpdate = U - CS->OperandList;
-  assert(CS->getOperand(OperandToUpdate) == From &&
-         "ReplaceAllUsesWith broken!");
+void GetElementPtrConstantExpr::anchor() { }
 
-  std::pair<StructConstantsTy::MapKey, Constant*> Lookup;
-  Lookup.first.first = CS->getType();
-  Lookup.second = CS;
-  std::vector<Constant*> &Values = Lookup.first.second;
-  Values.reserve(CS->getNumOperands());  // Build replacement struct.
-  
-  
-  // Fill values with the modified operands of the constant struct.  Also, 
-  // compute whether this turns into an all-zeros struct.
-  bool isAllZeros = false;
-  if (!ToC->isNullValue()) {
-    for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
-         O != E; ++O)
-      Values.push_back(cast<Constant>(O->get()));
-  } else {
-    isAllZeros = true;
-    for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
-         O != E; ++O) {
-      Constant *Val = cast<Constant>(O->get());
-      Values.push_back(Val);
-      if (isAllZeros) isAllZeros = Val->isNullValue();
-    }
-  }
-  Values[OperandToUpdate] = ToC;
-  
-  Constant *Replacement = 0;
-  if (isAllZeros) {
-    Replacement = Context.getConstantAggregateZero(CS->getType());
-  } else {
-    // Check to see if we have this array type already.
-    sys::SmartScopedWriter<true> Writer(ConstantsLock);
-    bool Exists;
-    StructConstantsTy::MapTy::iterator I =
-      StructConstants.InsertOrGetItem(Lookup, Exists);
-    
-    if (Exists) {
-      Replacement = I->second;
-    } else {
-      // Okay, the new shape doesn't exist in the system yet.  Instead of
-      // creating a new constant struct, inserting it, replaceallusesof'ing the
-      // old with the new, then deleting the old... just update the current one
-      // in place!
-      StructConstants.MoveConstantToNewSlot(CS, I);
-      
-      // Update to the new value.
-      CS->setOperand(OperandToUpdate, ToC);
-      return 0;
-    }
-  }
-  
-  assert(Replacement != CS && "I didn't contain From!");
-  
-  return Replacement;
-}
+void CompareConstantExpr::anchor() { }