Formalize MDNode's function-localness:
authorVictor Hernandez <vhernandez@apple.com>
Fri, 18 Dec 2009 20:09:14 +0000 (20:09 +0000)
committerVictor Hernandez <vhernandez@apple.com>
Fri, 18 Dec 2009 20:09:14 +0000 (20:09 +0000)
- an MDNode is designated as function-local when created, and continues to be even if its operands are modified not to refer to function-local IR
- function-localness is designated via lowest bit in SubclassData
- getLocalFunction() descends MDNode tree to see if it is consistently function-local

Add verification of MDNodes to checks that MDNodes are consistently function-local.
Update AsmWriter to use isFunctionLocal().

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

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

index 32c7fad203d1244cf0a82313cf248b539180561a..fd8ea0c13b2c0044d1ce5a1b49a2a7753e548fdd 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/Value.h"
 #include "llvm/Type.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/ilist_node.h"
 #include "llvm/Support/ValueHandle.h"
@@ -106,21 +107,22 @@ class MDNode : public MetadataBase, public FoldingSetNode {
       Parent->replaceElement(this->operator Value*(), NV);
     }
   };
+  
+  static const unsigned short FunctionLocalBit = 1;
+  
   // Replace each instance of F from the element list of this node with T.
   void replaceElement(Value *F, Value *T);
 
   ElementVH *Node;
   unsigned NodeSize;
-  Function *LocalFunction;
 
 protected:
   explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals,
-                  Function *LocalFunc = NULL);
+                  bool isFunctionLocal);
 public:
   // Constructors and destructors.
-  static MDNode *get(LLVMContext &Context, 
-                     Value *const *Vals, unsigned NumVals,
-                     Function *LocalFunction = NULL);
+  static MDNode *get(LLVMContext &Context, Value *const *Vals, unsigned NumVals,
+                     bool isFunctionLocal = false);
 
   /// ~MDNode - Destroy MDNode.
   ~MDNode();
@@ -135,7 +137,17 @@ public:
   unsigned getNumElements() const { return NodeSize; }
   
   /// isFunctionLocal - Return whether MDNode is local to a function.
-  bool isFunctionLocal() const { return LocalFunction; }
+  /// Note: MDNodes are designated as function-local when created, and keep
+  ///       that designation even if their operands are modified to no longer
+  ///       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
index c765d968fcde737de0ad690b4b9e5e515d29b48b..13905ea1906b88cfd4992bdec5a4b61fcf5d770b 100644 (file)
@@ -813,10 +813,9 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {
 void SlotTracker::CreateMetadataSlot(const MDNode *N) {
   assert(N && "Can't insert a null Value into SlotTracker!");
 
-  // Don't insert if N contains an instruction.
-  for (unsigned i = 0, e = N->getNumElements(); i != e; ++i)
-    if (N->getElement(i) && isa<Instruction>(N->getElement(i)))
-      return;
+  // Don't insert if N is a function-local metadata.
+  if (N->isFunctionLocal())
+    return;
 
   ValueMap::iterator I = mdnMap.find(N);
   if (I != mdnMap.end())
@@ -1232,7 +1231,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
   }
 
   if (const MDNode *N = dyn_cast<MDNode>(V)) {
-    if (Machine->getMetadataSlot(N) == -1) {
+    if (N->isFunctionLocal()) {
       // Print metadata inline, not via slot reference number.
       Out << "!{";
       for (unsigned mi = 0, me = N->getNumElements(); mi != me; ++mi) {
index ac91a40e10db2bb08251fa8f866e3ef52ced441d..ba89e09ae569ed73be01c943e0f46b3eeac8cd5e 100644 (file)
@@ -50,14 +50,15 @@ MDString *MDString::get(LLVMContext &Context, const char *Str) {
 // MDNode implementation.
 //
 MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals,
-               Function *LocalFunc)
+               bool isFunctionLocal)
   : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) {
   NodeSize = NumVals;
   Node = new ElementVH[NodeSize];
   ElementVH *Ptr = Node;
   for (unsigned i = 0; i != NumVals; ++i) 
     *Ptr++ = ElementVH(Vals[i], this);
-  LocalFunction = LocalFunc;
+  if (isFunctionLocal)
+    SubclassData |= FunctionLocalBit;
 }
 
 void MDNode::Profile(FoldingSetNodeID &ID) const {
@@ -66,19 +67,17 @@ void MDNode::Profile(FoldingSetNodeID &ID) const {
 }
 
 MDNode *MDNode::get(LLVMContext &Context, Value*const* Vals, unsigned NumVals,
-                    Function *LocalFunction) {
+                    bool isFunctionLocal) {
   LLVMContextImpl *pImpl = Context.pImpl;
   FoldingSetNodeID ID;
   for (unsigned i = 0; i != NumVals; ++i)
     ID.AddPointer(Vals[i]);
-  if (LocalFunction)
-    ID.AddPointer(LocalFunction);
 
   void *InsertPoint;
   MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
   if (!N) {
     // InsertPoint will have been set by the FindNodeOrInsertPos call.
-    N = new MDNode(Context, Vals, NumVals, LocalFunction);
+    N = new MDNode(Context, Vals, NumVals, isFunctionLocal);
     pImpl->MDNodeSet.InsertNode(N, InsertPoint);
   }
   return N;
@@ -146,6 +145,45 @@ 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 7aa86b776c76120268c392bf525bc79f2894bc07..a1b89dedeabb9bccb70da585339422b76c84953c 100644 (file)
@@ -1542,6 +1542,16 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
 #include "llvm/Intrinsics.gen"
 #undef GET_INTRINSIC_VERIFIER
 
+  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);
+    }
+
   switch (ID) {
   default:
     break;