llvm.org GIT mirror llvm / 0a9f921
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226529 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
8 changed file(s) with 252 addition(s) and 21 deletion(s). Raw diff Collapse all Expand all
4848 HANDLE_MDNODE_BRANCH(MDNode)
4949 HANDLE_MDNODE_LEAF(MDTuple)
5050 HANDLE_MDNODE_LEAF(MDLocation)
51 HANDLE_MDNODE_BRANCH(DwarfNode)
52 HANDLE_MDNODE_LEAF(GenericDwarfNode)
5153
5254 #undef HANDLE_METADATA
5355 #undef HANDLE_METADATA_LEAF
6060 enum MetadataKind {
6161 MDTupleKind,
6262 MDLocationKind,
63 GenericDwarfNodeKind,
6364 ConstantAsMetadataKind,
6465 LocalAsMetadataKind,
6566 MDStringKind
703704 }
704705
705706 MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
706 ArrayRef MDs);
707 ArrayRef Ops1, ArrayRef Ops2 = None);
707708 ~MDNode() {}
708709
709710 void dropAllReferences();
846847 /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
847848 static bool classof(const Metadata *MD) {
848849 return MD->getMetadataID() == MDTupleKind ||
849 MD->getMetadataID() == MDLocationKind;
850 MD->getMetadataID() == MDLocationKind ||
851 MD->getMetadataID() == GenericDwarfNodeKind;
850852 }
851853
852854 /// \brief Check whether MDNode is a vtable access.
985987
986988 static bool classof(const Metadata *MD) {
987989 return MD->getMetadataID() == MDLocationKind;
990 }
991 };
992
993 /// \brief Tagged dwarf node.
994 ///
995 /// A metadata node with a DWARF tag.
996 class DwarfNode : public MDNode {
997 friend class LLVMContextImpl;
998 friend class MDNode;
999
1000 protected:
1001 DwarfNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
1002 ArrayRef Ops1, ArrayRef Ops2 = None)
1003 : MDNode(C, ID, Storage, Ops1, Ops2) {
1004 assert(Tag < 1u << 16);
1005 SubclassData16 = Tag;
1006 }
1007 ~DwarfNode() {}
1008
1009 public:
1010 unsigned getTag() const { return SubclassData16; }
1011
1012 static bool classof(const Metadata *MD) {
1013 return MD->getMetadataID() == GenericDwarfNodeKind;
1014 }
1015 };
1016
1017 /// \brief Generic tagged dwarf node.
1018 ///
1019 /// A generic metadata node with a DWARF tag that doesn't have special
1020 /// handling.
1021 class GenericDwarfNode : public DwarfNode {
1022 friend class LLVMContextImpl;
1023 friend class MDNode;
1024
1025 GenericDwarfNode(LLVMContext &C, StorageType Storage, unsigned Hash,
1026 unsigned Tag, ArrayRef Ops1,
1027 ArrayRef Ops2)
1028 : DwarfNode(C, GenericDwarfNodeKind, Storage, Tag, Ops1, Ops2) {
1029 setHash(Hash);
1030 }
1031 ~GenericDwarfNode() { dropAllReferences(); }
1032
1033 void setHash(unsigned Hash) { SubclassData32 = Hash; }
1034 void recalculateHash();
1035
1036 static GenericDwarfNode *getImpl(LLVMContext &Context, unsigned Tag,
1037 MDString *Header,
1038 ArrayRef DwarfOps,
1039 StorageType Storage,
1040 bool ShouldCreate = true);
1041
1042 public:
1043 unsigned getHash() const { return SubclassData32; }
1044
1045 static GenericDwarfNode *get(LLVMContext &Context,
1046 unsigned Tag,
1047 MDString *Header,
1048 ArrayRef DwarfOps) {
1049 return getImpl(Context, Tag, Header, DwarfOps, Uniqued);
1050 }
1051 static GenericDwarfNode *getIfExists(LLVMContext &Context, unsigned Tag,
1052 MDString *Header,
1053 ArrayRef DwarfOps) {
1054 return getImpl(Context, Tag, Header, DwarfOps, Uniqued,
1055 /* ShouldCreate */ false);
1056 }
1057 static GenericDwarfNode *getDistinct(LLVMContext &Context, unsigned Tag,
1058 MDString *Header,
1059 ArrayRef DwarfOps) {
1060 return getImpl(Context, Tag, Header, DwarfOps, Distinct);
1061 }
1062 static TempGenericDwarfNode getTemporary(LLVMContext &Context, unsigned Tag,
1063 MDString *Header,
1064 ArrayRef DwarfOps) {
1065 return TempGenericDwarfNode(
1066 getImpl(Context, Tag, Header, DwarfOps, Temporary));
1067 }
1068
1069 unsigned getTag() const { return SubclassData16; }
1070 MDString *getHeader() const { return cast_or_null(getOperand(0)); }
1071
1072 op_iterator dwarf_op_begin() const { return op_begin() + 1; }
1073 op_iterator dwarf_op_end() const { return op_end(); }
1074 op_range dwarf_operands() const {
1075 return op_range(dwarf_op_begin(), dwarf_op_end());
1076 }
1077
1078 unsigned getNumDwarfOperands() const { return getNumOperands() - 1; }
1079 const MDOperand &getDwarfOperand(unsigned I) const {
1080 return getOperand(I + 1);
1081 }
1082 void replaceDwarfOperandWith(unsigned I, Metadata *New) {
1083 replaceOperandWith(I + 1, New);
1084 }
1085
1086 static bool classof(const Metadata *MD) {
1087 return MD->getMetadataID() == GenericDwarfNodeKind;
9881088 }
9891089 };
9901090
12851285 }
12861286 } // end namespace
12871287
1288 static void writeGenericDwarfNode(raw_ostream &, const GenericDwarfNode *,
1289 TypePrinting *, SlotTracker *,
1290 const Module *) {
1291 llvm_unreachable("Unimplemented write");
1292 }
1293
12881294 static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
12891295 TypePrinting *TypePrinter, SlotTracker *Machine,
12901296 const Module *Context) {
179179 static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
180180 }
181181
182 unsigned MDNodeOpsKey::calculateHash(MDNode *N) {
183 unsigned Hash = hash_combine_range(N->op_begin(), N->op_end());
182 unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) {
183 unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end());
184184 #ifndef NDEBUG
185185 {
186 SmallVector MDs(N->op_begin(), N->op_end());
186 SmallVector MDs(N->op_begin() + Offset, N->op_end());
187187 unsigned RawHash = calculateHash(MDs);
188188 assert(Hash == RawHash &&
189189 "Expected hash of MDOperand to equal hash of Metadata*");
178178 : RawOps(Ops), Hash(calculateHash(Ops)) {}
179179
180180 template
181 MDNodeOpsKey(NodeTy *N)
182 : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
183
184 template bool compareOps(const NodeTy *RHS) const {
181 MDNodeOpsKey(NodeTy *N, unsigned Offset = 0)
182 : Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
183
184 template
185 bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
185186 if (getHash() != RHS->getHash())
186187 return false;
187188
188189 assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
189 return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
190 }
191
192 static unsigned calculateHash(MDNode *N);
190 return RawOps.empty() ? compareOps(Ops, RHS, Offset)
191 : compareOps(RawOps, RHS, Offset);
192 }
193
194 static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
193195
194196 private:
195197 template
196 static bool compareOps(ArrayRef Ops, const MDNode *RHS) {
197 if (Ops.size() != RHS->getNumOperands())
198 static bool compareOps(ArrayRef Ops, const MDNode *RHS, unsigned Offset) {
199 if (Ops.size() != RHS->getNumOperands() - Offset)
198200 return false;
199 return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
201 return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
200202 }
201203
202204 static unsigned calculateHash(ArrayRef Ops);
282284 }
283285 };
284286
287 /// \brief DenseMapInfo for GenericDwarfNode.
288 struct GenericDwarfNodeInfo {
289 struct KeyTy : MDNodeOpsKey {
290 unsigned Tag;
291 MDString *Header;
292 KeyTy(unsigned Tag, MDString *Header, ArrayRef DwarfOps)
293 : MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
294 KeyTy(GenericDwarfNode *N)
295 : MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getHeader()) {}
296
297 bool operator==(const GenericDwarfNode *RHS) const {
298 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
299 return false;
300 return Tag == RHS->getTag() && Header == RHS->getHeader() &&
301 compareOps(RHS, 1);
302 }
303
304 static unsigned calculateHash(GenericDwarfNode *N) {
305 return MDNodeOpsKey::calculateHash(N, 1);
306 }
307 };
308 static inline GenericDwarfNode *getEmptyKey() {
309 return DenseMapInfo::getEmptyKey();
310 }
311 static inline GenericDwarfNode *getTombstoneKey() {
312 return DenseMapInfo::getTombstoneKey();
313 }
314 static unsigned getHashValue(const KeyTy &Key) {
315 return hash_combine(Key.getHash(), Key.Tag, Key.Header);
316 }
317 static unsigned getHashValue(const GenericDwarfNode *U) {
318 return hash_combine(U->getHash(), U->getTag(), U->getHeader());
319 }
320 static bool isEqual(const KeyTy &LHS, const GenericDwarfNode *RHS) {
321 return LHS == RHS;
322 }
323 static bool isEqual(const GenericDwarfNode *LHS,
324 const GenericDwarfNode *RHS) {
325 return LHS == RHS;
326 }
327 };
328
285329 class LLVMContextImpl {
286330 public:
287331 /// OwnedModules - The set of modules instantiated in this context, and which
314358
315359 DenseSet MDTuples;
316360 DenseSet MDLocations;
361 DenseSet GenericDwarfNodes;
317362
318363 // MDNodes may be uniqued or not uniqued. When they're not uniqued, they
319364 // aren't in the MDNodeSet, but they're still shared between objects, so no
396396 }
397397
398398 MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
399 ArrayRef MDs)
400 : Metadata(ID, Storage), NumOperands(MDs.size()), NumUnresolved(0),
401 Context(Context) {
402 for (unsigned I = 0, E = MDs.size(); I != E; ++I)
403 setOperand(I, MDs[I]);
399 ArrayRef Ops1, ArrayRef Ops2)
400 : Metadata(ID, Storage), NumOperands(Ops1.size() + Ops2.size()),
401 NumUnresolved(0), Context(Context) {
402 unsigned Op = 0;
403 for (Metadata *MD : Ops1)
404 setOperand(Op++, MD);
405 for (Metadata *MD : Ops2)
406 setOperand(Op++, MD);
404407
405408 if (isDistinct())
406409 return;
524527
525528 void MDTuple::recalculateHash() {
526529 setHash(MDTupleInfo::KeyTy::calculateHash(this));
530 }
531
532 void GenericDwarfNode::recalculateHash() {
533 setHash(GenericDwarfNodeInfo::KeyTy::calculateHash(this));
527534 }
528535
529536 void MDNode::dropAllReferences() {
619626 break;
620627 case MDTupleKind:
621628 cast(this)->recalculateHash();
629 break;
630 case GenericDwarfNodeKind:
631 cast(this)->recalculateHash();
622632 break;
623633 }
624634
732742 Storage, Context.pImpl->MDLocations);
733743 }
734744
745 GenericDwarfNode *GenericDwarfNode::getImpl(LLVMContext &Context, unsigned Tag,
746 MDString *Header,
747 ArrayRef DwarfOps,
748 StorageType Storage,
749 bool ShouldCreate) {
750 unsigned Hash = 0;
751 if (Storage == Uniqued) {
752 GenericDwarfNodeInfo::KeyTy Key(Tag, Header, DwarfOps);
753 if (auto *N = getUniqued(Context.pImpl->GenericDwarfNodes, Key))
754 return N;
755 if (!ShouldCreate)
756 return nullptr;
757 Hash = Key.getHash();
758 } else {
759 assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
760 }
761
762 Metadata *PreOps[] = {Header};
763 return storeImpl(new (DwarfOps.size() + 1) GenericDwarfNode(
764 Context, Storage, Hash, Tag, PreOps, DwarfOps),
765 Storage, Context.pImpl->GenericDwarfNodes);
766 }
767
735768 void MDNode::deleteTemporary(MDNode *N) {
736769 assert(N->isTemporary() && "Expected temporary node");
737770 N->deleteAsSubclass();
742775 Storage = Distinct;
743776 if (auto *T = dyn_cast(this))
744777 T->setHash(0);
778 else if (auto *G = dyn_cast(this))
779 G->setHash(0);
745780 getContext().pImpl->DistinctMDNodes.insert(this);
746781 }
747782
191191 Node->getInlinedAt());
192192 }
193193
194 static TempGenericDwarfNode
195 cloneGenericDwarfNode(const GenericDwarfNode *Node) {
196 SmallVector DwarfOps;
197 DwarfOps.append(Node->dwarf_op_begin(), Node->dwarf_op_end());
198 return GenericDwarfNode::getTemporary(Node->getContext(), Node->getTag(),
199 Node->getHeader(), DwarfOps);
200 }
201
194202 static TempMDNode cloneMDNode(const MDNode *Node) {
195203 switch (Node->getMetadataID()) {
196204 default:
560560 EXPECT_FALSE(L->isResolved());
561561 }
562562
563 typedef MetadataTest GenericDwarfNodeTest;
564
565 TEST_F(GenericDwarfNodeTest, get) {
566 auto *Header = MDString::get(Context, "header");
567 auto *Empty = MDNode::get(Context, None);
568 Metadata *Ops1[] = {Empty};
569 auto *N = GenericDwarfNode::get(Context, 15, Header, Ops1);
570 EXPECT_EQ(15u, N->getTag());
571 EXPECT_EQ(2u, N->getNumOperands());
572 EXPECT_EQ(Header, N->getHeader());
573 EXPECT_EQ(Header, N->getOperand(0));
574 EXPECT_EQ(1u, N->getNumDwarfOperands());
575 EXPECT_EQ(Empty, N->getDwarfOperand(0));
576 EXPECT_EQ(Empty, N->getOperand(1));
577 ASSERT_TRUE(N->isUniqued());
578
579 EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
580
581 N->replaceOperandWith(1, nullptr);
582 EXPECT_EQ(15u, N->getTag());
583 EXPECT_EQ(Header, N->getHeader());
584 EXPECT_EQ(nullptr, N->getDwarfOperand(0));
585 ASSERT_TRUE(N->isUniqued());
586
587 Metadata *Ops2[] = {nullptr};
588 EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops2));
589
590 N->replaceDwarfOperandWith(0, Empty);
591 EXPECT_EQ(15u, N->getTag());
592 EXPECT_EQ(Header, N->getHeader());
593 EXPECT_EQ(Empty, N->getDwarfOperand(0));
594 ASSERT_TRUE(N->isUniqued());
595 EXPECT_EQ(N, GenericDwarfNode::get(Context, 15, Header, Ops1));
596 }
597
563598 typedef MetadataTest MetadataAsValueTest;
564599
565600 TEST_F(MetadataAsValueTest, MDNode) {