IR: Assert that resolve() is only called on uniqued nodes, NFC
[oota-llvm.git] / lib / IR / Metadata.cpp
index 4b099ec255f3f60fc5882eb9db554f800adb6a43..8a4710444f34feb5a3d829d1f5b1e7bb68242ff6 100644 (file)
@@ -167,6 +167,11 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
     return L.second.second < R.second.second;
   });
   for (const auto &Pair : Uses) {
+    // Check that this Ref hasn't disappeared after RAUW (when updating a
+    // previous Ref).
+    if (!UseMap.count(Pair.first))
+      continue;
+
     OwnerTy Owner = Pair.second.first;
     if (!Owner) {
       // Update unowned tracking references directly.
@@ -222,15 +227,13 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
     if (Owner.is<MetadataAsValue *>())
       continue;
 
-    // Resolve GenericMDNodes that point at this.
-    auto *OwnerMD = dyn_cast<GenericMDNode>(Owner.get<Metadata *>());
+    // Resolve UniquableMDNodes that point at this.
+    auto *OwnerMD = dyn_cast<UniquableMDNode>(Owner.get<Metadata *>());
     if (!OwnerMD)
       continue;
     if (OwnerMD->isResolved())
       continue;
-    OwnerMD->decrementUnresolvedOperands();
-    if (!OwnerMD->hasUnresolvedOperands())
-      OwnerMD->resolve();
+    OwnerMD->decrementUnresolvedOperandCount();
   }
 }
 
@@ -255,9 +258,9 @@ ValueAsMetadata *ValueAsMetadata::get(Value *V) {
            "Expected this to be the only metadata use");
     V->NameAndIsUsedByMD.setInt(true);
     if (auto *C = dyn_cast<Constant>(V))
-      Entry = new ConstantAsMetadata(Context, C);
+      Entry = new ConstantAsMetadata(C);
     else
-      Entry = new LocalAsMetadata(Context, V);
+      Entry = new LocalAsMetadata(V);
   }
 
   return Entry;
@@ -392,17 +395,16 @@ void MDNode::operator delete(void *Mem) {
   ::operator delete(O);
 }
 
-MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
-    : Metadata(ID), Context(Context), NumOperands(MDs.size()),
+MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
+               ArrayRef<Metadata *> MDs)
+    : Metadata(ID, Storage), Context(Context), NumOperands(MDs.size()),
       MDNodeSubclassData(0) {
   for (unsigned I = 0, E = MDs.size(); I != E; ++I)
     setOperand(I, MDs[I]);
-}
 
-bool MDNode::isResolved() const {
-  if (isa<MDNodeFwdDecl>(this))
-    return false;
-  return cast<GenericMDNode>(this)->isResolved();
+  if (Storage == Temporary)
+    this->Context.makeReplaceable(
+        make_unique<ReplaceableMetadataImpl>(Context));
 }
 
 static bool isOperandUnresolved(Metadata *Op) {
@@ -411,31 +413,30 @@ static bool isOperandUnresolved(Metadata *Op) {
   return false;
 }
 
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
-    : MDNode(C, GenericMDNodeKind, Vals) {
+UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID,
+                                 StorageType Storage, ArrayRef<Metadata *> Vals)
+    : MDNode(C, ID, Storage, Vals) {
+  if (Storage != Uniqued)
+    return;
+
   // Check whether any operands are unresolved, requiring re-uniquing.
+  unsigned NumUnresolved = 0;
   for (const auto &Op : operands())
-    if (isOperandUnresolved(Op))
-      incrementUnresolvedOperands();
+    NumUnresolved += unsigned(isOperandUnresolved(Op));
 
-  if (hasUnresolvedOperands())
-    ReplaceableUses.reset(new ReplaceableMetadataImpl);
-}
+  if (!NumUnresolved)
+    return;
 
-GenericMDNode::~GenericMDNode() {
-  LLVMContextImpl *pImpl = getContext().pImpl;
-  if (isStoredDistinctInContext())
-    pImpl->NonUniquedMDNodes.erase(this);
-  else
-    pImpl->MDNodeSet.erase(this);
-  dropAllReferences();
+  this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(C));
+  SubclassData32 = NumUnresolved;
 }
 
-void GenericMDNode::resolve() {
+void UniquableMDNode::resolve() {
+  assert(Storage == Uniqued && "Expected this to be uniqued");
   assert(!isResolved() && "Expected this to be unresolved");
 
   // Move the map, so that this immediately looks resolved.
-  auto Uses = std::move(ReplaceableUses);
+  auto Uses = Context.takeReplaceableUses();
   SubclassData32 = 0;
   assert(isResolved() && "Expected this to be resolved");
 
@@ -443,7 +444,25 @@ void GenericMDNode::resolve() {
   Uses->resolveAllUses();
 }
 
-void GenericMDNode::resolveCycles() {
+void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+  assert(SubclassData32 != 0 && "Expected unresolved operands");
+
+  // Check if an operand was resolved.
+  if (!isOperandUnresolved(Old)) {
+    if (isOperandUnresolved(New))
+      // An operand was un-resolved!
+      ++SubclassData32;
+  } else if (!isOperandUnresolved(New))
+    decrementUnresolvedOperandCount();
+}
+
+void UniquableMDNode::decrementUnresolvedOperandCount() {
+  if (!--SubclassData32)
+    // Last unresolved operand has just been resolved.
+    resolve();
+}
+
+void UniquableMDNode::resolveCycles() {
   if (isResolved())
     return;
 
@@ -456,19 +475,31 @@ void GenericMDNode::resolveCycles() {
       continue;
     assert(!isa<MDNodeFwdDecl>(Op) &&
            "Expected all forward declarations to be resolved");
-    if (auto *N = dyn_cast<GenericMDNode>(Op))
+    if (auto *N = dyn_cast<UniquableMDNode>(Op))
       if (!N->isResolved())
         N->resolveCycles();
   }
 }
 
+void MDTuple::recalculateHash() {
+  setHash(hash_combine_range(op_begin(), op_end()));
+#ifndef NDEBUG
+  {
+    SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
+    unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
+    assert(getHash() == RawHash &&
+           "Expected hash of MDOperand to equal hash of Metadata*");
+  }
+#endif
+}
+
 void MDNode::dropAllReferences() {
   for (unsigned I = 0, E = NumOperands; I != E; ++I)
     setOperand(I, nullptr);
-  if (auto *G = dyn_cast<GenericMDNode>(this))
-    if (!G->isResolved()) {
-      G->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
-      G->ReplaceableUses.reset();
+  if (auto *N = dyn_cast<UniquableMDNode>(this))
+    if (!N->isResolved()) {
+      N->Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
+      (void)N->Context.takeReplaceableUses();
     }
 }
 
@@ -489,7 +520,7 @@ namespace llvm {
 static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
 }
 
-void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
+void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
   assert(Op < getNumOperands() && "Expected valid operand");
 
@@ -500,129 +531,231 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
     setOperand(Op, New);
     return;
   }
-  if (InRAUW) {
-    // We just hit a recursion due to RAUW.  Set the operand and move on, since
-    // we're about to be deleted.
-    //
-    // FIXME: Can this cycle really happen?
-    setOperand(Op, New);
-    return;
-  }
 
-  auto &Store = getContext().pImpl->MDNodeSet;
-  Store.erase(this);
+  // This node is uniqued.
+  eraseFromStore();
 
   Metadata *Old = getOperand(Op);
   setOperand(Op, New);
 
-  // Drop uniquing for self-reference cycles or if an operand drops to null.
-  //
-  // FIXME: Stop dropping uniquing when an operand drops to null.  The original
-  // motivation was to prevent madness during teardown of LLVMContextImpl, but
-  // dropAllReferences() fixes that problem in a better way.  (It's just here
-  // now for better staging of semantic changes.)
-  if (New == this || !New) {
-    storeDistinctInContext();
-    setHash(0);
+  // Drop uniquing for self-reference cycles.
+  if (New == this) {
     if (!isResolved())
       resolve();
+    storeDistinctInContext();
     return;
   }
 
-  // Re-calculate the hash.
-  setHash(hash_combine_range(op_begin(), op_end()));
-#ifndef NDEBUG
-  {
-    SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
-    unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
-    assert(getHash() == RawHash &&
-           "Expected hash of MDOperand to equal hash of Metadata*");
-  }
-#endif
-
   // Re-unique the node.
-  GenericMDNodeInfo::KeyTy Key(this);
-  auto I = Store.find_as(Key);
-  if (I == Store.end()) {
-    Store.insert(this);
-
-    if (!isResolved()) {
-      // Check if the last unresolved operand has just been resolved; if so,
-      // resolve this as well.
-      if (isOperandUnresolved(Old))
-        decrementUnresolvedOperands();
-      if (isOperandUnresolved(New))
-        incrementUnresolvedOperands();
-      if (!hasUnresolvedOperands())
-        resolve();
-    }
-
+  auto *Uniqued = uniquify();
+  if (Uniqued == this) {
+    if (!isResolved())
+      resolveAfterOperandChange(Old, New);
     return;
   }
 
   // Collision.
   if (!isResolved()) {
     // Still unresolved, so RAUW.
-    InRAUW = true;
-    ReplaceableUses->replaceAllUsesWith(*I);
-    delete this;
+    //
+    // First, clear out all operands to prevent any recursion (similar to
+    // dropAllReferences(), but we still need the use-list).
+    for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
+      setOperand(O, nullptr);
+    Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
+    deleteAsSubclass();
     return;
   }
 
-  // Store in non-uniqued form if this node has already been resolved.
-  setHash(0);
+  // Store in non-uniqued form if RAUW isn't possible.
   storeDistinctInContext();
 }
 
-MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
-                          bool Insert) {
-  auto &Store = Context.pImpl->MDNodeSet;
+void UniquableMDNode::deleteAsSubclass() {
+  switch (getMetadataID()) {
+  default:
+    llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS)                                           \
+  case CLASS##Kind:                                                            \
+    delete cast<CLASS>(this);                                                  \
+    break;
+#include "llvm/IR/Metadata.def"
+  }
+}
 
-  GenericMDNodeInfo::KeyTy Key(MDs);
+UniquableMDNode *UniquableMDNode::uniquify() {
+  switch (getMetadataID()) {
+  default:
+    llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS)                                           \
+  case CLASS##Kind:                                                            \
+    return cast<CLASS>(this)->uniquifyImpl();
+#include "llvm/IR/Metadata.def"
+  }
+}
+
+void UniquableMDNode::eraseFromStore() {
+  switch (getMetadataID()) {
+  default:
+    llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS)                                           \
+  case CLASS##Kind:                                                            \
+    cast<CLASS>(this)->eraseFromStoreImpl();                                   \
+    break;
+#include "llvm/IR/Metadata.def"
+  }
+}
+
+MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+                          bool ShouldCreate) {
+  MDTupleInfo::KeyTy Key(MDs);
+
+  auto &Store = Context.pImpl->MDTuples;
   auto I = Store.find_as(Key);
   if (I != Store.end())
     return *I;
-  if (!Insert)
+  if (!ShouldCreate)
     return nullptr;
 
   // Coallocate space for the node and Operands together, then placement new.
-  GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
+  auto *N = new (MDs.size()) MDTuple(Context, Uniqued, MDs);
   N->setHash(Key.Hash);
   Store.insert(N);
   return N;
 }
 
-MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
-                                    ArrayRef<Metadata *> MDs) {
-  MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
+MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  auto *N = new (MDs.size()) MDTuple(Context, Distinct, MDs);
+  N->storeDistinctInContext();
   return N;
 }
 
-void MDNode::deleteTemporary(MDNode *N) {
-  assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
-  delete cast<MDNodeFwdDecl>(N);
+MDTuple *MDTuple::uniquifyImpl() {
+  recalculateHash();
+  MDTupleInfo::KeyTy Key(this);
+
+  auto &Store = getContext().pImpl->MDTuples;
+  auto I = Store.find_as(Key);
+  if (I == Store.end()) {
+    Store.insert(this);
+    return this;
+  }
+  return *I;
+}
+
+void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
+
+MDLocation::MDLocation(LLVMContext &C, StorageType Storage, unsigned Line,
+                       unsigned Column, ArrayRef<Metadata *> MDs)
+    : UniquableMDNode(C, MDLocationKind, Storage, MDs) {
+  assert((MDs.size() == 1 || MDs.size() == 2) &&
+         "Expected a scope and optional inlined-at");
+
+  // Set line and column.
+  assert(Line < (1u << 24) && "Expected 24-bit line");
+  assert(Column < (1u << 16) && "Expected 16-bit column");
+
+  MDNodeSubclassData = Line;
+  SubclassData16 = Column;
+}
+
+MDLocation *MDLocation::constructHelper(LLVMContext &Context,
+                                        StorageType Storage, unsigned Line,
+                                        unsigned Column, Metadata *Scope,
+                                        Metadata *InlinedAt) {
+  SmallVector<Metadata *, 2> Ops;
+  Ops.push_back(Scope);
+  if (InlinedAt)
+    Ops.push_back(InlinedAt);
+  return new (Ops.size()) MDLocation(Context, Storage, Line, Column, Ops);
+}
+
+static void adjustLine(unsigned &Line) {
+  // Set to unknown on overflow.  Still use 24 bits for now.
+  if (Line >= (1u << 24))
+    Line = 0;
 }
 
-void MDNode::storeDistinctInContext() {
-  assert(!IsDistinctInContext && "Expected newly distinct metadata");
-  IsDistinctInContext = true;
-  auto *G = cast<GenericMDNode>(this);
-  G->setHash(0);
-  getContext().pImpl->NonUniquedMDNodes.insert(G);
+static void adjustColumn(unsigned &Column) {
+  // Set to unknown on overflow.  We only have 16 bits to play with here.
+  if (Column >= (1u << 16))
+    Column = 0;
+}
+
+MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
+                                unsigned Column, Metadata *Scope,
+                                Metadata *InlinedAt, bool ShouldCreate) {
+  // Fixup line/column.
+  adjustLine(Line);
+  adjustColumn(Column);
+
+  MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt);
+
+  auto &Store = Context.pImpl->MDLocations;
+  auto I = Store.find_as(Key);
+  if (I != Store.end())
+    return *I;
+  if (!ShouldCreate)
+    return nullptr;
+
+  auto *N = constructHelper(Context, Uniqued, Line, Column, Scope, InlinedAt);
+  Store.insert(N);
+  return N;
+}
+
+MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line,
+                                    unsigned Column, Metadata *Scope,
+                                    Metadata *InlinedAt) {
+  // Fixup line/column.
+  adjustLine(Line);
+  adjustColumn(Column);
+
+  auto *N = constructHelper(Context, Distinct, Line, Column, Scope, InlinedAt);
+  N->storeDistinctInContext();
+  return N;
+}
+
+MDLocation *MDLocation::uniquifyImpl() {
+  MDLocationInfo::KeyTy Key(this);
+
+  auto &Store = getContext().pImpl->MDLocations;
+  auto I = Store.find_as(Key);
+  if (I == Store.end()) {
+    Store.insert(this);
+    return this;
+  }
+  return *I;
+}
+
+void MDLocation::eraseFromStoreImpl() {
+  getContext().pImpl->MDLocations.erase(this);
+}
+
+MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
+                                    ArrayRef<Metadata *> MDs) {
+  return MDNodeFwdDecl::get(Context, MDs);
+}
+
+void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
+
+void UniquableMDNode::storeDistinctInContext() {
+  assert(isResolved() && "Expected resolved nodes");
+  Storage = Distinct;
+  if (auto *T = dyn_cast<MDTuple>(this))
+    T->setHash(0);
+  getContext().pImpl->DistinctMDNodes.insert(this);
 }
 
-// Replace value from this node's operand list.
 void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
   if (getOperand(I) == New)
     return;
 
-  if (auto *N = dyn_cast<GenericMDNode>(this)) {
-    N->handleChangedOperand(mutable_begin() + I, New);
+  if (!isUniqued()) {
+    setOperand(I, New);
     return;
   }
 
-  assert(isa<MDNodeFwdDecl>(this) && "Expected an MDNode");
-  setOperand(I, New);
+  cast<UniquableMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
 }
 
 void MDNode::setOperand(unsigned I, Metadata *New) {
@@ -841,6 +974,11 @@ MDNode *NamedMDNode::getOperand(unsigned i) const {
 
 void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); }
 
+void NamedMDNode::setOperand(unsigned I, MDNode *New) {
+  assert(I < getNumOperands() && "Invalid operand number");
+  getNMDOps(Operands)[I].reset(New);
+}
+
 void NamedMDNode::eraseFromParent() {
   getParent()->eraseNamedMetadata(this);
 }