#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
// Update unowned tracking references directly.
Metadata *&Ref = *static_cast<Metadata **>(Pair.first);
Ref = MD;
- MetadataTracking::track(Ref);
+ if (MD)
+ MetadataTracking::track(Ref);
UseMap.erase(Pair.first);
continue;
}
continue;
if (OwnerMD->isResolved())
continue;
- OwnerMD->decrementUnresolvedOperands();
- if (!OwnerMD->hasUnresolvedOperands())
- OwnerMD->resolve();
+ OwnerMD->decrementUnresolvedOperandCount();
}
}
"Expected this to be the only metadata use");
V->NameAndIsUsedByMD.setInt(true);
if (auto *C = dyn_cast<Constant>(V))
- Entry = new ConstantAsMetadata(Context, C);
+ Entry = new ConstantAsMetadata(C);
else
- Entry = new LocalAsMetadata(Context, V);
+ Entry = new LocalAsMetadata(V);
}
return Entry;
return false;
}
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
+GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
+ bool AllowRAUW)
: MDNode(C, GenericMDNodeKind, Vals) {
+ if (!AllowRAUW)
+ return;
+
// Check whether any operands are unresolved, requiring re-uniquing.
+ unsigned NumUnresolved = 0;
for (const auto &Op : operands())
- if (isOperandUnresolved(Op))
- incrementUnresolvedOperands();
+ NumUnresolved += unsigned(isOperandUnresolved(Op));
+
+ if (!NumUnresolved)
+ return;
- if (hasUnresolvedOperands())
- ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ SubclassData32 = NumUnresolved;
}
GenericMDNode::~GenericMDNode() {
pImpl->NonUniquedMDNodes.erase(this);
else
pImpl->MDNodeSet.erase(this);
+ dropAllReferences();
}
void GenericMDNode::resolve() {
Uses->resolveAllUses();
}
+void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+ assert(SubclassData32 != 0 && "Expected unresolved operands");
+
+ // Check if an operand was resolved.
+ if (!isOperandUnresolved(Old))
+ assert(isOperandUnresolved(New) && "Operand just became unresolved");
+ else if (!isOperandUnresolved(New))
+ decrementUnresolvedOperandCount();
+}
+
+void GenericMDNode::decrementUnresolvedOperandCount() {
+ if (!--SubclassData32)
+ // Last unresolved operand has just been resolved.
+ resolve();
+}
+
void GenericMDNode::resolveCycles() {
if (isResolved())
return;
}
}
+void GenericMDNode::recalculateHash() {
+ setHash(hash_combine_range(op_begin(), op_end()));
+#ifndef NDEBUG
+ {
+ SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
+ unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
+ assert(getHash() == RawHash &&
+ "Expected hash of MDOperand to equal hash of Metadata*");
+ }
+#endif
+}
+
void MDNode::dropAllReferences() {
for (unsigned I = 0, E = NumOperands; I != E; ++I)
setOperand(I, nullptr);
setOperand(Op, New);
return;
}
- if (InRAUW) {
- // We just hit a recursion due to RAUW. Set the operand and move on, since
- // we're about to be deleted.
- //
- // FIXME: Can this cycle really happen?
- setOperand(Op, New);
- return;
- }
auto &Store = getContext().pImpl->MDNodeSet;
Store.erase(this);
Metadata *Old = getOperand(Op);
setOperand(Op, New);
- // Drop uniquing for self-reference cycles or if an operand drops to null.
- //
- // FIXME: Stop dropping uniquing when an operand drops to null. The original
- // motivation was to prevent madness during teardown of LLVMContextImpl, but
- // dropAllReferences() fixes that problem in a better way. (It's just here
- // now for better staging of semantic changes.)
- if (New == this || !New) {
+ // Drop uniquing for self-reference cycles.
+ if (New == this) {
storeDistinctInContext();
- setHash(0);
if (!isResolved())
resolve();
return;
}
- // Re-calculate the hash.
- setHash(hash_combine_range(op_begin(), op_end()));
-#ifndef NDEBUG
- {
- SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
- unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
- assert(getHash() == RawHash &&
- "Expected hash of MDOperand to equal hash of Metadata*");
- }
-#endif
-
// Re-unique the node.
+ recalculateHash();
GenericMDNodeInfo::KeyTy Key(this);
auto I = Store.find_as(Key);
if (I == Store.end()) {
Store.insert(this);
- if (!isResolved()) {
- // Check if the last unresolved operand has just been resolved; if so,
- // resolve this as well.
- if (isOperandUnresolved(Old))
- decrementUnresolvedOperands();
- if (isOperandUnresolved(New))
- incrementUnresolvedOperands();
- if (!hasUnresolvedOperands())
- resolve();
- }
+ if (!isResolved())
+ resolveAfterOperandChange(Old, New);
return;
}
// Collision.
if (!isResolved()) {
// Still unresolved, so RAUW.
- InRAUW = true;
+ //
+ // First, clear out all operands to prevent any recursion (similar to
+ // dropAllReferences(), but we still need the use-list).
+ for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
+ setOperand(O, nullptr);
ReplaceableUses->replaceAllUsesWith(*I);
delete this;
return;
}
- // Store in non-uniqued form if this node has already been resolved.
- setHash(0);
+ // Store in non-uniqued form if RAUW isn't possible.
storeDistinctInContext();
}
return nullptr;
// Coallocate space for the node and Operands together, then placement new.
- GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
+ auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
N->setHash(Key.Hash);
Store.insert(N);
return N;
}
+MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false);
+ N->storeDistinctInContext();
+ return N;
+}
+
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
ArrayRef<Metadata *> MDs) {
MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
- LeakDetector::addGarbageObject(N);
return N;
}
void MDNode::deleteTemporary(MDNode *N) {
assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
- LeakDetector::removeGarbageObject(N);
delete cast<MDNodeFwdDecl>(N);
}
getContext().pImpl->NonUniquedMDNodes.insert(G);
}
-// Replace value from this node's operand list.
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
if (getOperand(I) == New)
return;
- if (auto *N = dyn_cast<GenericMDNode>(this)) {
- N->handleChangedOperand(mutable_begin() + I, New);
+ if (isDistinct()) {
+ setOperand(I, New);
return;
}
- assert(isa<MDNodeFwdDecl>(this) && "Expected an MDNode");
- setOperand(I, New);
+ cast<GenericMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
}
void MDNode::setOperand(unsigned I, Metadata *New) {
MDNode *NamedMDNode::getOperand(unsigned i) const {
assert(i < getNumOperands() && "Invalid Operand number!");
auto *N = getNMDOps(Operands)[i].get();
- if (N && i > 10000)
- N->dump();
return cast_or_null<MDNode>(N);
}
void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); }
+void NamedMDNode::setOperand(unsigned I, MDNode *New) {
+ assert(I < getNumOperands() && "Invalid operand number");
+ getNMDOps(Operands)[I].reset(New);
+}
+
void NamedMDNode::eraseFromParent() {
getParent()->eraseNamedMetadata(this);
}
getContext().pImpl->MetadataStore.erase(this);
setHasMetadataHashEntry(false);
}
-