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
This commit is contained in:
Victor Hernandez 2009-12-18 20:09:14 +00:00
parent 1edcafe10f
commit 5d30162150
4 changed files with 76 additions and 17 deletions

View 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

View 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) {

View 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.
//

View 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;