LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs,
unsigned Count) {
- return wrap(MDNode::getTemporary(*unwrap(C),
- ArrayRef<Metadata *>(unwrap(MDs), Count)));
+ return wrap(MDTuple::getTemporary(*unwrap(C),
+ ArrayRef<Metadata *>(unwrap(MDs), Count))
+ .release());
}
void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name,
}
};
+template <class T>
+struct TempMDNodeDeleter {
+ inline void operator()(T *Node) const;
+};
+
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ typedef std::unique_ptr<CLASS, TempMDNodeDeleter<CLASS>> Temp##CLASS;
+#include "llvm/IR/Metadata.def"
+
//===----------------------------------------------------------------------===//
/// \brief Tuple of metadata.
class MDNode : public Metadata {
ArrayRef<Metadata *> MDs);
static inline MDTuple *getDistinct(LLVMContext &Context,
ArrayRef<Metadata *> MDs);
- static inline MDTuple *getTemporary(LLVMContext &Context,
- ArrayRef<Metadata *> MDs);
+ static inline TempMDTuple getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
/// \brief Deallocate a node created by getTemporary.
///
/// 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 MDTuple *getTemporary(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
- return getImpl(Context, MDs, Temporary);
+ static TempMDTuple getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
+ return TempMDTuple(getImpl(Context, MDs, Temporary));
}
static bool classof(const Metadata *MD) {
MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return MDTuple::getDistinct(Context, MDs);
}
-MDTuple *MDNode::getTemporary(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+TempMDTuple MDNode::getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
return MDTuple::getTemporary(Context, MDs);
}
+template <class T>
+void TempMDNodeDeleter<T>::operator()(T *Node) const {
+ MDNode::deleteTemporary(Node);
+}
/// \brief Debug location.
///
Metadata *InlinedAt = nullptr) {
return getImpl(Context, Line, Column, Scope, InlinedAt, Distinct);
}
- static MDLocation *getTemporary(LLVMContext &Context, unsigned Line,
- unsigned Column, Metadata *Scope,
- Metadata *InlinedAt = nullptr) {
- return getImpl(Context, Line, Column, Scope, InlinedAt, Temporary);
+ static TempMDLocation getTemporary(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr) {
+ return TempMDLocation(
+ getImpl(Context, Line, Column, Scope, InlinedAt, Temporary));
}
unsigned getLine() const { return MDNodeSubclassData; }
}
// Otherwise, create MDNode forward reference.
- MDTuple *FwdNode = MDTuple::getTemporary(Context, None);
- ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc());
+ auto &FwdRef = ForwardRefMDNodes[MID];
+ FwdRef = std::make_pair(MDTuple::getTemporary(Context, None), Lex.getLoc());
if (NumberedMetadata.size() <= MID)
NumberedMetadata.resize(MID+1);
- NumberedMetadata[MID].reset(FwdNode);
- Result = FwdNode;
+ Result = FwdRef.first.get();
+ NumberedMetadata[MID].reset(Result);
return false;
}
// See if this was forward referenced, if so, handle it.
auto FI = ForwardRefMDNodes.find(MetadataID);
if (FI != ForwardRefMDNodes.end()) {
- MDTuple *Temp = FI->second.first;
- Temp->replaceAllUsesWith(Init);
- MDNode::deleteTemporary(Temp);
+ FI->second.first->replaceAllUsesWith(Init);
ForwardRefMDNodes.erase(FI);
assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work");
std::vector<std::pair<Type*, LocTy> > NumberedTypes;
std::vector<TrackingMDNodeRef> NumberedMetadata;
- std::map<unsigned, std::pair<MDTuple *, LocTy>> ForwardRefMDNodes;
+ std::map<unsigned, std::pair<TempMDTuple, LocTy>> ForwardRefMDNodes;
// Global Value reference information.
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
}
// If there was a forward reference to this value, replace it.
- MDTuple *PrevMD = cast<MDTuple>(OldMD.get());
+ TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
PrevMD->replaceAllUsesWith(MD);
- MDNode::deleteTemporary(PrevMD);
--NumFwdRefs;
}
// Create and return a placeholder, which will later be RAUW'd.
AnyFwdRefs = true;
++NumFwdRefs;
- Metadata *MD = MDNode::getTemporary(Context, None);
+ Metadata *MD = MDNode::getTemporary(Context, None).release();
MDValuePtrs[Idx].reset(MD);
return MD;
}
assert(!Filename.empty() &&
"Unable to create compile unit without filename");
Metadata *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)};
- TempEnumTypes = MDNode::getTemporary(VMContext, TElts);
+ TempEnumTypes = MDNode::getTemporary(VMContext, TElts).release();
- TempRetainTypes = MDNode::getTemporary(VMContext, TElts);
+ TempRetainTypes = MDNode::getTemporary(VMContext, TElts).release();
- TempSubprograms = MDNode::getTemporary(VMContext, TElts);
+ TempSubprograms = MDNode::getTemporary(VMContext, TElts).release();
- TempGVs = MDNode::getTemporary(VMContext, TElts);
+ TempGVs = MDNode::getTemporary(VMContext, TElts).release();
- TempImportedModules = MDNode::getTemporary(VMContext, TElts);
+ TempImportedModules = MDNode::getTemporary(VMContext, TElts).release();
Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit)
.concat(Lang)
nullptr, // TemplateParams
UniqueIdentifier.empty() ? nullptr
: MDString::get(VMContext, UniqueIdentifier)};
- DICompositeType RetTy(MDNode::getTemporary(VMContext, Elts));
+ DICompositeType RetTy(MDNode::getTemporary(VMContext, Elts).release());
assert(RetTy.isCompositeType() &&
"createReplaceableForwardDecl result should be a DIType");
if (!UniqueIdentifier.empty())
return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F,
LineNumber, Ty, isLocalToUnit, Val, Decl,
false, [&](ArrayRef<Metadata *> Elts) {
- return MDNode::getTemporary(VMContext, Elts);
+ return MDNode::getTemporary(VMContext, Elts).release();
});
}
return createFunctionHelper(VMContext, Context, Name, LinkageName, File,
LineNo, Ty, isLocalToUnit, isDefinition,
ScopeLine, Flags, isOptimized, Fn, TParams, Decl,
- MDNode::getTemporary(VMContext, None),
+ MDNode::getTemporary(VMContext, None).release(),
[&](ArrayRef<Metadata *> Elts) -> MDNode *{
MDNode *Node = MDNode::get(VMContext, Elts);
// Create a named metadata so that we
LineNo, Ty, isLocalToUnit, isDefinition,
ScopeLine, Flags, isOptimized, Fn, TParams, Decl,
nullptr, [&](ArrayRef<Metadata *> Elts) {
- return MDNode::getTemporary(VMContext, Elts);
+ return MDNode::getTemporary(VMContext, Elts).release();
});
}
MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) {
// To ensure uniqueness the root node is self-referential.
- MDNode *Dummy = MDNode::getTemporary(Context, None);
+ auto Dummy = MDNode::getTemporary(Context, None);
- SmallVector<Metadata *, 3> Args(1, Dummy);
+ SmallVector<Metadata *, 3> Args(1, Dummy.get());
if (Extra)
Args.push_back(Extra);
if (!Name.empty())
// !1 = metadata !{metadata !0} <- root
// Replace the dummy operand with the root node itself and delete the dummy.
Root->replaceOperandWith(0, Root);
- MDNode::deleteTemporary(Dummy);
+
// We now have
// !1 = metadata !{metadata !1} <- self-referential root
return Root;
// Now we have a complete set of all metadata in the chains used to specify
// the noalias scopes and the lists of those scopes.
- SmallVector<MDTuple *, 16> DummyNodes;
+ SmallVector<TempMDTuple, 16> DummyNodes;
DenseMap<const MDNode *, TrackingMDNodeRef> MDMap;
for (SetVector<const MDNode *>::iterator I = MD.begin(), IE = MD.end();
I != IE; ++I) {
- MDTuple *Dummy = MDTuple::getTemporary(CalledFunc->getContext(), None);
- DummyNodes.push_back(Dummy);
- MDMap[*I].reset(Dummy);
+ DummyNodes.push_back(MDTuple::getTemporary(CalledFunc->getContext(), None));
+ MDMap[*I].reset(DummyNodes.back().get());
}
// Create new metadata nodes to replace the dummy nodes, replacing old
NI->setMetadata(LLVMContext::MD_noalias, M);
}
}
-
- // Now that everything has been replaced, delete the dummy nodes.
- for (unsigned i = 0, ie = DummyNodes.size(); i != ie; ++i)
- MDNode::deleteTemporary(DummyNodes[i]);
}
/// AddAliasScopeMetadata - If the inlined function has noalias arguments, then
// In general we need a dummy node, since whether the operands are null can
// affect the size of the node.
- MDTuple *Dummy = MDTuple::getTemporary(Node->getContext(), None);
- mapToMetadata(VM, Node, Dummy);
+ auto Dummy = MDTuple::getTemporary(Node->getContext(), None);
+ mapToMetadata(VM, Node, Dummy.get());
Metadata *NewMD = cloneMDNode(Node, VM, Flags, TypeMapper, Materializer,
/* IsDistinct */ true);
Dummy->replaceAllUsesWith(NewMD);
- MDNode::deleteTemporary(Dummy);
return mapToMetadata(VM, Node, NewMD);
}
assert(Node->isUniqued() && "Expected uniqued node");
// Create a dummy node in case we have a metadata cycle.
- MDTuple *Dummy = MDTuple::getTemporary(Node->getContext(), None);
- mapToMetadata(VM, Node, Dummy);
+ auto Dummy = MDTuple::getTemporary(Node->getContext(), None);
+ mapToMetadata(VM, Node, Dummy.get());
// Check all operands to see if any need to be remapped.
if (!shouldRemapUniquedNode(Node, VM, Flags, TypeMapper, Materializer)) {
// Use an identity mapping.
mapToSelf(VM, Node);
- MDNode::deleteTemporary(Dummy);
return const_cast<Metadata *>(static_cast<const Metadata *>(Node));
}
Metadata *NewMD = cloneMDNode(Node, VM, Flags, TypeMapper, Materializer,
/* IsDistinct */ false);
Dummy->replaceAllUsesWith(NewMD);
- MDNode::deleteTemporary(Dummy);
return mapToMetadata(VM, Node, NewMD);
}
// !0 = !{!0}
// !1 = !{!0}
{
- MDNode *Temp = MDNode::getTemporary(Context, None);
- Metadata *Args[] = {Temp};
+ auto Temp = MDNode::getTemporary(Context, None);
+ Metadata *Args[] = {Temp.get()};
MDNode *Self = MDNode::get(Context, Args);
Self->replaceOperandWith(0, Self);
- MDNode::deleteTemporary(Temp);
ASSERT_EQ(Self, Self->getOperand(0));
// Self-references should be distinct, so MDNode::get() should grab a
// !0 = !{!0, !{}}
// !1 = !{!0, !{}}
{
- MDNode *Temp = MDNode::getTemporary(Context, None);
- Metadata *Args[] = {Temp, MDNode::get(Context, None)};
+ auto Temp = MDNode::getTemporary(Context, None);
+ Metadata *Args[] = {Temp.get(), MDNode::get(Context, None)};
MDNode *Self = MDNode::get(Context, Args);
Self->replaceOperandWith(0, Self);
- MDNode::deleteTemporary(Temp);
ASSERT_EQ(Self, Self->getOperand(0));
// Self-references should be distinct, so MDNode::get() should grab a
TEST_F(MDNodeTest, isUniqued) {
MDNode *U = MDTuple::get(Context, None);
MDNode *D = MDTuple::getDistinct(Context, None);
- MDNode *T = MDTuple::getTemporary(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
EXPECT_TRUE(U->isUniqued());
EXPECT_FALSE(D->isUniqued());
EXPECT_FALSE(T->isUniqued());
- MDNode::deleteTemporary(T);
}
TEST_F(MDNodeTest, isDistinct) {
MDNode *U = MDTuple::get(Context, None);
MDNode *D = MDTuple::getDistinct(Context, None);
- MDNode *T = MDTuple::getTemporary(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
EXPECT_FALSE(U->isDistinct());
EXPECT_TRUE(D->isDistinct());
EXPECT_FALSE(T->isDistinct());
- MDNode::deleteTemporary(T);
}
TEST_F(MDNodeTest, isTemporary) {
MDNode *U = MDTuple::get(Context, None);
MDNode *D = MDTuple::getDistinct(Context, None);
- MDNode *T = MDTuple::getTemporary(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
EXPECT_FALSE(U->isTemporary());
EXPECT_FALSE(D->isTemporary());
EXPECT_TRUE(T->isTemporary());
- MDNode::deleteTemporary(T);
}
TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {
// temporary !{}
- MDTuple *Temp = MDTuple::getTemporary(Context, None);
+ auto Temp = MDTuple::getTemporary(Context, None);
ASSERT_FALSE(Temp->isResolved());
// distinct !{temporary !{}}
- Metadata *Ops[] = {Temp};
+ Metadata *Ops[] = {Temp.get()};
MDNode *Distinct = MDNode::getDistinct(Context, Ops);
EXPECT_TRUE(Distinct->isResolved());
- EXPECT_EQ(Temp, Distinct->getOperand(0));
+ EXPECT_EQ(Temp.get(), Distinct->getOperand(0));
// temporary !{} => !{}
MDNode *Empty = MDNode::get(Context, None);
Temp->replaceAllUsesWith(Empty);
- MDNode::deleteTemporary(Temp);
EXPECT_EQ(Empty, Distinct->getOperand(0));
}
MDNode *N0 = MDNode::get(Context, None);
// !1 = !{!3, null}
- MDTuple *Temp3 = MDTuple::getTemporary(Context, None);
- Metadata *Ops1[] = {Temp3, nullptr};
+ auto Temp3 = MDTuple::getTemporary(Context, None);
+ Metadata *Ops1[] = {Temp3.get(), nullptr};
MDNode *N1 = MDNode::get(Context, Ops1);
// !2 = !{!3, !0}
- Metadata *Ops2[] = {Temp3, N0};
+ Metadata *Ops2[] = {Temp3.get(), N0};
MDNode *N2 = MDNode::get(Context, Ops2);
// !3 = !{!2}
Metadata *Ops3[] = {N2};
MDNode *N3 = MDNode::get(Context, Ops3);
Temp3->replaceAllUsesWith(N3);
- MDNode::deleteTemporary(Temp3);
// !4 = !{!1}
Metadata *Ops4[] = {N1};
// a global value that gets RAUW'ed.
//
// Use a temporary node to keep N from being resolved.
- MDTuple *Temp = MDTuple::getTemporary(Context, None);
- Metadata *Ops[] = {nullptr, Temp};
+ auto Temp = MDTuple::getTemporary(Context, None);
+ Metadata *Ops[] = {nullptr, Temp.get()};
MDNode *Empty = MDTuple::get(Context, ArrayRef<Metadata *>());
MDNode *N = MDTuple::get(Context, Ops);
EXPECT_EQ(Empty, N->getOperand(0));
// Check code for adding another unresolved operand.
- N->replaceOperandWith(0, Temp);
- EXPECT_EQ(Temp, N->getOperand(0));
+ N->replaceOperandWith(0, Temp.get());
+ EXPECT_EQ(Temp.get(), N->getOperand(0));
// Remove the references to Temp; required for teardown.
Temp->replaceAllUsesWith(nullptr);
- MDNode::deleteTemporary(Temp);
}
typedef MetadataTest MDLocationTest;
TEST_F(MDLocationTest, getTemporary) {
MDNode *N = MDNode::get(Context, None);
- MDLocation *L = MDLocation::getTemporary(Context, 2, 7, N);
+ auto L = MDLocation::getTemporary(Context, 2, 7, N);
EXPECT_TRUE(L->isTemporary());
EXPECT_FALSE(L->isResolved());
- MDNode::deleteTemporary(L);
}
typedef MetadataTest MetadataAsValueTest;
ConstantInt::get(getGlobalContext(), APInt(8, 0)));
// Create a temporary to prevent nodes from resolving.
- MDTuple *Temp = MDTuple::getTemporary(Context, None);
+ auto Temp = MDTuple::getTemporary(Context, None);
// When the first operand of N1 gets reset to nullptr, it'll collide with N2.
- Metadata *Ops1[] = {CI, CI, Temp};
- Metadata *Ops2[] = {nullptr, CI, Temp};
+ Metadata *Ops1[] = {CI, CI, Temp.get()};
+ Metadata *Ops2[] = {nullptr, CI, Temp.get()};
auto *N1 = MDTuple::get(Context, Ops1);
auto *N2 = MDTuple::get(Context, Ops2);
ValueAsMetadata::handleDeletion(CI->getValue());
EXPECT_EQ(nullptr, N2->getOperand(0));
EXPECT_EQ(nullptr, N2->getOperand(1));
- EXPECT_EQ(Temp, N2->getOperand(2));
+ EXPECT_EQ(Temp.get(), N2->getOperand(2));
// Clean up Temp for teardown.
Temp->replaceAllUsesWith(nullptr);
- MDNode::deleteTemporary(Temp);
}
typedef MetadataTest TrackingMDRefTest;