return L.second.second < R.second.second;
});
for (const auto &Pair : Uses) {
+ // Check that this Ref hasn't disappeared after RAUW (when updating a
+ // previous Ref).
+ if (!UseMap.count(Pair.first))
+ continue;
+
OwnerTy Owner = Pair.second.first;
if (!Owner) {
// Update unowned tracking references directly.
if (Owner.is<MetadataAsValue *>())
continue;
- // Resolve GenericMDNodes that point at this.
- auto *OwnerMD = dyn_cast<GenericMDNode>(Owner.get<Metadata *>());
+ // Resolve UniquableMDNodes that point at this.
+ auto *OwnerMD = dyn_cast<UniquableMDNode>(Owner.get<Metadata *>());
if (!OwnerMD)
continue;
if (OwnerMD->isResolved())
continue;
- if (!--OwnerMD->SubclassData32)
- OwnerMD->resolve();
+ OwnerMD->decrementUnresolvedOperandCount();
}
}
::operator delete(O);
}
-MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
- : Metadata(ID), Context(Context), NumOperands(MDs.size()),
+MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
+ ArrayRef<Metadata *> MDs)
+ : Metadata(ID, Storage), Context(Context), NumOperands(MDs.size()),
MDNodeSubclassData(0) {
for (unsigned I = 0, E = MDs.size(); I != E; ++I)
setOperand(I, MDs[I]);
-}
-bool MDNode::isResolved() const {
- if (isa<MDNodeFwdDecl>(this))
- return false;
- return cast<GenericMDNode>(this)->isResolved();
+ if (Storage == Temporary)
+ this->Context.makeReplaceable(
+ make_unique<ReplaceableMetadataImpl>(Context));
}
static bool isOperandUnresolved(Metadata *Op) {
return false;
}
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
- bool AllowRAUW)
- : MDNode(C, GenericMDNodeKind, Vals) {
- if (!AllowRAUW)
+UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID,
+ StorageType Storage, ArrayRef<Metadata *> Vals)
+ : MDNode(C, ID, Storage, Vals) {
+ if (Storage != Uniqued)
return;
// Check whether any operands are unresolved, requiring re-uniquing.
if (!NumUnresolved)
return;
- ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(C));
SubclassData32 = NumUnresolved;
}
-GenericMDNode::~GenericMDNode() {
- LLVMContextImpl *pImpl = getContext().pImpl;
- if (isStoredDistinctInContext())
- pImpl->NonUniquedMDNodes.erase(this);
- else
- pImpl->MDNodeSet.erase(this);
- dropAllReferences();
-}
-
-void GenericMDNode::resolve() {
+void UniquableMDNode::resolve() {
+ assert(Storage == Uniqued && "Expected this to be uniqued");
assert(!isResolved() && "Expected this to be unresolved");
// Move the map, so that this immediately looks resolved.
- auto Uses = std::move(ReplaceableUses);
+ auto Uses = Context.takeReplaceableUses();
SubclassData32 = 0;
assert(isResolved() && "Expected this to be resolved");
Uses->resolveAllUses();
}
-void GenericMDNode::resolveCycles() {
+void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+ assert(SubclassData32 != 0 && "Expected unresolved operands");
+
+ // Check if an operand was resolved.
+ if (!isOperandUnresolved(Old)) {
+ if (isOperandUnresolved(New))
+ // An operand was un-resolved!
+ ++SubclassData32;
+ } else if (!isOperandUnresolved(New))
+ decrementUnresolvedOperandCount();
+}
+
+void UniquableMDNode::decrementUnresolvedOperandCount() {
+ if (!--SubclassData32)
+ // Last unresolved operand has just been resolved.
+ resolve();
+}
+
+void UniquableMDNode::resolveCycles() {
if (isResolved())
return;
continue;
assert(!isa<MDNodeFwdDecl>(Op) &&
"Expected all forward declarations to be resolved");
- if (auto *N = dyn_cast<GenericMDNode>(Op))
+ if (auto *N = dyn_cast<UniquableMDNode>(Op))
if (!N->isResolved())
N->resolveCycles();
}
}
+void MDTuple::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);
- if (auto *G = dyn_cast<GenericMDNode>(this))
- if (!G->isResolved()) {
- G->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
- G->ReplaceableUses.reset();
+ if (auto *N = dyn_cast<UniquableMDNode>(this))
+ if (!N->isResolved()) {
+ N->Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
+ (void)N->Context.takeReplaceableUses();
}
}
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
}
-void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
+void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
assert(Op < getNumOperands() && "Expected valid operand");
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);
+ // This node is uniqued.
+ eraseFromStore();
Metadata *Old = getOperand(Op);
setOperand(Op, New);
// Drop uniquing for self-reference cycles.
if (New == this) {
- storeDistinctInContext();
if (!isResolved())
resolve();
+ storeDistinctInContext();
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.
- GenericMDNodeInfo::KeyTy Key(this);
- auto I = Store.find_as(Key);
- if (I == Store.end()) {
- Store.insert(this);
-
- if (!isResolved()) {
- 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)) {
- if (!--SubclassData32)
- resolve();
- }
- } else {
- // Operands shouldn't become unresolved.
- assert(isOperandUnresolved(New) && "Operand just became unresolved");
- }
- }
-
+ auto *Uniqued = uniquify();
+ if (Uniqued == this) {
+ if (!isResolved())
+ resolveAfterOperandChange(Old, New);
return;
}
// Collision.
if (!isResolved()) {
// Still unresolved, so RAUW.
- InRAUW = true;
- ReplaceableUses->replaceAllUsesWith(*I);
- delete this;
+ //
+ // 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);
+ Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
+ deleteAsSubclass();
return;
}
- // Store in non-uniqued form if this node has already been resolved.
+ // Store in non-uniqued form if RAUW isn't possible.
storeDistinctInContext();
}
-MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
- bool Insert) {
- auto &Store = Context.pImpl->MDNodeSet;
+void UniquableMDNode::deleteAsSubclass() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ delete cast<CLASS>(this); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+UniquableMDNode *UniquableMDNode::uniquify() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ return cast<CLASS>(this)->uniquifyImpl();
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+void UniquableMDNode::eraseFromStore() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ cast<CLASS>(this)->eraseFromStoreImpl(); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ bool ShouldCreate) {
+ MDTupleInfo::KeyTy Key(MDs);
- GenericMDNodeInfo::KeyTy Key(MDs);
+ auto &Store = Context.pImpl->MDTuples;
auto I = Store.find_as(Key);
if (I != Store.end())
return *I;
- if (!Insert)
+ if (!ShouldCreate)
return nullptr;
// Coallocate space for the node and Operands together, then placement new.
- auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
+ auto *N = new (MDs.size()) MDTuple(Context, Uniqued, MDs);
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);
+MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ auto *N = new (MDs.size()) MDTuple(Context, Distinct, MDs);
N->storeDistinctInContext();
return N;
}
-MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
- ArrayRef<Metadata *> MDs) {
- MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
+MDTuple *MDTuple::uniquifyImpl() {
+ recalculateHash();
+ MDTupleInfo::KeyTy Key(this);
+
+ auto &Store = getContext().pImpl->MDTuples;
+ auto I = Store.find_as(Key);
+ if (I == Store.end()) {
+ Store.insert(this);
+ return this;
+ }
+ return *I;
+}
+
+void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
+
+MDLocation::MDLocation(LLVMContext &C, StorageType Storage, unsigned Line,
+ unsigned Column, ArrayRef<Metadata *> MDs)
+ : UniquableMDNode(C, MDLocationKind, Storage, MDs) {
+ assert((MDs.size() == 1 || MDs.size() == 2) &&
+ "Expected a scope and optional inlined-at");
+
+ // Set line and column.
+ assert(Line < (1u << 24) && "Expected 24-bit line");
+ assert(Column < (1u << 16) && "Expected 16-bit column");
+
+ MDNodeSubclassData = Line;
+ SubclassData16 = Column;
+}
+
+MDLocation *MDLocation::constructHelper(LLVMContext &Context,
+ StorageType Storage, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt) {
+ SmallVector<Metadata *, 2> Ops;
+ Ops.push_back(Scope);
+ if (InlinedAt)
+ Ops.push_back(InlinedAt);
+ return new (Ops.size()) MDLocation(Context, Storage, Line, Column, Ops);
+}
+
+static void adjustLine(unsigned &Line) {
+ // Set to unknown on overflow. Still use 24 bits for now.
+ if (Line >= (1u << 24))
+ Line = 0;
+}
+
+static void adjustColumn(unsigned &Column) {
+ // Set to unknown on overflow. We only have 16 bits to play with here.
+ if (Column >= (1u << 16))
+ Column = 0;
+}
+
+MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool ShouldCreate) {
+ // Fixup line/column.
+ adjustLine(Line);
+ adjustColumn(Column);
+
+ MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt);
+
+ auto &Store = Context.pImpl->MDLocations;
+ auto I = Store.find_as(Key);
+ if (I != Store.end())
+ return *I;
+ if (!ShouldCreate)
+ return nullptr;
+
+ auto *N = constructHelper(Context, Uniqued, Line, Column, Scope, InlinedAt);
+ Store.insert(N);
return N;
}
-void MDNode::deleteTemporary(MDNode *N) {
- assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
- delete cast<MDNodeFwdDecl>(N);
+MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt) {
+ // Fixup line/column.
+ adjustLine(Line);
+ adjustColumn(Column);
+
+ auto *N = constructHelper(Context, Distinct, Line, Column, Scope, InlinedAt);
+ N->storeDistinctInContext();
+ return N;
}
-void MDNode::storeDistinctInContext() {
- assert(!IsDistinctInContext && "Expected newly distinct metadata");
- IsDistinctInContext = true;
- auto *G = cast<GenericMDNode>(this);
- G->setHash(0);
- getContext().pImpl->NonUniquedMDNodes.insert(G);
+MDLocation *MDLocation::uniquifyImpl() {
+ MDLocationInfo::KeyTy Key(this);
+
+ auto &Store = getContext().pImpl->MDLocations;
+ auto I = Store.find_as(Key);
+ if (I == Store.end()) {
+ Store.insert(this);
+ return this;
+ }
+ return *I;
+}
+
+void MDLocation::eraseFromStoreImpl() {
+ getContext().pImpl->MDLocations.erase(this);
+}
+
+MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
+ return MDNodeFwdDecl::get(Context, MDs);
+}
+
+void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
+
+void UniquableMDNode::storeDistinctInContext() {
+ assert(isResolved() && "Expected resolved nodes");
+ Storage = Distinct;
+ if (auto *T = dyn_cast<MDTuple>(this))
+ T->setHash(0);
+ getContext().pImpl->DistinctMDNodes.insert(this);
}
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
if (getOperand(I) == New)
return;
- if (isDistinct()) {
+ if (!isUniqued()) {
setOperand(I, New);
return;
}
- cast<GenericMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
+ cast<UniquableMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
}
void MDNode::setOperand(unsigned I, Metadata *New) {