-//===-- Metadata.cpp - Implement Metadata classes -------------------------===//
+//===- Metadata.cpp - Implement Metadata classes --------------------------===//
//
// The LLVM Compiler Infrastructure
//
#include "llvm/IR/Metadata.h"
#include "LLVMContextImpl.h"
+#include "MetadataImpl.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/ConstantRange.h"
+#include "llvm/IR/DebugInfoMetadata.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"
Metadata *MD) {
MD = canonicalizeMetadataForValue(Context, MD);
auto &Store = Context.pImpl->MetadataAsValues;
- auto I = Store.find(MD);
- return I == Store.end() ? nullptr : I->second;
+ return Store.lookup(MD);
}
void MetadataAsValue::handleChangedMetadata(Metadata *MD) {
}
void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
- assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Expected non-temp node");
+ assert(!(MD && isa<MDNode>(MD) && cast<MDNode>(MD)->isTemporary()) &&
+ "Expected non-temp node");
if (UseMap.empty())
return;
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 MDNodes that point at this.
+ auto *OwnerMD = dyn_cast<MDNode>(Owner.get<Metadata *>());
if (!OwnerMD)
continue;
if (OwnerMD->isResolved())
continue;
- OwnerMD->decrementUnresolvedOperands();
- if (!OwnerMD->hasUnresolvedOperands())
- OwnerMD->resolve();
+ OwnerMD->decrementUnresolvedOperandCount();
}
}
if (!Entry) {
assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) &&
"Expected constant or function-local value");
- assert(!V->NameAndIsUsedByMD.getInt() &&
+ assert(!V->IsUsedByMD &&
"Expected this to be the only metadata use");
- V->NameAndIsUsedByMD.setInt(true);
+ V->IsUsedByMD = 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;
auto &Store = Context.pImpl->ValuesAsMetadata;
auto I = Store.find(From);
if (I == Store.end()) {
- assert(!From->NameAndIsUsedByMD.getInt() &&
+ assert(!From->IsUsedByMD &&
"Expected From not to be used by metadata");
return;
}
// Remove old entry from the map.
- assert(From->NameAndIsUsedByMD.getInt() &&
+ assert(From->IsUsedByMD &&
"Expected From to be used by metadata");
- From->NameAndIsUsedByMD.setInt(false);
+ From->IsUsedByMD = false;
ValueAsMetadata *MD = I->second;
assert(MD && "Expected valid metadata");
assert(MD->getValue() == From && "Expected valid mapping");
}
// Update MD in place (and update the map entry).
- assert(!To->NameAndIsUsedByMD.getInt() &&
+ assert(!To->IsUsedByMD &&
"Expected this to be the only metadata use");
- To->NameAndIsUsedByMD.setInt(true);
+ To->IsUsedByMD = true;
MD->V = To;
Entry = MD;
}
// MDNode implementation.
//
+// Assert that the MDNode types will not be unaligned by the objects
+// prepended to them.
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ static_assert( \
+ llvm::AlignOf<uint64_t>::Alignment >= llvm::AlignOf<CLASS>::Alignment, \
+ "Alignment is insufficient after objects prepended to " #CLASS);
+#include "llvm/IR/Metadata.def"
+
void *MDNode::operator new(size_t Size, unsigned NumOps) {
- void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand));
+ size_t OpSize = NumOps * sizeof(MDOperand);
+ // uint64_t is the most aligned type we need support (ensured by static_assert
+ // above)
+ OpSize = RoundUpToAlignment(OpSize, llvm::alignOf<uint64_t>());
+ void *Ptr = reinterpret_cast<char *>(::operator new(OpSize + Size)) + OpSize;
MDOperand *O = static_cast<MDOperand *>(Ptr);
- for (MDOperand *E = O + NumOps; O != E; ++O)
- (void)new (O) MDOperand;
- return O;
+ for (MDOperand *E = O - NumOps; O != E; --O)
+ (void)new (O - 1) MDOperand;
+ return Ptr;
}
void MDNode::operator delete(void *Mem) {
MDNode *N = static_cast<MDNode *>(Mem);
+ size_t OpSize = N->NumOperands * sizeof(MDOperand);
+ OpSize = RoundUpToAlignment(OpSize, llvm::alignOf<uint64_t>());
+
MDOperand *O = static_cast<MDOperand *>(Mem);
for (MDOperand *E = O - N->NumOperands; O != E; --O)
(O - 1)->~MDOperand();
- ::operator delete(O);
+ ::operator delete(reinterpret_cast<char *>(Mem) - OpSize);
}
-MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
- : Metadata(ID), Context(Context), NumOperands(MDs.size()),
- MDNodeSubclassData(0) {
- for (unsigned I = 0, E = MDs.size(); I != E; ++I)
- setOperand(I, MDs[I]);
+MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
+ ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2)
+ : Metadata(ID, Storage), NumOperands(Ops1.size() + Ops2.size()),
+ NumUnresolved(0), Context(Context) {
+ unsigned Op = 0;
+ for (Metadata *MD : Ops1)
+ setOperand(Op++, MD);
+ for (Metadata *MD : Ops2)
+ setOperand(Op++, MD);
+
+ if (isDistinct())
+ return;
+
+ if (isUniqued())
+ // Check whether any operands are unresolved, requiring re-uniquing. If
+ // not, don't support RAUW.
+ if (!countUnresolvedOperands())
+ return;
+
+ this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(Context));
}
-bool MDNode::isResolved() const {
- if (isa<MDNodeFwdDecl>(this))
- return false;
- return cast<GenericMDNode>(this)->isResolved();
+TempMDNode MDNode::clone() const {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid MDNode subclass");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ return cast<CLASS>(this)->cloneImpl();
+#include "llvm/IR/Metadata.def"
+ }
}
static bool isOperandUnresolved(Metadata *Op) {
return false;
}
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
- : MDNode(C, GenericMDNodeKind, Vals) {
- // Check whether any operands are unresolved, requiring re-uniquing.
- for (const auto &Op : operands())
- if (isOperandUnresolved(Op))
- incrementUnresolvedOperands();
+unsigned MDNode::countUnresolvedOperands() {
+ assert(NumUnresolved == 0 && "Expected unresolved ops to be uncounted");
+ NumUnresolved = std::count_if(op_begin(), op_end(), isOperandUnresolved);
+ return NumUnresolved;
+}
- if (hasUnresolvedOperands())
- ReplaceableUses.reset(new ReplaceableMetadataImpl);
+void MDNode::makeUniqued() {
+ assert(isTemporary() && "Expected this to be temporary");
+ assert(!isResolved() && "Expected this to be unresolved");
+
+ // Enable uniquing callbacks.
+ for (auto &Op : mutable_operands())
+ Op.reset(Op.get(), this);
+
+ // Make this 'uniqued'.
+ Storage = Uniqued;
+ if (!countUnresolvedOperands())
+ resolve();
+
+ assert(isUniqued() && "Expected this to be uniqued");
}
-GenericMDNode::~GenericMDNode() {
- LLVMContextImpl *pImpl = getContext().pImpl;
- if (isStoredDistinctInContext())
- pImpl->NonUniquedMDNodes.erase(this);
- else
- pImpl->MDNodeSet.erase(this);
- dropAllReferences();
+void MDNode::makeDistinct() {
+ assert(isTemporary() && "Expected this to be temporary");
+ assert(!isResolved() && "Expected this to be unresolved");
+
+ // Pretend to be uniqued, resolve the node, and then store in distinct table.
+ Storage = Uniqued;
+ resolve();
+ storeDistinctInContext();
+
+ assert(isDistinct() && "Expected this to be distinct");
+ assert(isResolved() && "Expected this to be resolved");
}
-void GenericMDNode::resolve() {
+void MDNode::resolve() {
+ assert(isUniqued() && "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);
- SubclassData32 = 0;
+ auto Uses = Context.takeReplaceableUses();
+ NumUnresolved = 0;
assert(isResolved() && "Expected this to be resolved");
// Drop RAUW support.
Uses->resolveAllUses();
}
-void GenericMDNode::resolveCycles() {
+void MDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+ assert(NumUnresolved != 0 && "Expected unresolved operands");
+
+ // Check if an operand was resolved.
+ if (!isOperandUnresolved(Old)) {
+ if (isOperandUnresolved(New))
+ // An operand was un-resolved!
+ ++NumUnresolved;
+ } else if (!isOperandUnresolved(New))
+ decrementUnresolvedOperandCount();
+}
+
+void MDNode::decrementUnresolvedOperandCount() {
+ if (!--NumUnresolved)
+ // Last unresolved operand has just been resolved.
+ resolve();
+}
+
+void MDNode::resolveCycles() {
if (isResolved())
return;
// Resolve all operands.
for (const auto &Op : operands()) {
- if (!Op)
+ auto *N = dyn_cast_or_null<MDNode>(Op);
+ if (!N)
continue;
- assert(!isa<MDNodeFwdDecl>(Op) &&
+
+ assert(!N->isTemporary() &&
"Expected all forward declarations to be resolved");
- if (auto *N = dyn_cast<GenericMDNode>(Op))
- if (!N->isResolved())
- N->resolveCycles();
+ if (!N->isResolved())
+ N->resolveCycles();
}
}
+static bool hasSelfReference(MDNode *N) {
+ for (Metadata *MD : N->operands())
+ if (MD == N)
+ return true;
+ return false;
+}
+
+MDNode *MDNode::replaceWithPermanentImpl() {
+ if (hasSelfReference(this))
+ return replaceWithDistinctImpl();
+ return replaceWithUniquedImpl();
+}
+
+MDNode *MDNode::replaceWithUniquedImpl() {
+ // Try to uniquify in place.
+ MDNode *UniquedNode = uniquify();
+
+ if (UniquedNode == this) {
+ makeUniqued();
+ return this;
+ }
+
+ // Collision, so RAUW instead.
+ replaceAllUsesWith(UniquedNode);
+ deleteAsSubclass();
+ return UniquedNode;
+}
+
+MDNode *MDNode::replaceWithDistinctImpl() {
+ makeDistinct();
+ return this;
+}
+
+void MDTuple::recalculateHash() {
+ setHash(MDTupleInfo::KeyTy::calculateHash(this));
+}
+
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();
- }
-}
-
-namespace llvm {
-/// \brief Make MDOperand transparent for hashing.
-///
-/// This overload of an implementation detail of the hashing library makes
-/// MDOperand hash to the same value as a \a Metadata pointer.
-///
-/// Note that overloading \a hash_value() as follows:
-///
-/// \code
-/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
-/// \endcode
-///
-/// does not cause MDOperand to be transparent. In particular, a bare pointer
-/// doesn't get hashed before it's combined, whereas \a MDOperand would.
-static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
+ if (!isResolved()) {
+ Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
+ (void)Context.takeReplaceableUses();
+ }
}
-void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
+void MDNode::handleChangedOperand(void *Ref, Metadata *New) {
unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
assert(Op < getNumOperands() && "Expected valid operand");
- if (isStoredDistinctInContext()) {
- assert(isResolved() && "Expected distinct node to be resolved");
-
+ if (!isUniqued()) {
// This node is not uniqued. Just set the operand and be done with it.
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 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) {
- storeDistinctInContext();
- setHash(0);
+ // Drop uniquing for self-reference cycles.
+ if (New == this) {
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()) {
- // 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();
- }
-
+ 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.
- setHash(0);
+ // 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 MDNode::deleteAsSubclass() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ delete cast<CLASS>(this); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
- GenericMDNodeInfo::KeyTy Key(MDs);
- auto I = Store.find_as(Key);
- if (I != Store.end())
- return *I;
- if (!Insert)
- return nullptr;
+template <class T, class InfoT>
+static T *uniquifyImpl(T *N, DenseSet<T *, InfoT> &Store) {
+ if (T *U = getUniqued(Store, N))
+ return U;
- // Coallocate space for the node and Operands together, then placement new.
- GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
- N->setHash(Key.Hash);
Store.insert(N);
return N;
}
-MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
- ArrayRef<Metadata *> MDs) {
- MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
- LeakDetector::addGarbageObject(N);
- return N;
+template <class NodeTy> struct MDNode::HasCachedHash {
+ typedef char Yes[1];
+ typedef char No[2];
+ template <class U, U Val> struct SFINAE {};
+
+ template <class U>
+ static Yes &check(SFINAE<void (U::*)(unsigned), &U::setHash> *);
+ template <class U> static No &check(...);
+
+ static const bool value = sizeof(check<NodeTy>(nullptr)) == sizeof(Yes);
+};
+
+MDNode *MDNode::uniquify() {
+ assert(!hasSelfReference(this) && "Cannot uniquify a self-referencing node");
+
+ // Try to insert into uniquing store.
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: { \
+ CLASS *SubclassThis = cast<CLASS>(this); \
+ std::integral_constant<bool, HasCachedHash<CLASS>::value> \
+ ShouldRecalculateHash; \
+ dispatchRecalculateHash(SubclassThis, ShouldRecalculateHash); \
+ return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s); \
+ }
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+void MDNode::eraseFromStore() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ getContext().pImpl->CLASS##s.erase(cast<CLASS>(this)); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ StorageType Storage, bool ShouldCreate) {
+ unsigned Hash = 0;
+ if (Storage == Uniqued) {
+ MDTupleInfo::KeyTy Key(MDs);
+ if (auto *N = getUniqued(Context.pImpl->MDTuples, Key))
+ return N;
+ if (!ShouldCreate)
+ return nullptr;
+ Hash = Key.getHash();
+ } else {
+ assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
+ }
+
+ return storeImpl(new (MDs.size()) MDTuple(Context, Storage, Hash, MDs),
+ Storage, Context.pImpl->MDTuples);
}
void MDNode::deleteTemporary(MDNode *N) {
- assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
- LeakDetector::removeGarbageObject(N);
- delete cast<MDNodeFwdDecl>(N);
+ assert(N->isTemporary() && "Expected temporary node");
+ N->replaceAllUsesWith(nullptr);
+ N->deleteAsSubclass();
}
void MDNode::storeDistinctInContext() {
- assert(!IsDistinctInContext && "Expected newly distinct metadata");
- IsDistinctInContext = true;
- auto *G = cast<GenericMDNode>(this);
- G->setHash(0);
- getContext().pImpl->NonUniquedMDNodes.insert(G);
+ assert(isResolved() && "Expected resolved nodes");
+ Storage = Distinct;
+
+ // Reset the hash.
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case CLASS##Kind: { \
+ std::integral_constant<bool, HasCachedHash<CLASS>::value> ShouldResetHash; \
+ dispatchResetHash(cast<CLASS>(this), ShouldResetHash); \
+ break; \
+ }
+#include "llvm/IR/Metadata.def"
+ }
+
+ getContext().pImpl->DistinctMDNodes.insert(this);
}
-// 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 (!isUniqued()) {
+ setOperand(I, New);
return;
}
- assert(isa<MDNodeFwdDecl>(this) && "Expected an MDNode");
- setOperand(I, New);
+ handleChangedOperand(mutable_begin() + I, New);
}
void MDNode::setOperand(unsigned I, Metadata *New) {
assert(I < NumOperands);
- if (isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this))
- // No need for a callback, this isn't uniqued.
- mutable_begin()[I].reset(New, nullptr);
- else
- mutable_begin()[I].reset(New, this);
+ mutable_begin()[I].reset(New, isUniqued() ? this : nullptr);
}
/// \brief Get a node, or a self-reference that looks like it.
if (!B)
return A;
- SmallVector<Metadata *, 4> MDs(A->getNumOperands() + B->getNumOperands());
-
- unsigned j = 0;
- for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i)
- MDs[j++] = A->getOperand(i);
- for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i)
- MDs[j++] = B->getOperand(i);
+ SmallVector<Metadata *, 4> MDs;
+ MDs.reserve(A->getNumOperands() + B->getNumOperands());
+ MDs.append(A->op_begin(), A->op_end());
+ MDs.append(B->op_begin(), B->op_end());
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?
return nullptr;
SmallVector<Metadata *, 4> MDs;
- for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) {
- Metadata *MD = A->getOperand(i);
- for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j)
- if (MD == B->getOperand(j)) {
- MDs.push_back(MD);
- break;
- }
- }
+ for (Metadata *MD : A->operands())
+ if (std::find(B->op_begin(), B->op_end(), MD) != B->op_end())
+ MDs.push_back(MD);
+
+ // FIXME: This preserves long-standing behaviour, but is it really the right
+ // behaviour? Or was that an unintended side-effect of node uniquing?
+ return getOrSelfReference(A->getContext(), MDs);
+}
+
+MDNode *MDNode::getMostGenericAliasScope(MDNode *A, MDNode *B) {
+ if (!A || !B)
+ return nullptr;
+
+ SmallVector<Metadata *, 4> MDs(B->op_begin(), B->op_end());
+ for (Metadata *MD : A->operands())
+ if (std::find(B->op_begin(), B->op_end(), MD) == B->op_end())
+ MDs.push_back(MD);
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?
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);
}
//===----------------------------------------------------------------------===//
// Instruction Metadata method implementations.
//
+void MDAttachmentMap::set(unsigned ID, MDNode &MD) {
+ for (auto &I : Attachments)
+ if (I.first == ID) {
+ I.second.reset(&MD);
+ return;
+ }
+ Attachments.emplace_back(std::piecewise_construct, std::make_tuple(ID),
+ std::make_tuple(&MD));
+}
+
+void MDAttachmentMap::erase(unsigned ID) {
+ if (empty())
+ return;
+
+ // Common case is one/last value.
+ if (Attachments.back().first == ID) {
+ Attachments.pop_back();
+ return;
+ }
+
+ for (auto I = Attachments.begin(), E = std::prev(Attachments.end()); I != E;
+ ++I)
+ if (I->first == ID) {
+ *I = std::move(Attachments.back());
+ Attachments.pop_back();
+ return;
+ }
+}
+
+MDNode *MDAttachmentMap::lookup(unsigned ID) const {
+ for (const auto &I : Attachments)
+ if (I.first == ID)
+ return I.second;
+ return nullptr;
+}
+
+void MDAttachmentMap::getAll(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
+ Result.append(Attachments.begin(), Attachments.end());
+
+ // Sort the resulting array so it is stable.
+ if (Result.size() > 1)
+ array_pod_sort(Result.begin(), Result.end());
+}
void Instruction::setMetadata(StringRef Kind, MDNode *Node) {
if (!Node && !hasMetadata())
if (!hasMetadataHashEntry())
return; // Nothing to remove!
- DenseMap<const Instruction *, LLVMContextImpl::MDMapTy> &MetadataStore =
- getContext().pImpl->MetadataStore;
+ auto &InstructionMetadata = getContext().pImpl->InstructionMetadata;
if (KnownSet.empty()) {
// Just drop our entry at the store.
- MetadataStore.erase(this);
+ InstructionMetadata.erase(this);
setHasMetadataHashEntry(false);
return;
}
- LLVMContextImpl::MDMapTy &Info = MetadataStore[this];
- unsigned I;
- unsigned E;
- // Walk the array and drop any metadata we don't know.
- for (I = 0, E = Info.size(); I != E;) {
- if (KnownSet.count(Info[I].first)) {
- ++I;
- continue;
- }
-
- Info[I] = std::move(Info.back());
- Info.pop_back();
- --E;
- }
- assert(E == Info.size());
+ auto &Info = InstructionMetadata[this];
+ Info.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) {
+ return !KnownSet.count(I.first);
+ });
- if (E == 0) {
+ if (Info.empty()) {
// Drop our entry at the store.
- MetadataStore.erase(this);
+ InstructionMetadata.erase(this);
setHasMetadataHashEntry(false);
}
}
// Handle 'dbg' as a special case since it is not stored in the hash table.
if (KindID == LLVMContext::MD_dbg) {
- DbgLoc = DebugLoc::getFromDILocation(Node);
+ DbgLoc = DebugLoc(Node);
return;
}
// Handle the case when we're adding/updating metadata on an instruction.
if (Node) {
- LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
+ auto &Info = getContext().pImpl->InstructionMetadata[this];
assert(!Info.empty() == hasMetadataHashEntry() &&
"HasMetadata bit is wonked");
- if (Info.empty()) {
+ if (Info.empty())
setHasMetadataHashEntry(true);
- } else {
- // Handle replacement of an existing value.
- for (auto &P : Info)
- if (P.first == KindID) {
- P.second.reset(Node);
- return;
- }
- }
-
- // No replacement, just add it to the list.
- Info.emplace_back(std::piecewise_construct, std::make_tuple(KindID),
- std::make_tuple(Node));
+ Info.set(KindID, *Node);
return;
}
// Otherwise, we're removing metadata from an instruction.
assert((hasMetadataHashEntry() ==
- (getContext().pImpl->MetadataStore.count(this) > 0)) &&
+ (getContext().pImpl->InstructionMetadata.count(this) > 0)) &&
"HasMetadata bit out of date!");
if (!hasMetadataHashEntry())
return; // Nothing to remove!
- LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
+ auto &Info = getContext().pImpl->InstructionMetadata[this];
- // Common case is removing the only entry.
- if (Info.size() == 1 && Info[0].first == KindID) {
- getContext().pImpl->MetadataStore.erase(this);
- setHasMetadataHashEntry(false);
+ // Handle removal of an existing value.
+ Info.erase(KindID);
+
+ if (!Info.empty())
return;
- }
- // Handle removal of an existing value.
- for (unsigned i = 0, e = Info.size(); i != e; ++i)
- if (Info[i].first == KindID) {
- Info[i] = std::move(Info.back());
- Info.pop_back();
- assert(!Info.empty() && "Removing last entry should be handled above");
- return;
- }
- // Otherwise, removing an entry that doesn't exist on the instruction.
+ getContext().pImpl->InstructionMetadata.erase(this);
+ setHasMetadataHashEntry(false);
}
void Instruction::setAAMetadata(const AAMDNodes &N) {
if (KindID == LLVMContext::MD_dbg)
return DbgLoc.getAsMDNode();
- if (!hasMetadataHashEntry()) return nullptr;
-
- LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
+ if (!hasMetadataHashEntry())
+ return nullptr;
+ auto &Info = getContext().pImpl->InstructionMetadata[this];
assert(!Info.empty() && "bit out of sync with hash table");
- for (const auto &I : Info)
- if (I.first == KindID)
- return I.second;
- return nullptr;
+ return Info.lookup(KindID);
}
void Instruction::getAllMetadataImpl(
Result.clear();
// Handle 'dbg' as a special case since it is not stored in the hash table.
- if (!DbgLoc.isUnknown()) {
+ if (DbgLoc) {
Result.push_back(
std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode()));
if (!hasMetadataHashEntry()) return;
}
-
+
assert(hasMetadataHashEntry() &&
- getContext().pImpl->MetadataStore.count(this) &&
+ getContext().pImpl->InstructionMetadata.count(this) &&
"Shouldn't have called this");
- const LLVMContextImpl::MDMapTy &Info =
- getContext().pImpl->MetadataStore.find(this)->second;
+ const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second;
assert(!Info.empty() && "Shouldn't have called this");
-
- Result.reserve(Result.size() + Info.size());
- for (auto &I : Info)
- Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get())));
-
- // Sort the resulting array so it is stable.
- if (Result.size() > 1)
- array_pod_sort(Result.begin(), Result.end());
+ Info.getAll(Result);
}
void Instruction::getAllMetadataOtherThanDebugLocImpl(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
Result.clear();
assert(hasMetadataHashEntry() &&
- getContext().pImpl->MetadataStore.count(this) &&
+ getContext().pImpl->InstructionMetadata.count(this) &&
"Shouldn't have called this");
- const LLVMContextImpl::MDMapTy &Info =
- getContext().pImpl->MetadataStore.find(this)->second;
+ const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second;
assert(!Info.empty() && "Shouldn't have called this");
- Result.reserve(Result.size() + Info.size());
- for (auto &I : Info)
- Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get())));
-
- // Sort the resulting array so it is stable.
- if (Result.size() > 1)
- array_pod_sort(Result.begin(), Result.end());
+ Info.getAll(Result);
}
/// clearMetadataHashEntries - Clear all hashtable-based metadata from
/// this instruction.
void Instruction::clearMetadataHashEntries() {
assert(hasMetadataHashEntry() && "Caller should check");
- getContext().pImpl->MetadataStore.erase(this);
+ getContext().pImpl->InstructionMetadata.erase(this);
setHasMetadataHashEntry(false);
}
+MDNode *Function::getMetadata(unsigned KindID) const {
+ if (!hasMetadata())
+ return nullptr;
+ return getContext().pImpl->FunctionMetadata[this].lookup(KindID);
+}
+
+MDNode *Function::getMetadata(StringRef Kind) const {
+ if (!hasMetadata())
+ return nullptr;
+ return getMetadata(getContext().getMDKindID(Kind));
+}
+
+void Function::setMetadata(unsigned KindID, MDNode *MD) {
+ if (MD) {
+ if (!hasMetadata())
+ setHasMetadataHashEntry(true);
+
+ getContext().pImpl->FunctionMetadata[this].set(KindID, *MD);
+ return;
+ }
+
+ // Nothing to unset.
+ if (!hasMetadata())
+ return;
+
+ auto &Store = getContext().pImpl->FunctionMetadata[this];
+ Store.erase(KindID);
+ if (Store.empty())
+ clearMetadata();
+}
+
+void Function::setMetadata(StringRef Kind, MDNode *MD) {
+ if (!MD && !hasMetadata())
+ return;
+ setMetadata(getContext().getMDKindID(Kind), MD);
+}
+
+void Function::getAllMetadata(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
+ MDs.clear();
+
+ if (!hasMetadata())
+ return;
+
+ getContext().pImpl->FunctionMetadata[this].getAll(MDs);
+}
+
+void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
+ if (!hasMetadata())
+ return;
+ if (KnownIDs.empty()) {
+ clearMetadata();
+ return;
+ }
+
+ SmallSet<unsigned, 5> KnownSet;
+ KnownSet.insert(KnownIDs.begin(), KnownIDs.end());
+
+ auto &Store = getContext().pImpl->FunctionMetadata[this];
+ assert(!Store.empty());
+
+ Store.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) {
+ return !KnownSet.count(I.first);
+ });
+
+ if (Store.empty())
+ clearMetadata();
+}
+
+void Function::clearMetadata() {
+ if (!hasMetadata())
+ return;
+ getContext().pImpl->FunctionMetadata.erase(this);
+ setHasMetadataHashEntry(false);
+}