From aea8ab800f4e846ad9af0a689ba6d8f382f2b404 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Mon, 12 Jan 2015 19:36:35 +0000 Subject: [PATCH] IR: Prevent handleChangedOperand() recursion 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 | 5 ++--- lib/IR/Metadata.cpp | 14 ++++++-------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 8033a17efd7..cf2dbd03ef2 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -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. diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index baa0b78762c..ec9b8801b81 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -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(); } -- 2.34.1