From 104cf9e02b0ed94d4173869a598af6c6972a8660 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Thu, 23 Jul 2009 01:07:34 +0000 Subject: [PATCH] Derive MDNode from MetadataBase instead of Constant. Emit MDNodes into METADATA_BLOCK in bitcode file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76834 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/LLVMBitCodes.h | 6 +-- include/llvm/MDNode.h | 44 +++------------------- include/llvm/Value.h | 2 +- lib/AsmParser/LLParser.cpp | 33 ++++++++++------ lib/AsmParser/LLParser.h | 6 +-- lib/Bitcode/Reader/BitcodeReader.cpp | 33 ++++++++-------- lib/Bitcode/Writer/BitcodeWriter.cpp | 46 +++++++++++++---------- lib/Bitcode/Writer/ValueEnumerator.cpp | 28 +++++++------- lib/VMCore/AsmWriter.cpp | 5 +++ lib/VMCore/Constants.cpp | 11 +----- lib/VMCore/LLVMContextImpl.cpp | 2 +- test/Feature/embeddedmetadata.ll | 7 ++++ test/Feature/mdnode2.ll | 8 ---- test/Feature/mdnode3.ll | 3 -- test/Feature/mdnode4.ll | 6 --- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 2 +- unittests/VMCore/MetadataTest.cpp | 19 ---------- 17 files changed, 108 insertions(+), 153 deletions(-) delete mode 100644 test/Feature/mdnode2.ll delete mode 100644 test/Feature/mdnode3.ll delete mode 100644 test/Feature/mdnode4.ll diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 6847ac9472b..3d8c2469147 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -108,7 +108,8 @@ namespace bitc { }; enum MetadataCodes { - METADATA_STRING = 1 // MDString: [values] + METADATA_STRING = 1, // MDString: [values] + METADATA_NODE = 2 // MDNODE: [n x (type num, value num)] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each // constant and maintains an implicit current type value. @@ -131,8 +132,7 @@ namespace bitc { CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval] CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred] CST_CODE_INLINEASM = 18, // INLINEASM: [sideeffect,asmstr,conststr] - CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval] - CST_CODE_MDNODE = 21 // MDNODE: [n x (type num, value num)] + CST_CODE_CE_SHUFVEC_EX = 19 // SHUFVEC_EX: [opty, opval, opval, opval] }; /// CastOpcodes - These are values used in the bitcode files to encode which diff --git a/include/llvm/MDNode.h b/include/llvm/MDNode.h index d3af74a804f..a06d720bf11 100644 --- a/include/llvm/MDNode.h +++ b/include/llvm/MDNode.h @@ -53,7 +53,7 @@ public: /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const MDString *) { return true; } static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + return V->getValueID() == MDStringVal || V->getValueID() == MDNodeVal; } }; @@ -91,53 +91,22 @@ public: //===----------------------------------------------------------------------===// /// MDNode - a tuple of other values. -/// These contain a list of the Constants that represent the metadata. The -/// operand list is always empty, query the element list instead. -/// -/// This class will attempt to keep track of values as they are modified. When -/// a value is replaced the element will be replaced with it, and when the -/// value is deleted the element is set to a null pointer. In order to preserve -/// structural equivalence while the elements mutate, the MDNode may call -/// replaceAllUsesWith on itself. Because of this, users of MDNode must use a -/// WeakVH or CallbackVH to hold the node pointer if there is a chance that one -/// of the elements held by the node may change. +/// These contain a list of the values that represent the metadata. /// -class MDNode : public Constant, public FoldingSetNode { +class MDNode : public MetadataBase, public FoldingSetNode { MDNode(const MDNode &); // DO NOT IMPLEMENT friend class LLVMContextImpl; - friend class ElementVH; - struct ElementVH : public CallbackVH { - MDNode *OwningNode; - - ElementVH(Value *V, MDNode *Parent) - : CallbackVH(V), OwningNode(Parent) {} - - ~ElementVH() {} - - /// deleted - Set this entry in the MDNode to 'null'. This will reallocate - /// the MDNode. - virtual void deleted() { - OwningNode->replaceElement(this->operator Value*(), 0); - } - - /// allUsesReplacedWith - Modify the MDNode by replacing this entry with - /// new_value. This will reallocate the MDNode. - virtual void allUsesReplacedWith(Value *new_value) { - OwningNode->replaceElement(this->operator Value*(), new_value); - } - }; - void replaceElement(Value *From, Value *To); - SmallVector Node; - typedef SmallVectorImpl::iterator elem_iterator; + SmallVector Node; + typedef SmallVectorImpl::iterator elem_iterator; protected: explicit MDNode(Value*const* Vals, unsigned NumVals); public: - typedef SmallVectorImpl::const_iterator const_elem_iterator; + typedef SmallVectorImpl::const_iterator const_elem_iterator; Value *getElement(unsigned i) const { return Node[i]; @@ -176,7 +145,6 @@ public: /// duplicates void Profile(FoldingSetNodeID &ID) const; - virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { llvm_unreachable("This should never be called because MDNodes have no ops"); } diff --git a/include/llvm/Value.h b/include/llvm/Value.h index dd01cabb8cd..40b1dab2957 100644 --- a/include/llvm/Value.h +++ b/include/llvm/Value.h @@ -227,7 +227,7 @@ public: // Markers: ConstantFirstVal = FunctionVal, - ConstantLastVal = MDNodeVal + ConstantLastVal = ConstantPointerNullVal }; /// getValueID - Return an ID for the concrete type of this object. This is diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 18f83231dad..097b385c3ea 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -379,20 +379,20 @@ bool LLParser::ParseMDString(MetadataBase *&MDS) { // MDNode: // ::= '!' MDNodeNumber -bool LLParser::ParseMDNode(Constant *&Node) { +bool LLParser::ParseMDNode(MetadataBase *&Node) { // !{ ..., !42, ... } unsigned MID = 0; if (ParseUInt32(MID)) return true; // Check existing MDNode. - std::map::iterator I = MetadataCache.find(MID); + std::map::iterator I = MetadataCache.find(MID); if (I != MetadataCache.end()) { Node = I->second; return false; } // Check known forward references. - std::map >::iterator + std::map >::iterator FI = ForwardRefMDNodes.find(MID); if (FI != ForwardRefMDNodes.end()) { Node = FI->second.first; @@ -427,15 +427,24 @@ bool LLParser::ParseStandaloneMetadata() { if (ParseType(Ty, TyLoc)) return true; - Constant *Init = 0; - if (ParseGlobalValue(Ty, Init)) - return true; + if (Lex.getKind() != lltok::Metadata) + return TokError("Expected metadata here"); + + Lex.Lex(); + if (Lex.getKind() != lltok::lbrace) + return TokError("Expected '{' here"); + SmallVector Elts; + if (ParseMDNodeVector(Elts) + || ParseToken(lltok::rbrace, "exected end of metadata node")) + return true; + + MDNode *Init = Context.getMDNode(Elts.data(), Elts.size()); MetadataCache[MetadataID] = Init; - std::map >::iterator + std::map >::iterator FI = ForwardRefMDNodes.find(MetadataID); if (FI != ForwardRefMDNodes.end()) { - Constant *FwdNode = FI->second.first; + MDNode *FwdNode = cast(FI->second.first); FwdNode->replaceAllUsesWith(Init); ForwardRefMDNodes.erase(FI); } @@ -1677,7 +1686,7 @@ bool LLParser::ParseValID(ValID &ID) { ID.Kind = ValID::t_LocalName; break; case lltok::Metadata: { // !{...} MDNode, !"foo" MDString - ID.Kind = ValID::t_Constant; + ID.Kind = ValID::t_Metadata; Lex.Lex(); if (Lex.getKind() == lltok::lbrace) { SmallVector Elts; @@ -1685,13 +1694,13 @@ bool LLParser::ParseValID(ValID &ID) { ParseToken(lltok::rbrace, "expected end of metadata node")) return true; - ID.ConstantVal = Context.getMDNode(Elts.data(), Elts.size()); + ID.MetadataVal = Context.getMDNode(Elts.data(), Elts.size()); return false; } // Standalone metadata reference // !{ ..., !42, ... } - if (!ParseMDNode(ID.ConstantVal)) + if (!ParseMDNode(ID.MetadataVal)) return false; // MDString: @@ -3462,7 +3471,7 @@ bool LLParser::ParseMDNodeVector(SmallVectorImpl &Elts) { if (ParseType(Ty)) return true; if (Lex.getKind() == lltok::Metadata) { Lex.Lex(); - Constant *Node = 0; + MetadataBase *Node = 0; if (!ParseMDNode(Node)) V = Node; else { diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 1a0b6ccde9f..c77ef9d6d11 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -46,8 +46,8 @@ namespace llvm { std::map > ForwardRefTypeIDs; std::vector NumberedTypes; /// MetadataCache - This map keeps track of parsed metadata constants. - std::map MetadataCache; - std::map > ForwardRefMDNodes; + std::map MetadataCache; + std::map > ForwardRefMDNodes; struct UpRefRecord { /// Loc - This is the location of the upref. @@ -149,7 +149,7 @@ namespace llvm { bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); bool ParseStandaloneMetadata(); bool ParseMDString(MetadataBase *&S); - bool ParseMDNode(Constant *&N); + bool ParseMDNode(MetadataBase *&N); // Type Parsing. bool ParseType(PATypeHolder &Result, bool AllowVoid = false); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index d22d467476d..8393cd42163 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -734,6 +734,23 @@ bool BitcodeReader::ParseMetadata() { switch (Stream.ReadRecord(Code, Record)) { default: // Default behavior: ignore. break; + case bitc::METADATA_NODE: { + if (Record.empty() || Record.size() % 2 == 1) + return Error("Invalid METADATA_NODE record"); + + unsigned Size = Record.size(); + SmallVector Elts; + for (unsigned i = 0; i != Size; i += 2) { + const Type *Ty = getTypeByID(Record[i], false); + if (Ty != Type::VoidTy) + Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty)); + else + Elts.push_back(NULL); + } + Value *V = Context.getMDNode(&Elts[0], Elts.size()); + ValueList.AssignValue(V, NextValueNo++); + break; + } case bitc::METADATA_STRING: { unsigned MDStringLength = Record.size(); SmallString<8> String; @@ -1078,22 +1095,6 @@ bool BitcodeReader::ParseConstants() { AsmStr, ConstrStr, HasSideEffects); break; } - case bitc::CST_CODE_MDNODE: { - if (Record.empty() || Record.size() % 2 == 1) - return Error("Invalid CST_MDNODE record"); - - unsigned Size = Record.size(); - SmallVector Elts; - for (unsigned i = 0; i != Size; i += 2) { - const Type *Ty = getTypeByID(Record[i], false); - if (Ty != Type::VoidTy) - Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty)); - else - Elts.push_back(NULL); - } - V = Context.getMDNode(&Elts[0], Elts.size()); - break; - } } ValueList.AssignValue(V, NextCstNo); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 719ea8a02aa..7d745ffd50d 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -478,8 +478,26 @@ static uint64_t GetOptimizationFlags(const Value *V) { const ValueEnumerator::ValueList &Vals = VE.getValues(); bool StartedMetadataBlock = false; unsigned MDSAbbrev = 0; + SmallVector Record; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - if (const MDString *MDS = dyn_cast(Vals[i].first)) { + + if (const MDNode *N = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { + if (N->getElement(i)) { + Record.push_back(VE.getTypeID(N->getElement(i)->getType())); + Record.push_back(VE.getValueID(N->getElement(i))); + } else { + Record.push_back(VE.getTypeID(Type::VoidTy)); + Record.push_back(0); + } + } + Stream.EmitRecord(bitc::METADATA_NODE, Record, 0); + Record.clear(); + } else if (const MDString *MDS = dyn_cast(Vals[i].first)) { if (!StartedMetadataBlock) { Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); @@ -492,15 +510,14 @@ static uint64_t GetOptimizationFlags(const Value *V) { StartedMetadataBlock = true; } - SmallVector StrVals; - StrVals.clear(); // Code: [strchar x N] const char *StrBegin = MDS->begin(); for (unsigned i = 0, e = MDS->size(); i != e; ++i) - StrVals.push_back(StrBegin[i]); + Record.push_back(StrBegin[i]); // Emit the finished record. - Stream.EmitRecord(bitc::METADATA_STRING, StrVals, MDSAbbrev); + Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev); + Record.clear(); } } @@ -555,7 +572,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, const Type *LastTy = 0; for (unsigned i = FirstVal; i != LastVal; ++i) { const Value *V = Vals[i].first; - if (isa(V)) + if (isa(V) || isa(V)) continue; // If we need to switch types, do so now. if (V->getType() != LastTy) { @@ -736,17 +753,6 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(CE->getPredicate()); break; } - } else if (const MDNode *N = dyn_cast(C)) { - Code = bitc::CST_CODE_MDNODE; - for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) { - if (N->getElement(i)) { - Record.push_back(VE.getTypeID(N->getElement(i)->getType())); - Record.push_back(VE.getValueID(N->getElement(i))); - } else { - Record.push_back(VE.getTypeID(Type::VoidTy)); - Record.push_back(0); - } - } } else { llvm_unreachable("Unknown constant!"); } @@ -1342,12 +1348,12 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) { // descriptors for global variables, and function prototype info. WriteModuleInfo(M, VE, Stream); + // Emit constants. + WriteModuleConstants(VE, Stream); + // Emit metadata. WriteModuleMetadata(VE, Stream); - // Emit constants. - WriteModuleConstants(VE, Stream); - // Emit function bodies. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isDeclaration()) diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 4a6eea49430..38784ec4a0f 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -204,21 +204,23 @@ void ValueEnumerator::EnumerateValue(const Value *V) { Values.push_back(std::make_pair(V, 1U)); ValueMap[V] = Values.size(); return; - } else if (const MDNode *N = dyn_cast(C)) { - for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end(); - I != E; ++I) { - if (*I) - EnumerateValue(*I); - else - EnumerateType(Type::VoidTy); - } + } + } - Values.push_back(std::make_pair(V, 1U)); - ValueMap[V] = Values.size(); - return; + if (const MDNode *N = dyn_cast(V)) { + Values.push_back(std::make_pair(V, 1U)); + ValueMap[V] = Values.size(); + ValueID = Values.size(); + for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end(); + I != E; ++I) { + if (*I) + EnumerateValue(*I); + else + EnumerateType(Type::VoidTy); } + return; } - + // Add the value. Values.push_back(std::make_pair(V, 1U)); ValueID = Values.size(); @@ -265,7 +267,7 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) { EnumerateOperandType(Elem); } } - } else if (isa(V)) + } else if (isa(V) || isa(V)) EnumerateValue(V); } diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index d9d8cc834d5..ae55d5ba515 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1132,6 +1132,11 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, return; } + if (const MDNode *N = dyn_cast(V)) { + Out << '!' << Machine->getMetadataSlot(N); + return; + } + if (const MDString *MDS = dyn_cast(V)) { Out << "!\""; PrintEscapedString(MDS->begin(), MDS->size(), Out); diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index db405927ff5..065ebcd5dc9 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1327,9 +1327,9 @@ void UndefValue::destroyConstant() { // MDNode::MDNode(Value*const* Vals, unsigned NumVals) - : Constant(Type::MetadataTy, MDNodeVal, 0, 0) { + : MetadataBase(Type::MetadataTy, Value::MDNodeVal) { for (unsigned i = 0; i != NumVals; ++i) - Node.push_back(ElementVH(Vals[i], this)); + Node.push_back(WeakVH(Vals[i])); } void MDNode::Profile(FoldingSetNodeID &ID) const { @@ -1337,11 +1337,6 @@ void MDNode::Profile(FoldingSetNodeID &ID) const { ID.AddPointer(*I); } -void MDNode::destroyConstant() { - getType()->getContext().erase(this); - destroyConstantImpl(); -} - //---- ConstantExpr::get() implementations... // @@ -2315,6 +2310,4 @@ void MDNode::replaceElement(Value *From, Value *To) { assert(Replacement != this && "I didn't contain From!"); uncheckedReplaceAllUsesWith(Replacement); - - destroyConstant(); } diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 5441f1ab88b..8ad46a040c5 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -420,7 +420,7 @@ MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) { N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); if (!N) { // InsertPoint will have been set by the FindNodeOrInsertPos call. - N = new(0) MDNode(Vals, NumVals); + N = new MDNode(Vals, NumVals); MDNodeSet.InsertNode(N, InsertPoint); } } diff --git a/test/Feature/embeddedmetadata.ll b/test/Feature/embeddedmetadata.ll index 65e0d4c2a4b..6912cd972f2 100644 --- a/test/Feature/embeddedmetadata.ll +++ b/test/Feature/embeddedmetadata.ll @@ -11,3 +11,10 @@ define void @foo() { ret void } +;; Test forward reference +declare i8 @llvm.f2(metadata %a) +define void @f2() { + %x = call i8 @llvm.f2(metadata !2) + ret void +} +!2 = metadata !{i32 420} diff --git a/test/Feature/mdnode2.ll b/test/Feature/mdnode2.ll deleted file mode 100644 index 23e6318a8dd..00000000000 --- a/test/Feature/mdnode2.ll +++ /dev/null @@ -1,8 +0,0 @@ -; Test standalone metadata -; RUN: llvm-as < %s | llvm-dis > %t.ll -; RUN: grep "metadata !{i32 21, i32 22}" %t.ll -; RUN: grep "metadata !{i32 23, i32 24}" %t.ll - -!0 = metadata !{i32 21, i32 22} -!1 = metadata !{i32 23, i32 24} -@llvm.blah = constant metadata !{i32 1000, i16 200, metadata !1, metadata !0} diff --git a/test/Feature/mdnode3.ll b/test/Feature/mdnode3.ll deleted file mode 100644 index ecb280c8a05..00000000000 --- a/test/Feature/mdnode3.ll +++ /dev/null @@ -1,3 +0,0 @@ -; RUN: llvm-as < %s | llvm-dis | llvm-as -f -o /dev/null -!0 = metadata !{i32 21, i32 22} -@llvm.blah = constant metadata !{i32 1000, i16 200, metadata !0, metadata !0} diff --git a/test/Feature/mdnode4.ll b/test/Feature/mdnode4.ll deleted file mode 100644 index cf4c6e92d3d..00000000000 --- a/test/Feature/mdnode4.ll +++ /dev/null @@ -1,6 +0,0 @@ -; Test forward MDNode reference -; RUN: llvm-as < %s | llvm-dis -f -o /dev/null - -@llvm.blah = constant metadata !{metadata !1} -!1 = metadata !{i32 23, i32 24} - diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 4eaa60c7570..412cf334fd3 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -195,7 +195,6 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, case bitc::CST_CODE_CE_CMP: return "CE_CMP"; case bitc::CST_CODE_INLINEASM: return "INLINEASM"; case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX"; - case bitc::CST_CODE_MDNODE: return "MDNODE"; } case bitc::FUNCTION_BLOCK_ID: switch (CodeID) { @@ -248,6 +247,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, switch(CodeID) { default:return 0; case bitc::METADATA_STRING: return "MDSTRING"; + case bitc::METADATA_NODE: return "MDNODE"; } } } diff --git a/unittests/VMCore/MetadataTest.cpp b/unittests/VMCore/MetadataTest.cpp index c92bb139b43..732719ec5c4 100644 --- a/unittests/VMCore/MetadataTest.cpp +++ b/unittests/VMCore/MetadataTest.cpp @@ -101,25 +101,6 @@ TEST(MDNodeTest, Simple) { oss2.str().c_str()); } -TEST(MDNodeTest, RAUW) { - Constant *C = getGlobalContext().getConstantInt(Type::Int32Ty, 1); - Instruction *I = new BitCastInst(C, Type::Int32Ty); - - Value *const V1 = I; - MDNode *n1 = getGlobalContext().getMDNode(&V1, 1); - WeakVH wn1 = n1; - - Value *const V2 = C; - MDNode *n2 = getGlobalContext().getMDNode(&V2, 1); - WeakVH wn2 = n2; - - EXPECT_NE(wn1, wn2); - - I->replaceAllUsesWith(C); - - EXPECT_EQ(wn1, wn2); -} - TEST(MDNodeTest, Delete) { Constant *C = getGlobalContext().getConstantInt(Type::Int32Ty, 1); Instruction *I = new BitCastInst(C, Type::Int32Ty); -- 2.34.1