summaryrefslogtreecommitdiff
path: root/include/llvm/IR/Metadata.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/Metadata.h')
-rw-r--r--include/llvm/IR/Metadata.h152
1 files changed, 86 insertions, 66 deletions
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index df8ce354bb7fd..91f43d342d27f 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Constant.h"
@@ -51,7 +52,7 @@ protected:
enum StorageType { Uniqued, Distinct, Temporary };
/// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
- unsigned Storage : 2;
+ unsigned char Storage;
// TODO: expose remaining bits to subclasses.
unsigned short SubclassData16;
@@ -59,39 +60,14 @@ protected:
public:
enum MetadataKind {
- MDTupleKind,
- DILocationKind,
- GenericDINodeKind,
- DISubrangeKind,
- DIEnumeratorKind,
- DIBasicTypeKind,
- DIDerivedTypeKind,
- DICompositeTypeKind,
- DISubroutineTypeKind,
- DIFileKind,
- DICompileUnitKind,
- DISubprogramKind,
- DILexicalBlockKind,
- DILexicalBlockFileKind,
- DINamespaceKind,
- DIModuleKind,
- DITemplateTypeParameterKind,
- DITemplateValueParameterKind,
- DIGlobalVariableKind,
- DILocalVariableKind,
- DIExpressionKind,
- DIObjCPropertyKind,
- DIImportedEntityKind,
- ConstantAsMetadataKind,
- LocalAsMetadataKind,
- MDStringKind,
- DIMacroKind,
- DIMacroFileKind
+#define HANDLE_METADATA_LEAF(CLASS) CLASS##Kind,
+#include "llvm/IR/Metadata.def"
};
protected:
Metadata(unsigned ID, StorageType Storage)
: SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
+ static_assert(sizeof(*this) == 8, "Metdata fields poorly packed");
}
~Metadata() = default;
@@ -283,20 +259,14 @@ private:
LLVMContext &Context;
uint64_t NextIndex;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
- /// Flag that can be set to false if this metadata should not be
- /// RAUW'ed, e.g. if it is used as the key of a map.
- bool CanReplace;
public:
ReplaceableMetadataImpl(LLVMContext &Context)
- : Context(Context), NextIndex(0), CanReplace(true) {}
+ : Context(Context), NextIndex(0) {}
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
}
- /// Set the CanReplace flag to the given value.
- void setCanReplace(bool Replaceable) { CanReplace = Replaceable; }
-
LLVMContext &getContext() const { return Context; }
/// \brief Replace all uses of this with MD.
@@ -316,7 +286,19 @@ private:
void dropRef(void *Ref);
void moveRef(void *Ref, void *New, const Metadata &MD);
- static ReplaceableMetadataImpl *get(Metadata &MD);
+ /// Lazily construct RAUW support on MD.
+ ///
+ /// If this is an unresolved MDNode, RAUW support will be created on-demand.
+ /// ValueAsMetadata always has RAUW support.
+ static ReplaceableMetadataImpl *getOrCreate(Metadata &MD);
+
+ /// Get RAUW support on MD, if it exists.
+ static ReplaceableMetadataImpl *getIfExists(Metadata &MD);
+
+ /// Check whether this node will support RAUW.
+ ///
+ /// Returns \c true unless getOrCreate() would return null.
+ static bool isReplaceable(const Metadata &MD);
};
/// \brief Value wrapper in the Metadata hierarchy.
@@ -592,7 +574,6 @@ class MDString : public Metadata {
StringMapEntry<MDString> *Entry;
MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
- MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {}
public:
static MDString *get(LLVMContext &Context, StringRef Str);
@@ -767,6 +748,13 @@ public:
return nullptr;
}
+ /// Ensure that this has RAUW support, and then return it.
+ ReplaceableMetadataImpl *getOrCreateReplaceableUses() {
+ if (!hasReplaceableUses())
+ makeReplaceable(llvm::make_unique<ReplaceableMetadataImpl>(getContext()));
+ return getReplaceableUses();
+ }
+
/// \brief Assign RAUW support to this.
///
/// Make this replaceable, taking ownership of \c ReplaceableUses (which must
@@ -828,9 +816,9 @@ class MDNode : public Metadata {
unsigned NumOperands;
unsigned NumUnresolved;
-protected:
ContextAndReplaceableUses Context;
+protected:
void *operator new(size_t Size, unsigned NumOps);
void operator delete(void *Mem);
@@ -892,7 +880,7 @@ public:
/// As forward declarations are resolved, their containers should get
/// resolved automatically. However, if this (or one of its operands) is
/// involved in a cycle, \a resolveCycles() needs to be called explicitly.
- bool isResolved() const { return !Context.hasReplaceableUses(); }
+ bool isResolved() const { return !isTemporary() && !NumUnresolved; }
bool isUniqued() const { return Storage == Uniqued; }
bool isDistinct() const { return Storage == Distinct; }
@@ -903,33 +891,17 @@ public:
/// \pre \a isTemporary() must be \c true.
void replaceAllUsesWith(Metadata *MD) {
assert(isTemporary() && "Expected temporary node");
- assert(!isResolved() && "Expected RAUW support");
- Context.getReplaceableUses()->replaceAllUsesWith(MD);
- }
-
- /// Set the CanReplace flag to the given value.
- void setCanReplace(bool Replaceable) {
- Context.getReplaceableUses()->setCanReplace(Replaceable);
+ if (Context.hasReplaceableUses())
+ Context.getReplaceableUses()->replaceAllUsesWith(MD);
}
/// \brief Resolve cycles.
///
/// Once all forward declarations have been resolved, force cycles to be
- /// resolved. This interface is used when there are no more temporaries,
- /// and thus unresolved nodes are part of cycles and no longer need RAUW
- /// support.
+ /// resolved.
///
/// \pre No operands (or operands' operands, etc.) have \a isTemporary().
- void resolveCycles() { resolveRecursivelyImpl(/* AllowTemps */ false); }
-
- /// \brief Resolve cycles while ignoring temporaries.
- ///
- /// This drops RAUW support for any temporaries, which can no longer
- /// be uniqued.
- ///
- void resolveNonTemporaries() {
- resolveRecursivelyImpl(/* AllowTemps */ true);
- }
+ void resolveCycles();
/// \brief Replace a temporary node with a permanent one.
///
@@ -982,15 +954,15 @@ protected:
private:
void handleChangedOperand(void *Ref, Metadata *New);
+ /// Resolve a unique, unresolved node.
void resolve();
+
+ /// Drop RAUW support, if any.
+ void dropReplaceableUses();
+
void resolveAfterOperandChange(Metadata *Old, Metadata *New);
void decrementUnresolvedOperandCount();
- unsigned countUnresolvedOperands();
-
- /// Resolve cycles recursively. If \p AllowTemps is true, then any temporary
- /// metadata is ignored, otherwise it asserts when encountering temporary
- /// metadata.
- void resolveRecursivelyImpl(bool AllowTemps);
+ void countUnresolvedOperands();
/// \brief Mutate this to be "uniqued".
///
@@ -1221,6 +1193,52 @@ public:
typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array;
#include "llvm/IR/Metadata.def"
+/// Placeholder metadata for operands of distinct MDNodes.
+///
+/// This is a lightweight placeholder for an operand of a distinct node. It's
+/// purpose is to help track forward references when creating a distinct node.
+/// This allows distinct nodes involved in a cycle to be constructed before
+/// their operands without requiring a heavyweight temporary node with
+/// full-blown RAUW support.
+///
+/// Each placeholder supports only a single MDNode user. Clients should pass
+/// an ID, retrieved via \a getID(), to indicate the "real" operand that this
+/// should be replaced with.
+///
+/// While it would be possible to implement move operators, they would be
+/// fairly expensive. Leave them unimplemented to discourage their use
+/// (clients can use std::deque, std::list, BumpPtrAllocator, etc.).
+class DistinctMDOperandPlaceholder : public Metadata {
+ friend class MetadataTracking;
+
+ Metadata **Use = nullptr;
+
+ DistinctMDOperandPlaceholder() = delete;
+ DistinctMDOperandPlaceholder(DistinctMDOperandPlaceholder &&) = delete;
+ DistinctMDOperandPlaceholder(const DistinctMDOperandPlaceholder &) = delete;
+
+public:
+ explicit DistinctMDOperandPlaceholder(unsigned ID)
+ : Metadata(DistinctMDOperandPlaceholderKind, Distinct) {
+ SubclassData32 = ID;
+ }
+
+ ~DistinctMDOperandPlaceholder() {
+ if (Use)
+ *Use = nullptr;
+ }
+
+ unsigned getID() const { return SubclassData32; }
+
+ /// Replace the use of this with MD.
+ void replaceUseWith(Metadata *MD) {
+ if (!Use)
+ return;
+ *Use = MD;
+ Use = nullptr;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// \brief A tuple of MDNodes.
///
@@ -1297,6 +1315,8 @@ public:
void setOperand(unsigned I, MDNode *New);
StringRef getName() const;
void print(raw_ostream &ROS, bool IsForDebug = false) const;
+ void print(raw_ostream &ROS, ModuleSlotTracker &MST,
+ bool IsForDebug = false) const;
void dump() const;
// ---------------------------------------------------------------------------