[llvm] r226529 - IR: Introduce GenericDwarfNode
Duncan P. N. Exon Smith
dexonsmith at apple.com
Mon Jan 19 16:01:44 PST 2015
Author: dexonsmith
Date: Mon Jan 19 18:01:43 2015
New Revision: 226529
URL: http://llvm.org/viewvc/llvm-project?rev=226529&view=rev
Log:
IR: Introduce GenericDwarfNode
As part of PR22235, introduce `DwarfNode` and `GenericDwarfNode`. The
former is a metadata node with a DWARF tag. The latter matches our
current (generic) schema of a header with string (and stringified
integer) data and an arbitrary number of operands.
This doesn't move it into place yet; that change will require a large
number of testcase updates.
Modified:
llvm/trunk/include/llvm/IR/Metadata.def
llvm/trunk/include/llvm/IR/Metadata.h
llvm/trunk/lib/IR/AsmWriter.cpp
llvm/trunk/lib/IR/LLVMContextImpl.cpp
llvm/trunk/lib/IR/LLVMContextImpl.h
llvm/trunk/lib/IR/Metadata.cpp
llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
llvm/trunk/unittests/IR/MetadataTest.cpp
Modified: llvm/trunk/include/llvm/IR/Metadata.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.def?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.def (original)
+++ llvm/trunk/include/llvm/IR/Metadata.def Mon Jan 19 18:01:43 2015
@@ -49,6 +49,8 @@ HANDLE_METADATA_LEAF(LocalAsMetadata)
HANDLE_MDNODE_BRANCH(MDNode)
HANDLE_MDNODE_LEAF(MDTuple)
HANDLE_MDNODE_LEAF(MDLocation)
+HANDLE_MDNODE_BRANCH(DwarfNode)
+HANDLE_MDNODE_LEAF(GenericDwarfNode)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Mon Jan 19 18:01:43 2015
@@ -61,6 +61,7 @@ public:
enum MetadataKind {
MDTupleKind,
MDLocationKind,
+ GenericDwarfNodeKind,
ConstantAsMetadataKind,
LocalAsMetadataKind,
MDStringKind
@@ -704,7 +705,7 @@ protected:
}
MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
- ArrayRef<Metadata *> MDs);
+ ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None);
~MDNode() {}
void dropAllReferences();
@@ -847,7 +848,8 @@ public:
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDTupleKind ||
- MD->getMetadataID() == MDLocationKind;
+ MD->getMetadataID() == MDLocationKind ||
+ MD->getMetadataID() == GenericDwarfNodeKind;
}
/// \brief Check whether MDNode is a vtable access.
@@ -989,6 +991,104 @@ public:
}
};
+/// \brief Tagged dwarf node.
+///
+/// A metadata node with a DWARF tag.
+class DwarfNode : public MDNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+protected:
+ DwarfNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
+ ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
+ : MDNode(C, ID, Storage, Ops1, Ops2) {
+ assert(Tag < 1u << 16);
+ SubclassData16 = Tag;
+ }
+ ~DwarfNode() {}
+
+public:
+ unsigned getTag() const { return SubclassData16; }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == GenericDwarfNodeKind;
+ }
+};
+
+/// \brief Generic tagged dwarf node.
+///
+/// A generic metadata node with a DWARF tag that doesn't have special
+/// handling.
+class GenericDwarfNode : public DwarfNode {
+ friend class LLVMContextImpl;
+ friend class MDNode;
+
+ GenericDwarfNode(LLVMContext &C, StorageType Storage, unsigned Hash,
+ unsigned Tag, ArrayRef<Metadata *> Ops1,
+ ArrayRef<Metadata *> Ops2)
+ : DwarfNode(C, GenericDwarfNodeKind, Storage, Tag, Ops1, Ops2) {
+ setHash(Hash);
+ }
+ ~GenericDwarfNode() { dropAllReferences(); }
+
+ void setHash(unsigned Hash) { SubclassData32 = Hash; }
+ void recalculateHash();
+
+ static GenericDwarfNode *getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps,
+ StorageType Storage,
+ bool ShouldCreate = true);
+
+public:
+ unsigned getHash() const { return SubclassData32; }
+
+ static GenericDwarfNode *get(LLVMContext &Context,
+ unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps) {
+ return getImpl(Context, Tag, Header, DwarfOps, Uniqued);
+ }
+ static GenericDwarfNode *getIfExists(LLVMContext &Context, unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps) {
+ return getImpl(Context, Tag, Header, DwarfOps, Uniqued,
+ /* ShouldCreate */ false);
+ }
+ static GenericDwarfNode *getDistinct(LLVMContext &Context, unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps) {
+ return getImpl(Context, Tag, Header, DwarfOps, Distinct);
+ }
+ static TempGenericDwarfNode getTemporary(LLVMContext &Context, unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps) {
+ return TempGenericDwarfNode(
+ getImpl(Context, Tag, Header, DwarfOps, Temporary));
+ }
+
+ unsigned getTag() const { return SubclassData16; }
+ MDString *getHeader() const { return cast_or_null<MDString>(getOperand(0)); }
+
+ op_iterator dwarf_op_begin() const { return op_begin() + 1; }
+ op_iterator dwarf_op_end() const { return op_end(); }
+ op_range dwarf_operands() const {
+ return op_range(dwarf_op_begin(), dwarf_op_end());
+ }
+
+ unsigned getNumDwarfOperands() const { return getNumOperands() - 1; }
+ const MDOperand &getDwarfOperand(unsigned I) const {
+ return getOperand(I + 1);
+ }
+ void replaceDwarfOperandWith(unsigned I, Metadata *New) {
+ replaceOperandWith(I + 1, New);
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == GenericDwarfNodeKind;
+ }
+};
+
//===----------------------------------------------------------------------===//
/// \brief A tuple of MDNodes.
///
Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Mon Jan 19 18:01:43 2015
@@ -1286,6 +1286,12 @@ raw_ostream &operator<<(raw_ostream &OS,
}
} // end namespace
+static void writeGenericDwarfNode(raw_ostream &, const GenericDwarfNode *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("Unimplemented write");
+}
+
static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Mon Jan 19 18:01:43 2015
@@ -180,11 +180,11 @@ namespace llvm {
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
}
-unsigned MDNodeOpsKey::calculateHash(MDNode *N) {
- unsigned Hash = hash_combine_range(N->op_begin(), N->op_end());
+unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) {
+ unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end());
#ifndef NDEBUG
{
- SmallVector<Metadata *, 8> MDs(N->op_begin(), N->op_end());
+ SmallVector<Metadata *, 8> MDs(N->op_begin() + Offset, N->op_end());
unsigned RawHash = calculateHash(MDs);
assert(Hash == RawHash &&
"Expected hash of MDOperand to equal hash of Metadata*");
Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Mon Jan 19 18:01:43 2015
@@ -179,25 +179,27 @@ protected:
: RawOps(Ops), Hash(calculateHash(Ops)) {}
template <class NodeTy>
- MDNodeOpsKey(NodeTy *N)
- : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
+ MDNodeOpsKey(NodeTy *N, unsigned Offset = 0)
+ : Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
- template <class NodeTy> bool compareOps(const NodeTy *RHS) const {
+ template <class NodeTy>
+ bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
if (getHash() != RHS->getHash())
return false;
assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
- return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
+ return RawOps.empty() ? compareOps(Ops, RHS, Offset)
+ : compareOps(RawOps, RHS, Offset);
}
- static unsigned calculateHash(MDNode *N);
+ static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
private:
template <class T>
- static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS) {
- if (Ops.size() != RHS->getNumOperands())
+ static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
+ if (Ops.size() != RHS->getNumOperands() - Offset)
return false;
- return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
+ return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
}
static unsigned calculateHash(ArrayRef<Metadata *> Ops);
@@ -283,6 +285,48 @@ struct MDLocationInfo {
}
};
+/// \brief DenseMapInfo for GenericDwarfNode.
+struct GenericDwarfNodeInfo {
+ struct KeyTy : MDNodeOpsKey {
+ unsigned Tag;
+ MDString *Header;
+ KeyTy(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)
+ : MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
+ KeyTy(GenericDwarfNode *N)
+ : MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getHeader()) {}
+
+ bool operator==(const GenericDwarfNode *RHS) const {
+ if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+ return false;
+ return Tag == RHS->getTag() && Header == RHS->getHeader() &&
+ compareOps(RHS, 1);
+ }
+
+ static unsigned calculateHash(GenericDwarfNode *N) {
+ return MDNodeOpsKey::calculateHash(N, 1);
+ }
+ };
+ static inline GenericDwarfNode *getEmptyKey() {
+ return DenseMapInfo<GenericDwarfNode *>::getEmptyKey();
+ }
+ static inline GenericDwarfNode *getTombstoneKey() {
+ return DenseMapInfo<GenericDwarfNode *>::getTombstoneKey();
+ }
+ static unsigned getHashValue(const KeyTy &Key) {
+ return hash_combine(Key.getHash(), Key.Tag, Key.Header);
+ }
+ static unsigned getHashValue(const GenericDwarfNode *U) {
+ return hash_combine(U->getHash(), U->getTag(), U->getHeader());
+ }
+ static bool isEqual(const KeyTy &LHS, const GenericDwarfNode *RHS) {
+ return LHS == RHS;
+ }
+ static bool isEqual(const GenericDwarfNode *LHS,
+ const GenericDwarfNode *RHS) {
+ return LHS == RHS;
+ }
+};
+
class LLVMContextImpl {
public:
/// OwnedModules - The set of modules instantiated in this context, and which
@@ -315,6 +359,7 @@ public:
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
DenseSet<MDLocation *, MDLocationInfo> MDLocations;
+ DenseSet<GenericDwarfNode *, GenericDwarfNodeInfo> GenericDwarfNodes;
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
// aren't in the MDNodeSet, but they're still shared between objects, so no
Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Mon Jan 19 18:01:43 2015
@@ -397,11 +397,14 @@ void MDNode::operator delete(void *Mem)
}
MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
- ArrayRef<Metadata *> MDs)
- : Metadata(ID, Storage), NumOperands(MDs.size()), NumUnresolved(0),
- Context(Context) {
- for (unsigned I = 0, E = MDs.size(); I != E; ++I)
- setOperand(I, MDs[I]);
+ 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;
@@ -527,6 +530,10 @@ void MDTuple::recalculateHash() {
setHash(MDTupleInfo::KeyTy::calculateHash(this));
}
+void GenericDwarfNode::recalculateHash() {
+ setHash(GenericDwarfNodeInfo::KeyTy::calculateHash(this));
+}
+
void MDNode::dropAllReferences() {
for (unsigned I = 0, E = NumOperands; I != E; ++I)
setOperand(I, nullptr);
@@ -621,6 +628,9 @@ MDNode *MDNode::uniquify() {
case MDTupleKind:
cast<MDTuple>(this)->recalculateHash();
break;
+ case GenericDwarfNodeKind:
+ cast<GenericDwarfNode>(this)->recalculateHash();
+ break;
}
// Try to insert into uniquing store.
@@ -733,6 +743,29 @@ MDLocation *MDLocation::getImpl(LLVMCont
Storage, Context.pImpl->MDLocations);
}
+GenericDwarfNode *GenericDwarfNode::getImpl(LLVMContext &Context, unsigned Tag,
+ MDString *Header,
+ ArrayRef<Metadata *> DwarfOps,
+ StorageType Storage,
+ bool ShouldCreate) {
+ unsigned Hash = 0;
+ if (Storage == Uniqued) {
+ GenericDwarfNodeInfo::KeyTy Key(Tag, Header, DwarfOps);
+ if (auto *N = getUniqued(Context.pImpl->GenericDwarfNodes, Key))
+ return N;
+ if (!ShouldCreate)
+ return nullptr;
+ Hash = Key.getHash();
+ } else {
+ assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
+ }
+
+ Metadata *PreOps[] = {Header};
+ return storeImpl(new (DwarfOps.size() + 1) GenericDwarfNode(
+ Context, Storage, Hash, Tag, PreOps, DwarfOps),
+ Storage, Context.pImpl->GenericDwarfNodes);
+}
+
void MDNode::deleteTemporary(MDNode *N) {
assert(N->isTemporary() && "Expected temporary node");
N->deleteAsSubclass();
@@ -743,6 +776,8 @@ void MDNode::storeDistinctInContext() {
Storage = Distinct;
if (auto *T = dyn_cast<MDTuple>(this))
T->setHash(0);
+ else if (auto *G = dyn_cast<GenericDwarfNode>(this))
+ G->setHash(0);
getContext().pImpl->DistinctMDNodes.insert(this);
}
Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Mon Jan 19 18:01:43 2015
@@ -192,6 +192,14 @@ static TempMDLocation cloneMDLocation(co
Node->getInlinedAt());
}
+static TempGenericDwarfNode
+cloneGenericDwarfNode(const GenericDwarfNode *Node) {
+ SmallVector<Metadata *, 4> DwarfOps;
+ DwarfOps.append(Node->dwarf_op_begin(), Node->dwarf_op_end());
+ return GenericDwarfNode::getTemporary(Node->getContext(), Node->getTag(),
+ Node->getHeader(), DwarfOps);
+}
+
static TempMDNode cloneMDNode(const MDNode *Node) {
switch (Node->getMetadataID()) {
default:
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=226529&r1=226528&r2=226529&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Mon Jan 19 18:01:43 2015
@@ -561,6 +561,41 @@ TEST_F(MDLocationTest, getTemporary) {
EXPECT_FALSE(L->isResolved());
}
+typedef MetadataTest GenericDwarfNodeTest;
+
+TEST_F(GenericDwarfNodeTest, get) {
+ auto *Header = MDString::get(Context, "header");
+ auto *Empty = MDNode::get(Context, None);
+ Metadata *Ops1[] = {Empty};
+ auto *N = GenericDwarfNode::get(Context, 15, Header, Ops1);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(2u, N->getNumOperands());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(Header, N->getOperand(0));
+ EXPECT_EQ(1u, N->getNumDwarfOperands());
+ EXPECT_EQ(Empty, N->getDwarfOperand(0));
+ EXPECT_EQ(Empty, N->getOperand(1));
+ ASSERT_TRUE(N->isUniqued());
+
+ EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
+
+ N->replaceOperandWith(1, nullptr);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(nullptr, N->getDwarfOperand(0));
+ ASSERT_TRUE(N->isUniqued());
+
+ Metadata *Ops2[] = {nullptr};
+ EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops2));
+
+ N->replaceDwarfOperandWith(0, Empty);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(Empty, N->getDwarfOperand(0));
+ ASSERT_TRUE(N->isUniqued());
+ EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
+}
+
typedef MetadataTest MetadataAsValueTest;
TEST_F(MetadataAsValueTest, MDNode) {
More information about the llvm-commits
mailing list