IR: Prevent handleChangedOperand() recursion
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Mon, 12 Jan 2015 19:36:35 +0000 (19:36 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Mon, 12 Jan 2015 19:36:35 +0000 (19:36 +0000)
Instead of returning early on `handleChangedOperand()` recursion
(finally identified (and test added) in r225657), prevent it upfront by
releasing operands before RAUW.

Aside from massively different program flow, there should be no
functionality change ;).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225665 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Metadata.h
lib/IR/Metadata.cpp

index 8033a17efd7d917f9c6d2bf15a3286c838c0ecbf..cf2dbd03ef2c47d1d6deea84cab9430aa4e46c78 100644 (file)
@@ -49,7 +49,6 @@ class Metadata {
 protected:
   /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
   bool IsDistinctInContext : 1;
-  bool InRAUW : 1;
   // TODO: expose remaining bits to subclasses.
 
   unsigned short SubclassData16;
@@ -66,8 +65,8 @@ public:
 
 protected:
   Metadata(unsigned ID)
-      : SubclassID(ID), IsDistinctInContext(false), InRAUW(false),
-        SubclassData16(0), SubclassData32(0) {}
+      : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
+        SubclassData32(0) {}
   ~Metadata() {}
 
   /// \brief Store this in a big non-uniqued untyped bucket.
index baa0b78762c2b930b1251657a74faf98878f9561..ec9b8801b81e0a8e25ac7f09098212e485d4a149 100644 (file)
@@ -534,12 +534,6 @@ 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.
-    setOperand(Op, New);
-    return;
-  }
 
   auto &Store = getContext().pImpl->MDNodeSet;
   Store.erase(this);
@@ -571,13 +565,17 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   // Collision.
   if (!isResolved()) {
     // Still unresolved, so RAUW.
-    InRAUW = true;
+    //
+    // 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);
     ReplaceableUses->replaceAllUsesWith(*I);
     delete this;
     return;
   }
 
-  // Store in non-uniqued form if this node has already been resolved.
+  // Store in non-uniqued form if RAUW isn't possible.
   storeDistinctInContext();
 }