#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"
}
void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) {
- bool WasInserted = UseMap.insert(std::make_pair(Ref, Owner)).second;
+ bool WasInserted =
+ UseMap.insert(std::make_pair(Ref, std::make_pair(Owner, NextIndex)))
+ .second;
(void)WasInserted;
assert(WasInserted && "Expected to add a reference");
+
+ ++NextIndex;
+ assert(NextIndex != 0 && "Unexpected overflow");
}
void ReplaceableMetadataImpl::dropRef(void *Ref) {
const Metadata &MD) {
auto I = UseMap.find(Ref);
assert(I != UseMap.end() && "Expected to move a reference");
- OwnerTy Owner = I->second;
+ auto OwnerAndIndex = I->second;
UseMap.erase(I);
- addRef(New, Owner);
+ bool WasInserted = UseMap.insert(std::make_pair(New, OwnerAndIndex)).second;
+ (void)WasInserted;
+ assert(WasInserted && "Expected to add a reference");
// Check that the references are direct if there's no owner.
(void)MD;
- assert((Owner || *static_cast<Metadata **>(Ref) == &MD) &&
+ assert((OwnerAndIndex.first || *static_cast<Metadata **>(Ref) == &MD) &&
"Reference without owner must be direct");
- assert((Owner || *static_cast<Metadata **>(New) == &MD) &&
+ assert((OwnerAndIndex.first || *static_cast<Metadata **>(New) == &MD) &&
"Reference without owner must be direct");
}
return;
// Copy out uses since UseMap will get touched below.
- SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+ typedef std::pair<void *, std::pair<OwnerTy, uint64_t>> UseTy;
+ SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
+ std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
+ return L.second.second < R.second.second;
+ });
for (const auto &Pair : Uses) {
- if (!Pair.second) {
+ OwnerTy Owner = Pair.second.first;
+ if (!Owner) {
// 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;
}
// Check for MetadataAsValue.
- if (Pair.second.is<MetadataAsValue *>()) {
- Pair.second.get<MetadataAsValue *>()->handleChangedMetadata(MD);
+ if (Owner.is<MetadataAsValue *>()) {
+ Owner.get<MetadataAsValue *>()->handleChangedMetadata(MD);
continue;
}
// There's a Metadata owner -- dispatch.
- Metadata *Owner = Pair.second.get<Metadata *>();
- switch (Owner->getMetadataID()) {
+ Metadata *OwnerMD = Owner.get<Metadata *>();
+ switch (OwnerMD->getMetadataID()) {
#define HANDLE_METADATA_LEAF(CLASS) \
case Metadata::CLASS##Kind: \
- cast<CLASS>(Owner)->handleChangedOperand(Pair.first, MD); \
+ cast<CLASS>(OwnerMD)->handleChangedOperand(Pair.first, MD); \
continue;
#include "llvm/IR/Metadata.def"
default:
}
// Copy out uses since UseMap could get touched below.
- SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+ typedef std::pair<void *, std::pair<OwnerTy, uint64_t>> UseTy;
+ SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
+ std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
+ return L.second.second < R.second.second;
+ });
UseMap.clear();
for (const auto &Pair : Uses) {
- if (!Pair.second)
+ auto Owner = Pair.second.first;
+ if (!Owner)
continue;
- if (Pair.second.is<MetadataAsValue *>())
+ if (Owner.is<MetadataAsValue *>())
continue;
// Resolve GenericMDNodes that point at this.
- auto *Owner = dyn_cast<GenericMDNode>(Pair.second.get<Metadata *>());
- if (!Owner)
+ auto *OwnerMD = dyn_cast<GenericMDNode>(Owner.get<Metadata *>());
+ if (!OwnerMD)
continue;
- if (Owner->isResolved())
+ if (OwnerMD->isResolved())
continue;
- Owner->decrementUnresolvedOperands();
- if (!Owner->hasUnresolvedOperands())
- Owner->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;
if (I != Store.end())
return &I->second;
- auto *Entry = StringMapEntry<MDString>::Create(Str, Store.getAllocator());
+ auto *Entry =
+ StringMapEntry<MDString>::Create(Str, Store.getAllocator(), MDString());
bool WasInserted = Store.insert(Entry);
(void)WasInserted;
assert(WasInserted && "Expected entry to be inserted");
void *MDNode::operator new(size_t Size, unsigned NumOps) {
void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand));
- MDOperand *First = new (Ptr) MDOperand[NumOps];
- return First + NumOps;
+ MDOperand *O = static_cast<MDOperand *>(Ptr);
+ for (MDOperand *E = O + NumOps; O != E; ++O)
+ (void)new (O) MDOperand;
+ return O;
}
void MDNode::operator delete(void *Mem) {
MDNode *N = static_cast<MDNode *>(Mem);
- MDOperand *Last = static_cast<MDOperand *>(Mem);
- ::operator delete(Last - N->NumOperands);
+ MDOperand *O = static_cast<MDOperand *>(Mem);
+ for (MDOperand *E = O - N->NumOperands; O != E; --O)
+ (O - 1)->~MDOperand();
+ ::operator delete(O);
}
MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
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 the last unresolved operand has just been resolved; if so,
+ // resolve this as well.
+ if (isOperandUnresolved(Old)) {
+ if (!isOperandUnresolved(New))
+ decrementUnresolvedOperandCount();
+ } else {
+ // Operands shouldn't become unresolved.
+ assert(isOperandUnresolved(New) && "Operand just became unresolved");
+ }
+}
+
+void GenericMDNode::decrementUnresolvedOperandCount() {
+ if (!--SubclassData32)
+ 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);
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.
+ //
+ // 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);
}
-