diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2009-04-04 07:22:01 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2009-04-04 07:22:01 +0000 |
commit | 4dcf810bd693551137f97e79a155bf470ae08bf0 (patch) | |
tree | 6f5a7d6d7f4693fe0b16635fc34ac7c99174331d /lib/VMCore | |
parent | 20fe71b8dc6efe6380e8cb5aebd3edef3a66db3f (diff) | |
download | external_llvm-4dcf810bd693551137f97e79a155bf470ae08bf0.zip external_llvm-4dcf810bd693551137f97e79a155bf470ae08bf0.tar.gz external_llvm-4dcf810bd693551137f97e79a155bf470ae08bf0.tar.bz2 |
Add support for embedded metadata to LLVM. This introduces two new types of
Constant, MDString and MDNode which can only be used by globals with a name
that starts with "llvm." or as arguments to a function with the same naming
restriction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68420 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 25 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 80 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 2 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 51 |
4 files changed, 155 insertions, 3 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 3f8be47..83fc35b 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -23,6 +23,7 @@ #include "llvm/InlineAsm.h" #include "llvm/Instruction.h" #include "llvm/Instructions.h" +#include "llvm/Metadata.h" #include "llvm/Module.h" #include "llvm/ValueSymbolTable.h" #include "llvm/TypeSymbolTable.h" @@ -361,8 +362,8 @@ namespace { return; // If this is a structure or opaque type, add a name for the type. - if ((isa<StructType>(Ty) || isa<OpaqueType>(Ty)) - && !TP.hasTypeName(Ty)) { + if (((isa<StructType>(Ty) && cast<StructType>(Ty)->getNumElements()) + || isa<OpaqueType>(Ty)) && !TP.hasTypeName(Ty)) { TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size()))); NumberedTypes.push_back(Ty); } @@ -935,7 +936,27 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV, Out << "undef"; return; } + + if (const MDString *S = dyn_cast<MDString>(CV)) { + Out << "!\""; + PrintEscapedString(S->begin(), S->size(), Out); + Out << '"'; + return; + } + if (const MDNode *N = dyn_cast<MDNode>(CV)) { + Out << "!{"; + for (MDNode::const_op_iterator I = N->op_begin(), E = N->op_end(); I != E;){ + TypePrinter.print((*I)->getType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, *I, TypePrinter, Machine); + if (++I != E) + Out << ", "; + } + Out << "}"; + return; + } + if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { Out << CE->getOpcodeName(); if (CE->isCompare()) diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 7cd3599..2afaa6c 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -17,7 +17,9 @@ #include "llvm/GlobalValue.h" #include "llvm/Instructions.h" #include "llvm/Module.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" @@ -1657,6 +1659,63 @@ void UndefValue::destroyConstant() { destroyConstantImpl(); } +//---- MDString::get() implementation +// + +MDString::MDString(const char *begin, const char *end) + : Constant(Type::EmptyStructTy, MDStringVal, 0, 0), + StrBegin(begin), StrEnd(end) {} + +static ManagedStatic<StringMap<MDString*> > MDStringCache; + +MDString *MDString::get(const char *StrBegin, const char *StrEnd) { + StringMapEntry<MDString *> &Entry = MDStringCache->GetOrCreateValue(StrBegin, + StrEnd); + MDString *&S = Entry.getValue(); + if (!S) S = new MDString(Entry.getKeyData(), + Entry.getKeyData() + Entry.getKeyLength()); + return S; +} + +void MDString::destroyConstant() { + MDStringCache->erase(MDStringCache->find(StrBegin, StrEnd)); + destroyConstantImpl(); +} + +//---- MDNode::get() implementation +// + +static ManagedStatic<FoldingSet<MDNode> > MDNodeSet; + +MDNode::MDNode(Constant*const* Vals, unsigned NumVals) + : Constant(Type::EmptyStructTy, MDNodeVal, + OperandTraits<MDNode>::op_end(this) - NumVals, NumVals) { + std::copy(Vals, Vals + NumVals, OperandList); +} + +void MDNode::Profile(FoldingSetNodeID &ID) { + for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) + ID.AddPointer(*I); +} + +MDNode *MDNode::get(Constant*const* Vals, unsigned NumVals) { + FoldingSetNodeID ID; + for (unsigned i = 0; i != NumVals; ++i) + ID.AddPointer(Vals[i]); + + void *InsertPoint; + if (MDNode *N = MDNodeSet->FindNodeOrInsertPos(ID, InsertPoint)) + return N; + + // InsertPoint will have been set by the FindNodeOrInsertPos call. + MDNode *N = new(NumVals) MDNode(Vals, NumVals); + MDNodeSet->InsertNode(N, InsertPoint); + return N; +} + +void MDNode::destroyConstant() { + destroyConstantImpl(); +} //---- ConstantExpr::get() implementations... // @@ -2741,3 +2800,24 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, // Delete the old constant! destroyConstant(); } + +void MDNode::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { + assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); + + SmallVector<Constant*, 8> Values; + Values.reserve(getNumOperands()); // Build replacement array... + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = cast<Constant>(To); + Values.push_back(Val); + } + + Constant *Replacement = MDNode::get(&Values[0], Values.size()); + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 237ec05..c14d511 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -288,6 +288,8 @@ const IntegerType *Type::Int16Ty = new BuiltinIntegerType(16); const IntegerType *Type::Int32Ty = new BuiltinIntegerType(32); const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64); +const Type *Type::EmptyStructTy = StructType::get(NULL, NULL); + //===----------------------------------------------------------------------===// // Derived Type Constructors diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 5af66df..df9acee 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -338,6 +338,36 @@ static RegisterPass<Verifier> X("verify", "Module Verifier"); #define Assert4(C, M, V1, V2, V3, V4) \ do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0) +/// Check whether or not a Value is metadata or made up of a constant +/// expression involving metadata. +static bool isMetadata(Value *X) { + SmallPtrSet<Value *, 8> Visited; + SmallVector<Value *, 8> Queue; + Queue.push_back(X); + + while (!Queue.empty()) { + Value *V = Queue.back(); + Queue.pop_back(); + if (!Visited.insert(V)) + continue; + + if (isa<MDString>(V) || isa<MDNode>(V)) + return true; + if (!isa<ConstantExpr>(V)) + continue; + ConstantExpr *CE = cast<ConstantExpr>(V); + + if (CE->getType() != Type::EmptyStructTy) + continue; + + // The only constant expression that works on metadata type is select. + if (CE->getOpcode() != Instruction::Select) return false; + + Queue.push_back(CE->getOperand(1)); + Queue.push_back(CE->getOperand(2)); + } + return false; +} void Verifier::visit(Instruction &I) { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) @@ -649,6 +679,7 @@ void Verifier::visitReturnInst(ReturnInst &RI) { "Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); else if (N == 1 && F->getReturnType() == RI.getOperand(0)->getType()) { + Assert1(!isMetadata(RI.getOperand(0)), "Invalid use of metadata!", &RI); // Exactly one return value and it matches the return type. Good. } else if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) { // The return type is a struct; check for multiple return values. @@ -696,6 +727,8 @@ void Verifier::visitSelectInst(SelectInst &SI) { Assert1(SI.getTrueValue()->getType() == SI.getType(), "Select values must have same type as select instruction!", &SI); + Assert1(!isMetadata(SI.getOperand(1)) && !isMetadata(SI.getOperand(2)), + "Invalid use of metadata!", &SI); visitInstruction(SI); } @@ -951,6 +984,13 @@ void Verifier::visitPHINode(PHINode &PN) { Assert1(PN.getType() == PN.getIncomingValue(i)->getType(), "PHI node operands are not the same type as the result!", &PN); + // Check that it's not a PHI of metadata. + if (PN.getType() == Type::EmptyStructTy) { + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + Assert1(!isMetadata(PN.getIncomingValue(i)), + "Invalid use of metadata!", &PN); + } + // All other PHI node constraints are checked in the visitBasicBlock method. visitInstruction(PN); @@ -981,6 +1021,14 @@ void Verifier::VerifyCallSite(CallSite CS) { "Call parameter type does not match function signature!", CS.getArgument(i), FTy->getParamType(i), I); + if (CS.getCalledValue()->getNameLen() < 5 || + strncmp(CS.getCalledValue()->getNameStart(), "llvm.", 5) != 0) { + // Verify that none of the arguments are metadata... + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + Assert2(!isMetadata(CS.getArgument(i)), "Invalid use of metadata!", + CS.getArgument(i), I); + } + const AttrListPtr &Attrs = CS.getAttributes(); Assert1(VerifyAttributeCount(Attrs, CS.arg_size()), @@ -1152,6 +1200,7 @@ void Verifier::visitStoreInst(StoreInst &SI) { cast<PointerType>(SI.getOperand(1)->getType())->getElementType(); Assert2(ElTy == SI.getOperand(0)->getType(), "Stored value type does not match pointer operand type!", &SI, ElTy); + Assert1(!isMetadata(SI.getOperand(0)), "Invalid use of metadata!", &SI); visitInstruction(SI); } @@ -1481,7 +1530,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty, if (EltTy != Ty) Suffix += "v" + utostr(NumElts); - Suffix += "i" + utostr(GotBits);; + Suffix += "i" + utostr(GotBits); // Check some constraints on various intrinsics. switch (ID) { |