diff options
Diffstat (limited to 'llvm/lib/VMCore/Metadata.cpp')
| -rw-r--r-- | llvm/lib/VMCore/Metadata.cpp | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/llvm/lib/VMCore/Metadata.cpp b/llvm/lib/VMCore/Metadata.cpp index ac91a40e10d..ba89e09ae56 100644 --- a/llvm/lib/VMCore/Metadata.cpp +++ b/llvm/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<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. // |

