diff options
Diffstat (limited to 'include/llvm/IR/Metadata.h')
-rw-r--r-- | include/llvm/IR/Metadata.h | 152 |
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; // --------------------------------------------------------------------------- |