IR: Extract DEFINE_MDNODE_GET(), NFC
[oota-llvm.git] / include / llvm / IR / DebugInfoMetadata.h
1 //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Declarations for metadata specific to debug info.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_IR_DEBUGINFOMETADATA_H
15 #define LLVM_IR_DEBUGINFOMETADATA_H
16
17 #include "llvm/IR/Metadata.h"
18
19 // Helper macros for defining get() overrides.
20 #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__
21 #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS
22 #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS)                                 \
23   static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) {  \
24     return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued);          \
25   }                                                                            \
26   static CLASS *getIfExists(LLVMContext &Context,                              \
27                             DEFINE_MDNODE_GET_UNPACK(FORMAL)) {                \
28     return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued,           \
29                    /* ShouldCreate */ false);                                  \
30   }                                                                            \
31   static CLASS *getDistinct(LLVMContext &Context,                              \
32                             DEFINE_MDNODE_GET_UNPACK(FORMAL)) {                \
33     return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct);         \
34   }                                                                            \
35   static Temp##CLASS getTemporary(LLVMContext &Context,                        \
36                                   DEFINE_MDNODE_GET_UNPACK(FORMAL)) {          \
37     return Temp##CLASS(                                                        \
38         getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary));          \
39   }
40
41 namespace llvm {
42
43 /// \brief Debug location.
44 ///
45 /// A debug location in source code, used for debug info and otherwise.
46 class MDLocation : public MDNode {
47   friend class LLVMContextImpl;
48   friend class MDNode;
49
50   MDLocation(LLVMContext &C, StorageType Storage, unsigned Line,
51              unsigned Column, ArrayRef<Metadata *> MDs);
52   ~MDLocation() { dropAllReferences(); }
53
54   static MDLocation *getImpl(LLVMContext &Context, unsigned Line,
55                              unsigned Column, Metadata *Scope,
56                              Metadata *InlinedAt, StorageType Storage,
57                              bool ShouldCreate = true);
58
59   TempMDLocation cloneImpl() const {
60     return getTemporary(getContext(), getLine(), getColumn(), getScope(),
61                         getInlinedAt());
62   }
63
64   // Disallow replacing operands.
65   void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
66
67 public:
68   DEFINE_MDNODE_GET(MDLocation,
69                     (unsigned Line, unsigned Column, Metadata *Scope,
70                      Metadata *InlinedAt = nullptr),
71                     (Line, Column, Scope, InlinedAt))
72
73   /// \brief Return a (temporary) clone of this.
74   TempMDLocation clone() const { return cloneImpl(); }
75
76   unsigned getLine() const { return SubclassData32; }
77   unsigned getColumn() const { return SubclassData16; }
78   Metadata *getScope() const { return getOperand(0); }
79   Metadata *getInlinedAt() const {
80     if (getNumOperands() == 2)
81       return getOperand(1);
82     return nullptr;
83   }
84
85   static bool classof(const Metadata *MD) {
86     return MD->getMetadataID() == MDLocationKind;
87   }
88 };
89
90 /// \brief Tagged DWARF-like metadata node.
91 ///
92 /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*,
93 /// defined in llvm/Support/Dwarf.h).  Called \a DebugNode because it's
94 /// potentially used for non-DWARF output.
95 class DebugNode : public MDNode {
96   friend class LLVMContextImpl;
97   friend class MDNode;
98
99 protected:
100   DebugNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
101             ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
102       : MDNode(C, ID, Storage, Ops1, Ops2) {
103     assert(Tag < 1u << 16);
104     SubclassData16 = Tag;
105   }
106   ~DebugNode() {}
107
108   StringRef getStringOperand(unsigned I) const {
109     if (auto *S = cast_or_null<MDString>(getOperand(I)))
110       return S->getString();
111     return StringRef();
112   }
113
114 public:
115   unsigned getTag() const { return SubclassData16; }
116
117   static bool classof(const Metadata *MD) {
118     return MD->getMetadataID() == GenericDebugNodeKind;
119   }
120 };
121
122 /// \brief Generic tagged DWARF-like metadata node.
123 ///
124 /// An un-specialized DWARF-like metadata node.  The first operand is a
125 /// (possibly empty) null-separated \a MDString header that contains arbitrary
126 /// fields.  The remaining operands are \a dwarf_operands(), and are pointers
127 /// to other metadata.
128 class GenericDebugNode : public DebugNode {
129   friend class LLVMContextImpl;
130   friend class MDNode;
131
132   GenericDebugNode(LLVMContext &C, StorageType Storage, unsigned Hash,
133                    unsigned Tag, ArrayRef<Metadata *> Ops1,
134                    ArrayRef<Metadata *> Ops2)
135       : DebugNode(C, GenericDebugNodeKind, Storage, Tag, Ops1, Ops2) {
136     setHash(Hash);
137   }
138   ~GenericDebugNode() { dropAllReferences(); }
139
140   void setHash(unsigned Hash) { SubclassData32 = Hash; }
141   void recalculateHash();
142
143   static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag,
144                                    StringRef Header,
145                                    ArrayRef<Metadata *> DwarfOps,
146                                    StorageType Storage,
147                                    bool ShouldCreate = true);
148
149   TempGenericDebugNode cloneImpl() const {
150     return getTemporary(
151         getContext(), getTag(), getHeader(),
152         SmallVector<Metadata *, 4>(dwarf_op_begin(), dwarf_op_end()));
153   }
154
155 public:
156   unsigned getHash() const { return SubclassData32; }
157
158   DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header,
159                                        ArrayRef<Metadata *> DwarfOps),
160                     (Tag, Header, DwarfOps))
161
162   /// \brief Return a (temporary) clone of this.
163   TempGenericDebugNode clone() const { return cloneImpl(); }
164
165   unsigned getTag() const { return SubclassData16; }
166   StringRef getHeader() const { return getStringOperand(0); }
167
168   op_iterator dwarf_op_begin() const { return op_begin() + 1; }
169   op_iterator dwarf_op_end() const { return op_end(); }
170   op_range dwarf_operands() const {
171     return op_range(dwarf_op_begin(), dwarf_op_end());
172   }
173
174   unsigned getNumDwarfOperands() const { return getNumOperands() - 1; }
175   const MDOperand &getDwarfOperand(unsigned I) const {
176     return getOperand(I + 1);
177   }
178   void replaceDwarfOperandWith(unsigned I, Metadata *New) {
179     replaceOperandWith(I + 1, New);
180   }
181
182   static bool classof(const Metadata *MD) {
183     return MD->getMetadataID() == GenericDebugNodeKind;
184   }
185 };
186
187 } // end namespace llvm
188
189 #undef DEFINE_MDNODE_GET_UNPACK_IMPL
190 #undef DEFINE_MDNODE_GET_UNPACK
191 #undef DEFINE_MDNODE_GET
192
193 #endif