Fix a crasher where when we're attempting to replace a type
[oota-llvm.git] / lib / IR / Metadata.cpp
index d751064e2227bb1ce385340be55ac489ea61967a..ad943de88cc5a5e9ede7827b078bd67250e8f568 100644 (file)
@@ -16,6 +16,7 @@
 #include "SymbolTableListTraitsImpl.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/Instruction.h"
@@ -65,7 +66,7 @@ class MDNodeOperand : public CallbackVH {
 
 public:
   MDNodeOperand(Value *V) : CallbackVH(V) {}
-  ~MDNodeOperand() {}
+  virtual ~MDNodeOperand();
 
   void set(Value *V) {
     unsigned IsFirst = this->getValPtrInt();
@@ -82,6 +83,8 @@ public:
 };
 } // end namespace llvm.
 
+// Provide out-of-line definition to prevent weak vtable.
+MDNodeOperand::~MDNodeOperand() {}
 
 void MDNodeOperand::deleted() {
   getParent()->replaceOperand(this, 0);
@@ -303,6 +306,7 @@ void MDNode::deleteTemporary(MDNode *N) {
 
 /// getOperand - Return specified operand.
 Value *MDNode::getOperand(unsigned i) const {
+  assert(i < getNumOperands() && "Invalid operand number");
   return *getOperandPtr(const_cast<MDNode*>(this), i);
 }
 
@@ -402,42 +406,6 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
   }
 }
 
-MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) {
-  if (!A || !B)
-    return NULL;
-
-  if (A == B)
-    return A;
-
-  SmallVector<MDNode *, 4> PathA;
-  MDNode *T = A;
-  while (T) {
-    PathA.push_back(T);
-    T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
-  }
-
-  SmallVector<MDNode *, 4> PathB;
-  T = B;
-  while (T) {
-    PathB.push_back(T);
-    T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
-  }
-
-  int IA = PathA.size() - 1;
-  int IB = PathB.size() - 1;
-
-  MDNode *Ret = 0;
-  while (IA >= 0 && IB >=0) {
-    if (PathA[IA] == PathB[IB])
-      Ret = PathA[IA];
-    else
-      break;
-    --IA;
-    --IB;
-  }
-  return Ret;
-}
-
 MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {
   if (!A || !B)
     return NULL;
@@ -457,7 +425,7 @@ static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) {
   return !A.intersectWith(B).isEmptySet() || isContiguous(A, B);
 }
 
-static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
+static bool tryMergeRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low,
                           ConstantInt *High) {
   ConstantRange NewRange(Low->getValue(), High->getValue());
   unsigned Size = EndPoints.size();
@@ -474,7 +442,7 @@ static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
   return false;
 }
 
-static void addRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
+static void addRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low,
                      ConstantInt *High) {
   if (!EndPoints.empty())
     if (tryMergeRange(EndPoints, Low, High))
@@ -616,6 +584,50 @@ MDNode *Instruction::getMetadataImpl(StringRef Kind) const {
   return getMetadataImpl(getContext().getMDKindID(Kind));
 }
 
+void Instruction::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
+  SmallSet<unsigned, 5> KnownSet;
+  KnownSet.insert(KnownIDs.begin(), KnownIDs.end());
+
+  // Drop debug if needed
+  if (KnownSet.erase(LLVMContext::MD_dbg))
+    DbgLoc = DebugLoc();
+
+  if (!hasMetadataHashEntry())
+    return; // Nothing to remove!
+
+  DenseMap<const Instruction *, LLVMContextImpl::MDMapTy> &MetadataStore =
+      getContext().pImpl->MetadataStore;
+
+  if (KnownSet.empty()) {
+    // Just drop our entry at the store.
+    MetadataStore.erase(this);
+    setHasMetadataHashEntry(false);
+    return;
+  }
+
+  LLVMContextImpl::MDMapTy &Info = MetadataStore[this];
+  unsigned I;
+  unsigned E;
+  // Walk the array and drop any metadata we don't know.
+  for (I = 0, E = Info.size(); I != E;) {
+    if (KnownSet.count(Info[I].first)) {
+      ++I;
+      continue;
+    }
+
+    Info[I] = Info.back();
+    Info.pop_back();
+    --E;
+  }
+  assert(E == Info.size());
+
+  if (E == 0) {
+    // Drop our entry at the store.
+    MetadataStore.erase(this);
+    setHasMetadataHashEntry(false);
+  }
+}
+
 /// setMetadata - Set the metadata of of the specified kind to the specified
 /// node.  This updates/replaces metadata if already present, or removes it if
 /// Node is null.