Rewrite the function-local validation logic for MDNodes (most of r91708).
authorChris Lattner <sabre@nondot.org>
Mon, 28 Dec 2009 09:07:21 +0000 (09:07 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 28 Dec 2009 09:07:21 +0000 (09:07 +0000)
Among other benefits, this doesn't leak the SmallPtrSet, has the verifier
code in the verifier pass, actually does the verification at the end,
and is considerably simpler.

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

include/llvm/Metadata.h
lib/VMCore/Metadata.cpp
lib/VMCore/Verifier.cpp

index 63601d2d25f1c74b9efee42822632a2ea48ca9bd..7cfaeafa8f1d7777e36424ed3a582dabb5d4f0b5 100644 (file)
@@ -27,7 +27,6 @@ class LLVMContext;
 class Module;
 class MetadataContextImpl;
 template <typename T> class SmallVectorImpl;
-template<class PtrType, unsigned SmallSize> class SmallPtrSet;
 
 //===----------------------------------------------------------------------===//
 // MetadataBase  - A base class for MDNode, MDString and NamedMDNode.
@@ -91,17 +90,20 @@ class MDNodeElement;
 /// MDNode is always unnamed.
 class MDNode : public MetadataBase, public FoldingSetNode {
   MDNode(const MDNode &);                // DO NOT IMPLEMENT
-
+  void operator=(const MDNode &);        // DO NOT IMPLEMENT
   friend class MDNodeElement;
+
+  MDNodeElement *Operands;
+  unsigned NumOperands;
   
-  static const unsigned short FunctionLocalBit = 1;
+  // Subclass data enums.
+  enum {
+    FunctionLocalBit = 1
+  };
   
   // Replace each instance of F from the element list of this node with T.
   void replaceElement(Value *F, Value *T);
 
-  MDNodeElement *Operands;
-  unsigned NumOperands;
-
 protected:
   explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals,
                   bool isFunctionLocal);
@@ -125,13 +127,6 @@ public:
   ///       refer to function-local IR.
   bool isFunctionLocal() const { return SubclassData & FunctionLocalBit; }
 
-  /// getLocalFunction - Return false if MDNode's recursive function-localness
-  /// is invalid (local to more than one function).  Return true otherwise.
-  /// If MDNode has one function to which it is local, set LocalFunction to that
-  /// function.
-  bool getLocalFunction(Function *LocalFunction,
-                        SmallPtrSet<MDNode *, 32> *VisitedMDNodes = NULL);
-
   /// Profile - calculate a unique identifier for this MDNode to collapse
   /// duplicates
   void Profile(FoldingSetNodeID &ID) const;
index 01b47d676798d73f780899a1ecec0e51ead76591..c1213a3d3a9d789c537fa894ebf9b6a5ee08d937 100644 (file)
@@ -188,46 +188,6 @@ void MDNode::replaceElement(Value *From, Value *To) {
   }
 }
 
-// getLocalFunction - Return false if MDNode's recursive function-localness is
-// invalid (local to more than one function).  Return true otherwise. If MDNode
-// has one function to which it is local, set LocalFunction to that function.
-bool MDNode::getLocalFunction(Function *LocalFunction,
-                              SmallPtrSet<MDNode *, 32> *VisitedMDNodes) {
-  if (!isFunctionLocal())
-    return true;
-    
-  if (!VisitedMDNodes)
-    VisitedMDNodes = new SmallPtrSet<MDNode *, 32>();
-    
-  if (!VisitedMDNodes->insert(this))
-    // MDNode has already been visited, nothing to do.
-    return true;
-
-  for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
-    Value *V = getElement(i);
-    if (!V) continue;
-
-    Function *LocalFunctionTemp = NULL;
-    if (Instruction *I = dyn_cast<Instruction>(V))
-      LocalFunctionTemp = I->getParent()->getParent();
-    else if (MDNode *MD = dyn_cast<MDNode>(V))
-      if (!MD->getLocalFunction(LocalFunctionTemp, VisitedMDNodes))
-        // This MDNode's operand is function-locally invalid or local to a
-        // different function.
-        return false;
-
-    if (LocalFunctionTemp) {
-      if (!LocalFunction)
-        LocalFunction = LocalFunctionTemp;
-      else if (LocalFunction != LocalFunctionTemp)
-        // This MDNode contains operands that are local to different functions.
-        return false;
-    }
-  }
-    
-  return true;
-}
-
 //===----------------------------------------------------------------------===//
 // NamedMDNode implementation.
 //
index a1b89dedeabb9bccb70da585339422b76c84953c..b7e87711ae4ace8a81b95d81d03b5cdb7d0a82e1 100644 (file)
@@ -329,6 +329,8 @@ namespace {
                           int VT, unsigned ArgNo, std::string &Suffix);
     void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
                                   unsigned RetNum, unsigned ParamNum, ...);
+    void VerifyFunctionLocalMetadata(MDNode *N, Function *F,
+                                     SmallPtrSet<MDNode *, 32> &Visited);
     void VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
                               bool isReturnValue, const Value *V);
     void VerifyFunctionAttrs(const FunctionType *FT, const AttrListPtr &Attrs,
@@ -1526,6 +1528,38 @@ void Verifier::VerifyType(const Type *Ty) {
   }
 }
 
+/// VerifyFunctionLocalMetadata - Verify that the specified MDNode is local to
+/// specified Function.
+void Verifier::VerifyFunctionLocalMetadata(MDNode *N, Function *F,
+                                           SmallPtrSet<MDNode *, 32> &Visited) {
+  assert(N->isFunctionLocal() && "Should only be called on function-local MD");
+
+  // Only visit each node once.
+  if (!Visited.insert(N))
+    return;
+  
+  for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) {
+    Value *V = N->getElement(i);
+    if (!V) continue;
+    
+    Function *ActualF = 0;
+    if (Instruction *I = dyn_cast<Instruction>(V))
+      ActualF = I->getParent()->getParent();
+    else if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
+      ActualF = BB->getParent();
+    else if (Argument *A = dyn_cast<Argument>(V))
+      ActualF = A->getParent();
+    else if (MDNode *MD = dyn_cast<MDNode>(V))
+      if (MD->isFunctionLocal())
+        VerifyFunctionLocalMetadata(MD, F, Visited);
+
+    // If this was an instruction, bb, or argument, verify that it is in the
+    // function that we expect.
+    Assert1(ActualF == 0 || ActualF == F,
+            "function-local metadata used in wrong function", N);
+  }
+}
+
 // Flags used by TableGen to mark intrinsic parameters with the
 // LLVMExtendedElementVectorType and LLVMTruncatedElementVectorType classes.
 static const unsigned ExtendedElementVectorType = 0x40000000;
@@ -1542,14 +1576,13 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
 #include "llvm/Intrinsics.gen"
 #undef GET_INTRINSIC_VERIFIER
 
+  // If the intrinsic takes MDNode arguments, verify that they are either global
+  // or are local to *this* function.
   for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)
     if (MDNode *MD = dyn_cast<MDNode>(CI.getOperand(i))) {
-      Function* LocalFunction = NULL;
-      Assert1(MD && MD->getLocalFunction(LocalFunction),
-              "invalid function-local metadata", &CI);
-      if (LocalFunction)
-        Assert1(LocalFunction == CI.getParent()->getParent(),
-                "function-local metadata used in wrong function", &CI);
+      if (!MD->isFunctionLocal()) continue;
+      SmallPtrSet<MDNode *, 32> Visited;
+      VerifyFunctionLocalMetadata(MD, CI.getParent()->getParent(), Visited);
     }
 
   switch (ID) {