IR: Assert that resolve() is only called on uniqued nodes, NFC
[oota-llvm.git] / lib / IR / Metadata.cpp
index 859512db001585cf77e417b6d37f9edf3ee1361c..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,8 +227,8 @@ 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())
@@ -390,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) {
@@ -409,10 +413,10 @@ static bool isOperandUnresolved(Metadata *Op) {
   return false;
 }
 
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
-                             bool AllowRAUW)
-    : MDNode(C, GenericMDNodeKind, Vals) {
-  if (!AllowRAUW)
+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.
@@ -423,24 +427,16 @@ GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
   if (!NumUnresolved)
     return;
 
-  ReplaceableUses.reset(new ReplaceableMetadataImpl);
+  this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(C));
   SubclassData32 = NumUnresolved;
 }
 
-GenericMDNode::~GenericMDNode() {
-  LLVMContextImpl *pImpl = getContext().pImpl;
-  if (isStoredDistinctInContext())
-    pImpl->NonUniquedMDNodes.erase(this);
-  else
-    pImpl->MDNodeSet.erase(this);
-  dropAllReferences();
-}
-
-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");
 
@@ -448,23 +444,25 @@ void GenericMDNode::resolve() {
   Uses->resolveAllUses();
 }
 
-void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
   assert(SubclassData32 != 0 && "Expected unresolved operands");
 
   // Check if an operand was resolved.
-  if (!isOperandUnresolved(Old))
-    assert(isOperandUnresolved(New) && "Operand just became unresolved");
-  else if (!isOperandUnresolved(New))
+  if (!isOperandUnresolved(Old)) {
+    if (isOperandUnresolved(New))
+      // An operand was un-resolved!
+      ++SubclassData32;
+  } else if (!isOperandUnresolved(New))
     decrementUnresolvedOperandCount();
 }
 
-void GenericMDNode::decrementUnresolvedOperandCount() {
+void UniquableMDNode::decrementUnresolvedOperandCount() {
   if (!--SubclassData32)
     // Last unresolved operand has just been resolved.
     resolve();
 }
 
-void GenericMDNode::resolveCycles() {
+void UniquableMDNode::resolveCycles() {
   if (isResolved())
     return;
 
@@ -477,13 +475,13 @@ 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 GenericMDNode::recalculateHash() {
+void MDTuple::recalculateHash() {
   setHash(hash_combine_range(op_begin(), op_end()));
 #ifndef NDEBUG
   {
@@ -498,10 +496,10 @@ void GenericMDNode::recalculateHash() {
 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();
     }
 }
 
@@ -522,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");
 
@@ -534,30 +532,25 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *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.
   if (New == this) {
-    storeDistinctInContext();
     if (!isResolved())
       resolve();
+    storeDistinctInContext();
     return;
   }
 
   // Re-unique the node.
-  recalculateHash();
-  GenericMDNodeInfo::KeyTy Key(this);
-  auto I = Store.find_as(Key);
-  if (I == Store.end()) {
-    Store.insert(this);
-
+  auto *Uniqued = uniquify();
+  if (Uniqued == this) {
     if (!isResolved())
       resolveAfterOperandChange(Old, New);
-
     return;
   }
 
@@ -569,8 +562,8 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
     // dropAllReferences(), but we still need the use-list).
     for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
       setOperand(O, nullptr);
-    ReplaceableUses->replaceAllUsesWith(*I);
-    delete this;
+    Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
+    deleteAsSubclass();
     return;
   }
 
@@ -578,59 +571,191 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   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.
-  auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
+  auto *N = new (MDs.size()) MDTuple(Context, Uniqued, MDs);
   N->setHash(Key.Hash);
   Store.insert(N);
   return N;
 }
 
-MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
-  auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false);
+MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  auto *N = new (MDs.size()) MDTuple(Context, Distinct, MDs);
   N->storeDistinctInContext();
   return N;
 }
 
-MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
-                                    ArrayRef<Metadata *> MDs) {
-  MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
+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;
+}
+
+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;
 }
 
-void MDNode::deleteTemporary(MDNode *N) {
-  assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
-  delete cast<MDNodeFwdDecl>(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);
 }
 
-void MDNode::storeDistinctInContext() {
-  assert(!IsDistinctInContext && "Expected newly distinct metadata");
-  IsDistinctInContext = true;
-  auto *G = cast<GenericMDNode>(this);
-  G->setHash(0);
-  getContext().pImpl->NonUniquedMDNodes.insert(G);
+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);
 }
 
 void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
   if (getOperand(I) == New)
     return;
 
-  if (isDistinct()) {
+  if (!isUniqued()) {
     setOperand(I, New);
     return;
   }
 
-  cast<GenericMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
+  cast<UniquableMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
 }
 
 void MDNode::setOperand(unsigned I, Metadata *New) {