From 5d3016215075c52766711e741ce5401ee891d4ac Mon Sep 17 00:00:00 2001 From: Victor Hernandez Date: Fri, 18 Dec 2009 20:09:14 +0000 Subject: [PATCH] Formalize MDNode's function-localness: - 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 | 24 ++++++++++++++----- lib/VMCore/AsmWriter.cpp | 9 ++++---- lib/VMCore/Metadata.cpp | 50 +++++++++++++++++++++++++++++++++++----- lib/VMCore/Verifier.cpp | 10 ++++++++ 4 files changed, 76 insertions(+), 17 deletions(-) diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index 32c7fad203d..fd8ea0c13b2 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -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 *VisitedMDNodes = NULL); /// Profile - calculate a unique identifier for this MDNode to collapse /// duplicates diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index c765d968fcd..13905ea1906 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -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(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(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) { diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index ac91a40e10d..ba89e09ae56 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -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 *VisitedMDNodes) { + if (!isFunctionLocal()) + return true; + + if (!VisitedMDNodes) + VisitedMDNodes = new SmallPtrSet(); + + 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(V)) + LocalFunctionTemp = I->getParent()->getParent(); + else if (MDNode *MD = dyn_cast(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. // diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 7aa86b776c7..a1b89dedeab 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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(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; -- 2.34.1