diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 625ca8a8443..da226273a01 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -272,6 +272,10 @@ namespace llvm { StringRef getFilename() const { return getCompileUnit().getFilename();} StringRef getDirectory() const { return getCompileUnit().getDirectory();} + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. + void replaceAllUsesWith(DIDescriptor &D); + /// print - print type. void print(raw_ostream &OS) const; @@ -314,10 +318,6 @@ namespace llvm { /// dump - print derived type to dbgs() with a newline. void dump() const; - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(DIDescriptor &D); }; /// DICompositeType - This descriptor holds a type that can refer to multiple @@ -654,6 +654,9 @@ namespace llvm { unsigned RunTimeLang = 0, MDNode *ContainingType = 0); + /// CreateTemporaryType - Create a temporary forward-declared type. + DIType CreateTemporaryType(DIDescriptor Context); + /// CreateArtificialType - Create a new DIType with "artificial" flag set. DIType CreateArtificialType(DIType Ty); diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index ef9646e9774..f773817e829 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -128,6 +128,16 @@ public: static MDNode *getIfExists(LLVMContext &Context, Value *const *Vals, unsigned NumVals); + + /// getTemporary - Return a temporary MDNode, for use in constructing + /// cyclic MDNode structures. A temporary MDNode is not uniqued, + /// may be RAUW'd, and must be manually deleted with deleteTemporary. + static MDNode *getTemporary(LLVMContext &Context, Value *const *Vals, + unsigned NumVals); + + /// deleteTemporary - Deallocate a node created by getTemporary. The + /// node must not have any users. + static void deleteTemporary(MDNode *N); /// getOperand - Return specified operand. Value *getOperand(unsigned i) const; diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 1b9008cca72..065a00ae609 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" @@ -260,7 +261,7 @@ unsigned DIArray::getNumElements() const { /// replaceAllUsesWith - Replace all uses of debug info referenced by /// this descriptor. -void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { +void DIType::replaceAllUsesWith(DIDescriptor &D) { if (!DbgNode) return; @@ -274,6 +275,7 @@ void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) { const MDNode *DN = D; const Value *V = cast_or_null(DN); Node->replaceAllUsesWith(const_cast(V)); + MDNode::deleteTemporary(Node); } } @@ -934,6 +936,18 @@ DICompositeType DIFactory::CreateCompositeType(unsigned Tag, } +/// CreateTemporaryType - Create a temporary forward-declared type. +DIType DIFactory::CreateTemporaryType(DIDescriptor Context) { + // Give the temporary MDNode a tag. It doesn't matter what tag we + // use here as long as DIType accepts it. + Value *Elts[] = { + GetTagConstant(DW_TAG_base_type) + }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); + return DIType(Node); +} + + /// CreateCompositeType - Create a composite type like array, struct, etc. DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index c55a16520f9..dc545fff2da 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -517,11 +517,7 @@ bool LLParser::ParseMDNodeID(MDNode *&Result) { if (Result) return false; // Otherwise, create MDNode forward reference. - - // FIXME: This is not unique enough! - std::string FwdRefName = "llvm.mdnode.fwdref." + utostr(MID); - Value *V = MDString::get(Context, FwdRefName); - MDNode *FwdNode = MDNode::get(Context, &V, 1); + MDNode *FwdNode = MDNode::getTemporary(Context, 0, 0); ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc()); if (NumberedMetadata.size() <= MID) @@ -585,7 +581,9 @@ bool LLParser::ParseStandaloneMetadata() { std::map, LocTy> >::iterator FI = ForwardRefMDNodes.find(MetadataID); if (FI != ForwardRefMDNodes.end()) { - FI->second.first->replaceAllUsesWith(Init); + MDNode *Temp = FI->second.first; + Temp->replaceAllUsesWith(Init); + MDNode::deleteTemporary(Temp); ForwardRefMDNodes.erase(FI); assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 8f999a68758..2010468824c 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -333,9 +333,9 @@ void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) { } // If there was a forward reference to this value, replace it. - Value *PrevVal = OldV; + MDNode *PrevVal = cast(OldV); OldV->replaceAllUsesWith(V); - delete PrevVal; + MDNode::deleteTemporary(PrevVal); // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new // value for Idx. MDValuePtrs[Idx] = V; @@ -351,7 +351,7 @@ Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { } // Create and return a placeholder, which will later be RAUW'd. - Value *V = new Argument(Type::getMetadataTy(Context)); + Value *V = MDNode::getTemporary(Context, 0, 0); MDValuePtrs[Idx] = V; return V; } diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index 442b5c51b65..236ddaa15b2 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/SmallString.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/Support/LeakDetector.h" #include "llvm/Support/ValueHandle.h" using namespace llvm; @@ -244,6 +245,28 @@ MDNode *MDNode::getIfExists(LLVMContext &Context, Value *const *Vals, return getMDNode(Context, Vals, NumVals, FL_Unknown, false); } +MDNode *MDNode::getTemporary(LLVMContext &Context, Value *const *Vals, + unsigned NumVals) { + MDNode *N = (MDNode *)malloc(sizeof(MDNode)+NumVals*sizeof(MDNodeOperand)); + N = new (N) MDNode(Context, Vals, NumVals, FL_No); + N->setValueSubclassData(N->getSubclassDataFromValue() | + NotUniquedBit); + LeakDetector::addGarbageObject(N); + return N; +} + +void MDNode::deleteTemporary(MDNode *N) { + assert(N->use_empty() && "Temporary MDNode has uses!"); + assert((N->getSubclassDataFromValue() & NotUniquedBit) && + "Temporary MDNode does not have NotUniquedBit set!"); + assert((N->getSubclassDataFromValue() & DestroyFlag) == 0 && + "Temporary MDNode does has DestroyFlag set!"); + N->setValueSubclassData(N->getSubclassDataFromValue() | + DestroyFlag); + LeakDetector::removeGarbageObject(N); + delete N; +} + /// getOperand - Return specified operand. Value *MDNode::getOperand(unsigned i) const { return *getOperandPtr(const_cast(this), i);