1 | //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Declarations for metadata specific to debug info. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_IR_DEBUGINFOMETADATA_H |
14 | #define LLVM_IR_DEBUGINFOMETADATA_H |
15 | |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/BitmaskEnum.h" |
18 | #include "llvm/ADT/None.h" |
19 | #include "llvm/ADT/Optional.h" |
20 | #include "llvm/ADT/PointerUnion.h" |
21 | #include "llvm/ADT/STLExtras.h" |
22 | #include "llvm/ADT/SmallVector.h" |
23 | #include "llvm/ADT/StringRef.h" |
24 | #include "llvm/ADT/iterator_range.h" |
25 | #include "llvm/BinaryFormat/Dwarf.h" |
26 | #include "llvm/IR/Constants.h" |
27 | #include "llvm/IR/Metadata.h" |
28 | #include "llvm/Support/Casting.h" |
29 | #include <cassert> |
30 | #include <climits> |
31 | #include <cstddef> |
32 | #include <cstdint> |
33 | #include <iterator> |
34 | #include <type_traits> |
35 | #include <vector> |
36 | |
37 | // Helper macros for defining get() overrides. |
38 | #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ |
39 | #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS |
40 | #define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS) \ |
41 | static CLASS *getDistinct(LLVMContext &Context, \ |
42 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ |
43 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ |
44 | } \ |
45 | static Temp##CLASS getTemporary(LLVMContext &Context, \ |
46 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ |
47 | return Temp##CLASS( \ |
48 | getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ |
49 | } |
50 | #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ |
51 | static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ |
52 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ |
53 | } \ |
54 | static CLASS *getIfExists(LLVMContext &Context, \ |
55 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ |
56 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ |
57 | /* ShouldCreate */ false); \ |
58 | } \ |
59 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS) |
60 | |
61 | namespace llvm { |
62 | |
63 | class DITypeRefArray { |
64 | const MDTuple *N = nullptr; |
65 | |
66 | public: |
67 | DITypeRefArray() = default; |
68 | DITypeRefArray(const MDTuple *N) : N(N) {} |
69 | |
70 | explicit operator bool() const { return get(); } |
71 | explicit operator MDTuple *() const { return get(); } |
72 | |
73 | MDTuple *get() const { return const_cast<MDTuple *>(N); } |
74 | MDTuple *operator->() const { return get(); } |
75 | MDTuple &operator*() const { return *get(); } |
76 | |
77 | // FIXME: Fix callers and remove condition on N. |
78 | unsigned size() const { return N ? N->getNumOperands() : 0u; } |
79 | DIType *operator[](unsigned I) const { |
80 | return cast_or_null<DIType>(N->getOperand(I)); |
81 | } |
82 | |
83 | class iterator { |
84 | MDNode::op_iterator I = nullptr; |
85 | |
86 | public: |
87 | using iterator_category = std::input_iterator_tag; |
88 | using value_type = DIType *; |
89 | using difference_type = std::ptrdiff_t; |
90 | using pointer = void; |
91 | using reference = DIType *; |
92 | |
93 | iterator() = default; |
94 | explicit iterator(MDNode::op_iterator I) : I(I) {} |
95 | |
96 | DIType *operator*() const { return cast_or_null<DIType>(*I); } |
97 | |
98 | iterator &operator++() { |
99 | ++I; |
100 | return *this; |
101 | } |
102 | |
103 | iterator operator++(int) { |
104 | iterator Temp(*this); |
105 | ++I; |
106 | return Temp; |
107 | } |
108 | |
109 | bool operator==(const iterator &X) const { return I == X.I; } |
110 | bool operator!=(const iterator &X) const { return I != X.I; } |
111 | }; |
112 | |
113 | // FIXME: Fix callers and remove condition on N. |
114 | iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } |
115 | iterator end() const { return N ? iterator(N->op_end()) : iterator(); } |
116 | }; |
117 | |
118 | /// Tagged DWARF-like metadata node. |
119 | /// |
120 | /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, |
121 | /// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's |
122 | /// potentially used for non-DWARF output. |
123 | class DINode : public MDNode { |
124 | friend class LLVMContextImpl; |
125 | friend class MDNode; |
126 | |
127 | protected: |
128 | DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, |
129 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) |
130 | : MDNode(C, ID, Storage, Ops1, Ops2) { |
131 | assert(Tag < 1u << 16); |
132 | SubclassData16 = Tag; |
133 | } |
134 | ~DINode() = default; |
135 | |
136 | template <class Ty> Ty *getOperandAs(unsigned I) const { |
137 | return cast_or_null<Ty>(getOperand(I)); |
138 | } |
139 | |
140 | StringRef getStringOperand(unsigned I) const { |
141 | if (auto *S = getOperandAs<MDString>(I)) |
142 | return S->getString(); |
143 | return StringRef(); |
144 | } |
145 | |
146 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { |
147 | if (S.empty()) |
148 | return nullptr; |
149 | return MDString::get(Context, S); |
150 | } |
151 | |
152 | /// Allow subclasses to mutate the tag. |
153 | void setTag(unsigned Tag) { SubclassData16 = Tag; } |
154 | |
155 | public: |
156 | unsigned getTag() const { return SubclassData16; } |
157 | |
158 | /// Debug info flags. |
159 | /// |
160 | /// The three accessibility flags are mutually exclusive and rolled together |
161 | /// in the first two bits. |
162 | enum DIFlags : uint32_t { |
163 | #define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, |
164 | #define DI_FLAG_LARGEST_NEEDED |
165 | #include "llvm/IR/DebugInfoFlags.def" |
166 | FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, |
167 | FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | |
168 | FlagVirtualInheritance, |
169 | LLVM_MARK_AS_BITMASK_ENUM(FlagLargest) |
170 | }; |
171 | |
172 | static DIFlags getFlag(StringRef Flag); |
173 | static StringRef getFlagString(DIFlags Flag); |
174 | |
175 | /// Split up a flags bitfield. |
176 | /// |
177 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns |
178 | /// any remaining (unrecognized) bits. |
179 | static DIFlags splitFlags(DIFlags Flags, |
180 | SmallVectorImpl<DIFlags> &SplitFlags); |
181 | |
182 | static bool classof(const Metadata *MD) { |
183 | switch (MD->getMetadataID()) { |
184 | default: |
185 | return false; |
186 | case GenericDINodeKind: |
187 | case DISubrangeKind: |
188 | case DIEnumeratorKind: |
189 | case DIBasicTypeKind: |
190 | case DIStringTypeKind: |
191 | case DIDerivedTypeKind: |
192 | case DICompositeTypeKind: |
193 | case DISubroutineTypeKind: |
194 | case DIFileKind: |
195 | case DICompileUnitKind: |
196 | case DISubprogramKind: |
197 | case DILexicalBlockKind: |
198 | case DILexicalBlockFileKind: |
199 | case DINamespaceKind: |
200 | case DICommonBlockKind: |
201 | case DITemplateTypeParameterKind: |
202 | case DITemplateValueParameterKind: |
203 | case DIGlobalVariableKind: |
204 | case DILocalVariableKind: |
205 | case DILabelKind: |
206 | case DIObjCPropertyKind: |
207 | case DIImportedEntityKind: |
208 | case DIModuleKind: |
209 | case DIGenericSubrangeKind: |
210 | return true; |
211 | } |
212 | } |
213 | }; |
214 | |
215 | /// Generic tagged DWARF-like metadata node. |
216 | /// |
217 | /// An un-specialized DWARF-like metadata node. The first operand is a |
218 | /// (possibly empty) null-separated \a MDString header that contains arbitrary |
219 | /// fields. The remaining operands are \a dwarf_operands(), and are pointers |
220 | /// to other metadata. |
221 | class GenericDINode : public DINode { |
222 | friend class LLVMContextImpl; |
223 | friend class MDNode; |
224 | |
225 | GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, |
226 | unsigned Tag, ArrayRef<Metadata *> Ops1, |
227 | ArrayRef<Metadata *> Ops2) |
228 | : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { |
229 | setHash(Hash); |
230 | } |
231 | ~GenericDINode() { dropAllReferences(); } |
232 | |
233 | void setHash(unsigned Hash) { SubclassData32 = Hash; } |
234 | void recalculateHash(); |
235 | |
236 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, |
237 | StringRef , ArrayRef<Metadata *> DwarfOps, |
238 | StorageType Storage, bool ShouldCreate = true) { |
239 | return getImpl(Context, Tag, getCanonicalMDString(Context, Header), |
240 | DwarfOps, Storage, ShouldCreate); |
241 | } |
242 | |
243 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, |
244 | MDString *, ArrayRef<Metadata *> DwarfOps, |
245 | StorageType Storage, bool ShouldCreate = true); |
246 | |
247 | TempGenericDINode cloneImpl() const { |
248 | return getTemporary(getContext(), getTag(), getHeader(), |
249 | SmallVector<Metadata *, 4>(dwarf_operands())); |
250 | } |
251 | |
252 | public: |
253 | unsigned getHash() const { return SubclassData32; } |
254 | |
255 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef , |
256 | ArrayRef<Metadata *> DwarfOps), |
257 | (Tag, Header, DwarfOps)) |
258 | DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *, |
259 | ArrayRef<Metadata *> DwarfOps), |
260 | (Tag, Header, DwarfOps)) |
261 | |
262 | /// Return a (temporary) clone of this. |
263 | TempGenericDINode clone() const { return cloneImpl(); } |
264 | |
265 | unsigned getTag() const { return SubclassData16; } |
266 | StringRef () const { return getStringOperand(0); } |
267 | MDString *() const { return getOperandAs<MDString>(0); } |
268 | |
269 | op_iterator dwarf_op_begin() const { return op_begin() + 1; } |
270 | op_iterator dwarf_op_end() const { return op_end(); } |
271 | op_range dwarf_operands() const { |
272 | return op_range(dwarf_op_begin(), dwarf_op_end()); |
273 | } |
274 | |
275 | unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } |
276 | const MDOperand &getDwarfOperand(unsigned I) const { |
277 | return getOperand(I + 1); |
278 | } |
279 | void replaceDwarfOperandWith(unsigned I, Metadata *New) { |
280 | replaceOperandWith(I + 1, New); |
281 | } |
282 | |
283 | static bool classof(const Metadata *MD) { |
284 | return MD->getMetadataID() == GenericDINodeKind; |
285 | } |
286 | }; |
287 | |
288 | /// Array subrange. |
289 | /// |
290 | /// TODO: Merge into node for DW_TAG_array_type, which should have a custom |
291 | /// type. |
292 | class DISubrange : public DINode { |
293 | friend class LLVMContextImpl; |
294 | friend class MDNode; |
295 | |
296 | DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) |
297 | : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {} |
298 | |
299 | ~DISubrange() = default; |
300 | |
301 | static DISubrange *getImpl(LLVMContext &Context, int64_t Count, |
302 | int64_t LowerBound, StorageType Storage, |
303 | bool ShouldCreate = true); |
304 | |
305 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, |
306 | int64_t LowerBound, StorageType Storage, |
307 | bool ShouldCreate = true); |
308 | |
309 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, |
310 | Metadata *LowerBound, Metadata *UpperBound, |
311 | Metadata *Stride, StorageType Storage, |
312 | bool ShouldCreate = true); |
313 | |
314 | TempDISubrange cloneImpl() const { |
315 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), |
316 | getRawUpperBound(), getRawStride()); |
317 | } |
318 | |
319 | public: |
320 | DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), |
321 | (Count, LowerBound)) |
322 | |
323 | DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0), |
324 | (CountNode, LowerBound)) |
325 | |
326 | DEFINE_MDNODE_GET(DISubrange, |
327 | (Metadata * CountNode, Metadata *LowerBound, |
328 | Metadata *UpperBound, Metadata *Stride), |
329 | (CountNode, LowerBound, UpperBound, Stride)) |
330 | |
331 | TempDISubrange clone() const { return cloneImpl(); } |
332 | |
333 | Metadata *getRawCountNode() const { |
334 | return getOperand(0).get(); |
335 | } |
336 | |
337 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } |
338 | |
339 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } |
340 | |
341 | Metadata *getRawStride() const { return getOperand(3).get(); } |
342 | |
343 | typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; |
344 | |
345 | BoundType getCount() const; |
346 | |
347 | BoundType getLowerBound() const; |
348 | |
349 | BoundType getUpperBound() const; |
350 | |
351 | BoundType getStride() const; |
352 | |
353 | static bool classof(const Metadata *MD) { |
354 | return MD->getMetadataID() == DISubrangeKind; |
355 | } |
356 | }; |
357 | |
358 | class DIGenericSubrange : public DINode { |
359 | friend class LLVMContextImpl; |
360 | friend class MDNode; |
361 | |
362 | DIGenericSubrange(LLVMContext &C, StorageType Storage, |
363 | ArrayRef<Metadata *> Ops) |
364 | : DINode(C, DIGenericSubrangeKind, Storage, |
365 | dwarf::DW_TAG_generic_subrange, Ops) {} |
366 | |
367 | ~DIGenericSubrange() = default; |
368 | |
369 | static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, |
370 | Metadata *LowerBound, Metadata *UpperBound, |
371 | Metadata *Stride, StorageType Storage, |
372 | bool ShouldCreate = true); |
373 | |
374 | TempDIGenericSubrange cloneImpl() const { |
375 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), |
376 | getRawUpperBound(), getRawStride()); |
377 | } |
378 | |
379 | public: |
380 | DEFINE_MDNODE_GET(DIGenericSubrange, |
381 | (Metadata * CountNode, Metadata *LowerBound, |
382 | Metadata *UpperBound, Metadata *Stride), |
383 | (CountNode, LowerBound, UpperBound, Stride)) |
384 | |
385 | TempDIGenericSubrange clone() const { return cloneImpl(); } |
386 | |
387 | Metadata *getRawCountNode() const { return getOperand(0).get(); } |
388 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } |
389 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } |
390 | Metadata *getRawStride() const { return getOperand(3).get(); } |
391 | |
392 | using BoundType = PointerUnion<DIVariable *, DIExpression *>; |
393 | |
394 | BoundType getCount() const; |
395 | BoundType getLowerBound() const; |
396 | BoundType getUpperBound() const; |
397 | BoundType getStride() const; |
398 | |
399 | static bool classof(const Metadata *MD) { |
400 | return MD->getMetadataID() == DIGenericSubrangeKind; |
401 | } |
402 | }; |
403 | |
404 | /// Enumeration value. |
405 | /// |
406 | /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no |
407 | /// longer creates a type cycle. |
408 | class DIEnumerator : public DINode { |
409 | friend class LLVMContextImpl; |
410 | friend class MDNode; |
411 | |
412 | APInt Value; |
413 | DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, |
414 | bool IsUnsigned, ArrayRef<Metadata *> Ops) |
415 | : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), |
416 | Value(Value) { |
417 | SubclassData32 = IsUnsigned; |
418 | } |
419 | DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, |
420 | bool IsUnsigned, ArrayRef<Metadata *> Ops) |
421 | : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, |
422 | Ops) {} |
423 | ~DIEnumerator() = default; |
424 | |
425 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, |
426 | bool IsUnsigned, StringRef Name, |
427 | StorageType Storage, bool ShouldCreate = true) { |
428 | return getImpl(Context, Value, IsUnsigned, |
429 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); |
430 | } |
431 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, |
432 | bool IsUnsigned, MDString *Name, |
433 | StorageType Storage, bool ShouldCreate = true); |
434 | |
435 | TempDIEnumerator cloneImpl() const { |
436 | return getTemporary(getContext(), getValue(), isUnsigned(), getName()); |
437 | } |
438 | |
439 | public: |
440 | DEFINE_MDNODE_GET(DIEnumerator, |
441 | (int64_t Value, bool IsUnsigned, StringRef Name), |
442 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) |
443 | DEFINE_MDNODE_GET(DIEnumerator, |
444 | (int64_t Value, bool IsUnsigned, MDString *Name), |
445 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) |
446 | DEFINE_MDNODE_GET(DIEnumerator, |
447 | (APInt Value, bool IsUnsigned, StringRef Name), |
448 | (Value, IsUnsigned, Name)) |
449 | DEFINE_MDNODE_GET(DIEnumerator, |
450 | (APInt Value, bool IsUnsigned, MDString *Name), |
451 | (Value, IsUnsigned, Name)) |
452 | |
453 | TempDIEnumerator clone() const { return cloneImpl(); } |
454 | |
455 | const APInt &getValue() const { return Value; } |
456 | bool isUnsigned() const { return SubclassData32; } |
457 | StringRef getName() const { return getStringOperand(0); } |
458 | |
459 | MDString *getRawName() const { return getOperandAs<MDString>(0); } |
460 | |
461 | static bool classof(const Metadata *MD) { |
462 | return MD->getMetadataID() == DIEnumeratorKind; |
463 | } |
464 | }; |
465 | |
466 | /// Base class for scope-like contexts. |
467 | /// |
468 | /// Base class for lexical scopes and types (which are also declaration |
469 | /// contexts). |
470 | /// |
471 | /// TODO: Separate the concepts of declaration contexts and lexical scopes. |
472 | class DIScope : public DINode { |
473 | protected: |
474 | DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, |
475 | ArrayRef<Metadata *> Ops) |
476 | : DINode(C, ID, Storage, Tag, Ops) {} |
477 | ~DIScope() = default; |
478 | |
479 | public: |
480 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } |
481 | |
482 | inline StringRef getFilename() const; |
483 | inline StringRef getDirectory() const; |
484 | inline Optional<StringRef> getSource() const; |
485 | |
486 | StringRef getName() const; |
487 | DIScope *getScope() const; |
488 | |
489 | /// Return the raw underlying file. |
490 | /// |
491 | /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it |
492 | /// \em is the file). If \c this is an \a DIFile, we need to return \c this. |
493 | /// Otherwise, return the first operand, which is where all other subclasses |
494 | /// store their file pointer. |
495 | Metadata *getRawFile() const { |
496 | return isa<DIFile>(this) ? const_cast<DIScope *>(this) |
497 | : static_cast<Metadata *>(getOperand(0)); |
498 | } |
499 | |
500 | static bool classof(const Metadata *MD) { |
501 | switch (MD->getMetadataID()) { |
502 | default: |
503 | return false; |
504 | case DIBasicTypeKind: |
505 | case DIStringTypeKind: |
506 | case DIDerivedTypeKind: |
507 | case DICompositeTypeKind: |
508 | case DISubroutineTypeKind: |
509 | case DIFileKind: |
510 | case DICompileUnitKind: |
511 | case DISubprogramKind: |
512 | case DILexicalBlockKind: |
513 | case DILexicalBlockFileKind: |
514 | case DINamespaceKind: |
515 | case DICommonBlockKind: |
516 | case DIModuleKind: |
517 | return true; |
518 | } |
519 | } |
520 | }; |
521 | |
522 | /// File. |
523 | /// |
524 | /// TODO: Merge with directory/file node (including users). |
525 | /// TODO: Canonicalize paths on creation. |
526 | class DIFile : public DIScope { |
527 | friend class LLVMContextImpl; |
528 | friend class MDNode; |
529 | |
530 | public: |
531 | /// Which algorithm (e.g. MD5) a checksum was generated with. |
532 | /// |
533 | /// The encoding is explicit because it is used directly in Bitcode. The |
534 | /// value 0 is reserved to indicate the absence of a checksum in Bitcode. |
535 | enum ChecksumKind { |
536 | // The first variant was originally CSK_None, encoded as 0. The new |
537 | // internal representation removes the need for this by wrapping the |
538 | // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 |
539 | // encoding is reserved. |
540 | CSK_MD5 = 1, |
541 | CSK_SHA1 = 2, |
542 | CSK_SHA256 = 3, |
543 | CSK_Last = CSK_SHA256 // Should be last enumeration. |
544 | }; |
545 | |
546 | /// A single checksum, represented by a \a Kind and a \a Value (a string). |
547 | template <typename T> |
548 | struct ChecksumInfo { |
549 | /// The kind of checksum which \a Value encodes. |
550 | ChecksumKind Kind; |
551 | /// The string value of the checksum. |
552 | T Value; |
553 | |
554 | ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) { } |
555 | ~ChecksumInfo() = default; |
556 | bool operator==(const ChecksumInfo<T> &X) const { |
557 | return Kind == X.Kind && Value == X.Value; |
558 | } |
559 | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } |
560 | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } |
561 | }; |
562 | |
563 | private: |
564 | Optional<ChecksumInfo<MDString *>> Checksum; |
565 | Optional<MDString *> Source; |
566 | |
567 | DIFile(LLVMContext &C, StorageType Storage, |
568 | Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src, |
569 | ArrayRef<Metadata *> Ops) |
570 | : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), |
571 | Checksum(CS), Source(Src) {} |
572 | ~DIFile() = default; |
573 | |
574 | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, |
575 | StringRef Directory, |
576 | Optional<ChecksumInfo<StringRef>> CS, |
577 | Optional<StringRef> Source, |
578 | StorageType Storage, bool ShouldCreate = true) { |
579 | Optional<ChecksumInfo<MDString *>> MDChecksum; |
580 | if (CS) |
581 | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); |
582 | return getImpl(Context, getCanonicalMDString(Context, Filename), |
583 | getCanonicalMDString(Context, Directory), MDChecksum, |
584 | Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None, |
585 | Storage, ShouldCreate); |
586 | } |
587 | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, |
588 | MDString *Directory, |
589 | Optional<ChecksumInfo<MDString *>> CS, |
590 | Optional<MDString *> Source, StorageType Storage, |
591 | bool ShouldCreate = true); |
592 | |
593 | TempDIFile cloneImpl() const { |
594 | return getTemporary(getContext(), getFilename(), getDirectory(), |
595 | getChecksum(), getSource()); |
596 | } |
597 | |
598 | public: |
599 | DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, |
600 | Optional<ChecksumInfo<StringRef>> CS = None, |
601 | Optional<StringRef> Source = None), |
602 | (Filename, Directory, CS, Source)) |
603 | DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, |
604 | Optional<ChecksumInfo<MDString *>> CS = None, |
605 | Optional<MDString *> Source = None), |
606 | (Filename, Directory, CS, Source)) |
607 | |
608 | TempDIFile clone() const { return cloneImpl(); } |
609 | |
610 | StringRef getFilename() const { return getStringOperand(0); } |
611 | StringRef getDirectory() const { return getStringOperand(1); } |
612 | Optional<ChecksumInfo<StringRef>> getChecksum() const { |
613 | Optional<ChecksumInfo<StringRef>> StringRefChecksum; |
614 | if (Checksum) |
615 | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); |
616 | return StringRefChecksum; |
617 | } |
618 | Optional<StringRef> getSource() const { |
619 | return Source ? Optional<StringRef>((*Source)->getString()) : None; |
620 | } |
621 | |
622 | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } |
623 | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } |
624 | Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; } |
625 | Optional<MDString *> getRawSource() const { return Source; } |
626 | |
627 | static StringRef getChecksumKindAsString(ChecksumKind CSKind); |
628 | static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); |
629 | |
630 | static bool classof(const Metadata *MD) { |
631 | return MD->getMetadataID() == DIFileKind; |
632 | } |
633 | }; |
634 | |
635 | StringRef DIScope::getFilename() const { |
636 | if (auto *F = getFile()) |
637 | return F->getFilename(); |
638 | return "" ; |
639 | } |
640 | |
641 | StringRef DIScope::getDirectory() const { |
642 | if (auto *F = getFile()) |
643 | return F->getDirectory(); |
644 | return "" ; |
645 | } |
646 | |
647 | Optional<StringRef> DIScope::getSource() const { |
648 | if (auto *F = getFile()) |
649 | return F->getSource(); |
650 | return None; |
651 | } |
652 | |
653 | /// Base class for types. |
654 | /// |
655 | /// TODO: Remove the hardcoded name and context, since many types don't use |
656 | /// them. |
657 | /// TODO: Split up flags. |
658 | class DIType : public DIScope { |
659 | unsigned Line; |
660 | DIFlags Flags; |
661 | uint64_t SizeInBits; |
662 | uint64_t OffsetInBits; |
663 | uint32_t AlignInBits; |
664 | |
665 | protected: |
666 | DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, |
667 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, |
668 | uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops) |
669 | : DIScope(C, ID, Storage, Tag, Ops) { |
670 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); |
671 | } |
672 | ~DIType() = default; |
673 | |
674 | void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, |
675 | uint64_t OffsetInBits, DIFlags Flags) { |
676 | this->Line = Line; |
677 | this->Flags = Flags; |
678 | this->SizeInBits = SizeInBits; |
679 | this->AlignInBits = AlignInBits; |
680 | this->OffsetInBits = OffsetInBits; |
681 | } |
682 | |
683 | /// Change fields in place. |
684 | void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, |
685 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { |
686 | assert(isDistinct() && "Only distinct nodes can mutate" ); |
687 | setTag(Tag); |
688 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); |
689 | } |
690 | |
691 | public: |
692 | TempDIType clone() const { |
693 | return TempDIType(cast<DIType>(MDNode::clone().release())); |
694 | } |
695 | |
696 | unsigned getLine() const { return Line; } |
697 | uint64_t getSizeInBits() const { return SizeInBits; } |
698 | uint32_t getAlignInBits() const { return AlignInBits; } |
699 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } |
700 | uint64_t getOffsetInBits() const { return OffsetInBits; } |
701 | DIFlags getFlags() const { return Flags; } |
702 | |
703 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } |
704 | StringRef getName() const { return getStringOperand(2); } |
705 | |
706 | |
707 | Metadata *getRawScope() const { return getOperand(1); } |
708 | MDString *getRawName() const { return getOperandAs<MDString>(2); } |
709 | |
710 | /// Returns a new temporary DIType with updated Flags |
711 | TempDIType cloneWithFlags(DIFlags NewFlags) const { |
712 | auto NewTy = clone(); |
713 | NewTy->Flags = NewFlags; |
714 | return NewTy; |
715 | } |
716 | |
717 | bool isPrivate() const { |
718 | return (getFlags() & FlagAccessibility) == FlagPrivate; |
719 | } |
720 | bool isProtected() const { |
721 | return (getFlags() & FlagAccessibility) == FlagProtected; |
722 | } |
723 | bool isPublic() const { |
724 | return (getFlags() & FlagAccessibility) == FlagPublic; |
725 | } |
726 | bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } |
727 | bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } |
728 | bool isVirtual() const { return getFlags() & FlagVirtual; } |
729 | bool isArtificial() const { return getFlags() & FlagArtificial; } |
730 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } |
731 | bool isObjcClassComplete() const { |
732 | return getFlags() & FlagObjcClassComplete; |
733 | } |
734 | bool isVector() const { return getFlags() & FlagVector; } |
735 | bool isBitField() const { return getFlags() & FlagBitField; } |
736 | bool isStaticMember() const { return getFlags() & FlagStaticMember; } |
737 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } |
738 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } |
739 | bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } |
740 | bool isTypePassByReference() const { |
741 | return getFlags() & FlagTypePassByReference; |
742 | } |
743 | bool isBigEndian() const { return getFlags() & FlagBigEndian; } |
744 | bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } |
745 | bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } |
746 | |
747 | static bool classof(const Metadata *MD) { |
748 | switch (MD->getMetadataID()) { |
749 | default: |
750 | return false; |
751 | case DIBasicTypeKind: |
752 | case DIStringTypeKind: |
753 | case DIDerivedTypeKind: |
754 | case DICompositeTypeKind: |
755 | case DISubroutineTypeKind: |
756 | return true; |
757 | } |
758 | } |
759 | }; |
760 | |
761 | /// Basic type, like 'int' or 'float'. |
762 | /// |
763 | /// TODO: Split out DW_TAG_unspecified_type. |
764 | /// TODO: Drop unused accessors. |
765 | class DIBasicType : public DIType { |
766 | friend class LLVMContextImpl; |
767 | friend class MDNode; |
768 | |
769 | unsigned Encoding; |
770 | |
771 | DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, |
772 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, |
773 | DIFlags Flags, ArrayRef<Metadata *> Ops) |
774 | : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, |
775 | Flags, Ops), |
776 | Encoding(Encoding) {} |
777 | ~DIBasicType() = default; |
778 | |
779 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, |
780 | StringRef Name, uint64_t SizeInBits, |
781 | uint32_t AlignInBits, unsigned Encoding, |
782 | DIFlags Flags, StorageType Storage, |
783 | bool ShouldCreate = true) { |
784 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), |
785 | SizeInBits, AlignInBits, Encoding, Flags, Storage, |
786 | ShouldCreate); |
787 | } |
788 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, |
789 | MDString *Name, uint64_t SizeInBits, |
790 | uint32_t AlignInBits, unsigned Encoding, |
791 | DIFlags Flags, StorageType Storage, |
792 | bool ShouldCreate = true); |
793 | |
794 | TempDIBasicType cloneImpl() const { |
795 | return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), |
796 | getAlignInBits(), getEncoding(), getFlags()); |
797 | } |
798 | |
799 | public: |
800 | DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), |
801 | (Tag, Name, 0, 0, 0, FlagZero)) |
802 | DEFINE_MDNODE_GET(DIBasicType, |
803 | (unsigned Tag, StringRef Name, uint64_t SizeInBits), |
804 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) |
805 | DEFINE_MDNODE_GET(DIBasicType, |
806 | (unsigned Tag, MDString *Name, uint64_t SizeInBits), |
807 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) |
808 | DEFINE_MDNODE_GET(DIBasicType, |
809 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, |
810 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), |
811 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) |
812 | DEFINE_MDNODE_GET(DIBasicType, |
813 | (unsigned Tag, MDString *Name, uint64_t SizeInBits, |
814 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), |
815 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) |
816 | |
817 | TempDIBasicType clone() const { return cloneImpl(); } |
818 | |
819 | unsigned getEncoding() const { return Encoding; } |
820 | |
821 | enum class Signedness { Signed, Unsigned }; |
822 | |
823 | /// Return the signedness of this type, or None if this type is neither |
824 | /// signed nor unsigned. |
825 | Optional<Signedness> getSignedness() const; |
826 | |
827 | static bool classof(const Metadata *MD) { |
828 | return MD->getMetadataID() == DIBasicTypeKind; |
829 | } |
830 | }; |
831 | |
832 | /// String type, Fortran CHARACTER(n) |
833 | class DIStringType : public DIType { |
834 | friend class LLVMContextImpl; |
835 | friend class MDNode; |
836 | |
837 | unsigned Encoding; |
838 | |
839 | DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, |
840 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, |
841 | ArrayRef<Metadata *> Ops) |
842 | : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, |
843 | FlagZero, Ops), |
844 | Encoding(Encoding) {} |
845 | ~DIStringType() = default; |
846 | |
847 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, |
848 | StringRef Name, Metadata *StringLength, |
849 | Metadata *StrLenExp, uint64_t SizeInBits, |
850 | uint32_t AlignInBits, unsigned Encoding, |
851 | StorageType Storage, bool ShouldCreate = true) { |
852 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), |
853 | StringLength, StrLenExp, SizeInBits, AlignInBits, Encoding, |
854 | Storage, ShouldCreate); |
855 | } |
856 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, |
857 | MDString *Name, Metadata *StringLength, |
858 | Metadata *StrLenExp, uint64_t SizeInBits, |
859 | uint32_t AlignInBits, unsigned Encoding, |
860 | StorageType Storage, bool ShouldCreate = true); |
861 | |
862 | TempDIStringType cloneImpl() const { |
863 | return getTemporary(getContext(), getTag(), getRawName(), |
864 | getRawStringLength(), getRawStringLengthExp(), |
865 | getSizeInBits(), getAlignInBits(), getEncoding()); |
866 | } |
867 | |
868 | public: |
869 | DEFINE_MDNODE_GET(DIStringType, |
870 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, |
871 | uint32_t AlignInBits), |
872 | (Tag, Name, nullptr, nullptr, SizeInBits, AlignInBits, 0)) |
873 | DEFINE_MDNODE_GET(DIStringType, |
874 | (unsigned Tag, MDString *Name, Metadata *StringLength, |
875 | Metadata *StringLengthExp, uint64_t SizeInBits, |
876 | uint32_t AlignInBits, unsigned Encoding), |
877 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, |
878 | AlignInBits, Encoding)) |
879 | DEFINE_MDNODE_GET(DIStringType, |
880 | (unsigned Tag, StringRef Name, Metadata *StringLength, |
881 | Metadata *StringLengthExp, uint64_t SizeInBits, |
882 | uint32_t AlignInBits, unsigned Encoding), |
883 | (Tag, Name, StringLength, StringLengthExp, SizeInBits, |
884 | AlignInBits, Encoding)) |
885 | |
886 | TempDIStringType clone() const { return cloneImpl(); } |
887 | |
888 | static bool classof(const Metadata *MD) { |
889 | return MD->getMetadataID() == DIStringTypeKind; |
890 | } |
891 | |
892 | DIVariable *getStringLength() const { |
893 | return cast_or_null<DIVariable>(getRawStringLength()); |
894 | } |
895 | |
896 | DIExpression *getStringLengthExp() const { |
897 | return cast_or_null<DIExpression>(getRawStringLengthExp()); |
898 | } |
899 | |
900 | unsigned getEncoding() const { return Encoding; } |
901 | |
902 | Metadata *getRawStringLength() const { return getOperand(3); } |
903 | |
904 | Metadata *getRawStringLengthExp() const { return getOperand(4); } |
905 | }; |
906 | |
907 | /// Derived types. |
908 | /// |
909 | /// This includes qualified types, pointers, references, friends, typedefs, and |
910 | /// class members. |
911 | /// |
912 | /// TODO: Split out members (inheritance, fields, methods, etc.). |
913 | class DIDerivedType : public DIType { |
914 | friend class LLVMContextImpl; |
915 | friend class MDNode; |
916 | |
917 | /// The DWARF address space of the memory pointed to or referenced by a |
918 | /// pointer or reference type respectively. |
919 | Optional<unsigned> DWARFAddressSpace; |
920 | |
921 | DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, |
922 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, |
923 | uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, |
924 | DIFlags Flags, ArrayRef<Metadata *> Ops) |
925 | : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, |
926 | AlignInBits, OffsetInBits, Flags, Ops), |
927 | DWARFAddressSpace(DWARFAddressSpace) {} |
928 | ~DIDerivedType() = default; |
929 | |
930 | static DIDerivedType * |
931 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, |
932 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, |
933 | uint32_t AlignInBits, uint64_t OffsetInBits, |
934 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, |
935 | Metadata *, StorageType Storage, bool ShouldCreate = true) { |
936 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, |
937 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, |
938 | DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); |
939 | } |
940 | static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, |
941 | MDString *Name, Metadata *File, unsigned Line, |
942 | Metadata *Scope, Metadata *BaseType, |
943 | uint64_t SizeInBits, uint32_t AlignInBits, |
944 | uint64_t OffsetInBits, |
945 | Optional<unsigned> DWARFAddressSpace, |
946 | DIFlags Flags, Metadata *, |
947 | StorageType Storage, bool ShouldCreate = true); |
948 | |
949 | TempDIDerivedType cloneImpl() const { |
950 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), |
951 | getScope(), getBaseType(), getSizeInBits(), |
952 | getAlignInBits(), getOffsetInBits(), |
953 | getDWARFAddressSpace(), getFlags(), getExtraData()); |
954 | } |
955 | |
956 | public: |
957 | DEFINE_MDNODE_GET(DIDerivedType, |
958 | (unsigned Tag, MDString *Name, Metadata *File, |
959 | unsigned Line, Metadata *Scope, Metadata *BaseType, |
960 | uint64_t SizeInBits, uint32_t AlignInBits, |
961 | uint64_t OffsetInBits, |
962 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, |
963 | Metadata * = nullptr), |
964 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, |
965 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, |
966 | ExtraData)) |
967 | DEFINE_MDNODE_GET(DIDerivedType, |
968 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, |
969 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, |
970 | uint32_t AlignInBits, uint64_t OffsetInBits, |
971 | Optional<unsigned> DWARFAddressSpace, DIFlags Flags, |
972 | Metadata * = nullptr), |
973 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, |
974 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, |
975 | ExtraData)) |
976 | |
977 | TempDIDerivedType clone() const { return cloneImpl(); } |
978 | |
979 | /// Get the base type this is derived from. |
980 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } |
981 | Metadata *getRawBaseType() const { return getOperand(3); } |
982 | |
983 | /// \returns The DWARF address space of the memory pointed to or referenced by |
984 | /// a pointer or reference type respectively. |
985 | Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; } |
986 | |
987 | /// Get extra data associated with this derived type. |
988 | /// |
989 | /// Class type for pointer-to-members, objective-c property node for ivars, |
990 | /// global constant wrapper for static members, or virtual base pointer offset |
991 | /// for inheritance. |
992 | /// |
993 | /// TODO: Separate out types that need this extra operand: pointer-to-member |
994 | /// types and member fields (static members and ivars). |
995 | Metadata *() const { return getRawExtraData(); } |
996 | Metadata *() const { return getOperand(4); } |
997 | |
998 | /// Get casted version of extra data. |
999 | /// @{ |
1000 | DIType *getClassType() const { |
1001 | assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); |
1002 | return cast_or_null<DIType>(getExtraData()); |
1003 | } |
1004 | |
1005 | DIObjCProperty *getObjCProperty() const { |
1006 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); |
1007 | } |
1008 | |
1009 | uint32_t getVBPtrOffset() const { |
1010 | assert(getTag() == dwarf::DW_TAG_inheritance); |
1011 | if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) |
1012 | if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) |
1013 | return static_cast<uint32_t>(CI->getZExtValue()); |
1014 | return 0; |
1015 | } |
1016 | |
1017 | Constant *getStorageOffsetInBits() const { |
1018 | assert(getTag() == dwarf::DW_TAG_member && isBitField()); |
1019 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) |
1020 | return C->getValue(); |
1021 | return nullptr; |
1022 | } |
1023 | |
1024 | Constant *getConstant() const { |
1025 | assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); |
1026 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) |
1027 | return C->getValue(); |
1028 | return nullptr; |
1029 | } |
1030 | Constant *getDiscriminantValue() const { |
1031 | assert(getTag() == dwarf::DW_TAG_member && !isStaticMember()); |
1032 | if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) |
1033 | return C->getValue(); |
1034 | return nullptr; |
1035 | } |
1036 | /// @} |
1037 | |
1038 | static bool classof(const Metadata *MD) { |
1039 | return MD->getMetadataID() == DIDerivedTypeKind; |
1040 | } |
1041 | }; |
1042 | |
1043 | /// Composite types. |
1044 | /// |
1045 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). |
1046 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. |
1047 | class DICompositeType : public DIType { |
1048 | friend class LLVMContextImpl; |
1049 | friend class MDNode; |
1050 | |
1051 | unsigned RuntimeLang; |
1052 | |
1053 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, |
1054 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, |
1055 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, |
1056 | ArrayRef<Metadata *> Ops) |
1057 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, |
1058 | AlignInBits, OffsetInBits, Flags, Ops), |
1059 | RuntimeLang(RuntimeLang) {} |
1060 | ~DICompositeType() = default; |
1061 | |
1062 | /// Change fields in place. |
1063 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, |
1064 | uint64_t SizeInBits, uint32_t AlignInBits, |
1065 | uint64_t OffsetInBits, DIFlags Flags) { |
1066 | assert(isDistinct() && "Only distinct nodes can mutate" ); |
1067 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate" ); |
1068 | this->RuntimeLang = RuntimeLang; |
1069 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); |
1070 | } |
1071 | |
1072 | static DICompositeType * |
1073 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, |
1074 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, |
1075 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, |
1076 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, |
1077 | DITemplateParameterArray TemplateParams, StringRef Identifier, |
1078 | DIDerivedType *Discriminator, Metadata *DataLocation, |
1079 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, |
1080 | StorageType Storage, bool ShouldCreate = true) { |
1081 | return getImpl( |
1082 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, |
1083 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), |
1084 | RuntimeLang, VTableHolder, TemplateParams.get(), |
1085 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, |
1086 | Associated, Allocated, Rank, Storage, ShouldCreate); |
1087 | } |
1088 | static DICompositeType * |
1089 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, |
1090 | unsigned Line, Metadata *Scope, Metadata *BaseType, |
1091 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, |
1092 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, |
1093 | Metadata *VTableHolder, Metadata *TemplateParams, |
1094 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, |
1095 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, |
1096 | StorageType Storage, bool ShouldCreate = true); |
1097 | |
1098 | TempDICompositeType cloneImpl() const { |
1099 | return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), |
1100 | getScope(), getBaseType(), getSizeInBits(), |
1101 | getAlignInBits(), getOffsetInBits(), getFlags(), |
1102 | getElements(), getRuntimeLang(), getVTableHolder(), |
1103 | getTemplateParams(), getIdentifier(), |
1104 | getDiscriminator(), getRawDataLocation(), |
1105 | getRawAssociated(), getRawAllocated(), getRawRank()); |
1106 | } |
1107 | |
1108 | public: |
1109 | DEFINE_MDNODE_GET( |
1110 | DICompositeType, |
1111 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, |
1112 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, |
1113 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, |
1114 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, |
1115 | DITemplateParameterArray TemplateParams = nullptr, |
1116 | StringRef Identifier = "" , DIDerivedType *Discriminator = nullptr, |
1117 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, |
1118 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr), |
1119 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, |
1120 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, |
1121 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) |
1122 | DEFINE_MDNODE_GET( |
1123 | DICompositeType, |
1124 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, |
1125 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, |
1126 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, |
1127 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, |
1128 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, |
1129 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, |
1130 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, |
1131 | Metadata *Rank = nullptr), |
1132 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, |
1133 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, |
1134 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank)) |
1135 | |
1136 | TempDICompositeType clone() const { return cloneImpl(); } |
1137 | |
1138 | /// Get a DICompositeType with the given ODR identifier. |
1139 | /// |
1140 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped |
1141 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates |
1142 | /// a new node. |
1143 | /// |
1144 | /// Else, returns \c nullptr. |
1145 | static DICompositeType * |
1146 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, |
1147 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, |
1148 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, |
1149 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, |
1150 | unsigned RuntimeLang, Metadata *VTableHolder, |
1151 | Metadata *TemplateParams, Metadata *Discriminator, |
1152 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, |
1153 | Metadata *Rank); |
1154 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, |
1155 | MDString &Identifier); |
1156 | |
1157 | /// Build a DICompositeType with the given ODR identifier. |
1158 | /// |
1159 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If |
1160 | /// it doesn't exist, creates a new one. If it does exist and \a |
1161 | /// isForwardDecl(), and the new arguments would be a definition, mutates the |
1162 | /// the type in place. In either case, returns the type. |
1163 | /// |
1164 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns |
1165 | /// nullptr. |
1166 | static DICompositeType * |
1167 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, |
1168 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, |
1169 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, |
1170 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, |
1171 | unsigned RuntimeLang, Metadata *VTableHolder, |
1172 | Metadata *TemplateParams, Metadata *Discriminator, |
1173 | Metadata *DataLocation, Metadata *Associated, |
1174 | Metadata *Allocated, Metadata *Rank); |
1175 | |
1176 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } |
1177 | DINodeArray getElements() const { |
1178 | return cast_or_null<MDTuple>(getRawElements()); |
1179 | } |
1180 | DIType *getVTableHolder() const { |
1181 | return cast_or_null<DIType>(getRawVTableHolder()); |
1182 | } |
1183 | DITemplateParameterArray getTemplateParams() const { |
1184 | return cast_or_null<MDTuple>(getRawTemplateParams()); |
1185 | } |
1186 | StringRef getIdentifier() const { return getStringOperand(7); } |
1187 | unsigned getRuntimeLang() const { return RuntimeLang; } |
1188 | |
1189 | Metadata *getRawBaseType() const { return getOperand(3); } |
1190 | Metadata *getRawElements() const { return getOperand(4); } |
1191 | Metadata *getRawVTableHolder() const { return getOperand(5); } |
1192 | Metadata *getRawTemplateParams() const { return getOperand(6); } |
1193 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } |
1194 | Metadata *getRawDiscriminator() const { return getOperand(8); } |
1195 | DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); } |
1196 | Metadata *getRawDataLocation() const { return getOperand(9); } |
1197 | DIVariable *getDataLocation() const { |
1198 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); |
1199 | } |
1200 | DIExpression *getDataLocationExp() const { |
1201 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); |
1202 | } |
1203 | Metadata *getRawAssociated() const { return getOperand(10); } |
1204 | DIVariable *getAssociated() const { |
1205 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); |
1206 | } |
1207 | DIExpression *getAssociatedExp() const { |
1208 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); |
1209 | } |
1210 | Metadata *getRawAllocated() const { return getOperand(11); } |
1211 | DIVariable *getAllocated() const { |
1212 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); |
1213 | } |
1214 | DIExpression *getAllocatedExp() const { |
1215 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); |
1216 | } |
1217 | Metadata *getRawRank() const { return getOperand(12); } |
1218 | ConstantInt *getRankConst() const { |
1219 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) |
1220 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); |
1221 | return nullptr; |
1222 | } |
1223 | DIExpression *getRankExp() const { |
1224 | return dyn_cast_or_null<DIExpression>(getRawRank()); |
1225 | } |
1226 | |
1227 | /// Replace operands. |
1228 | /// |
1229 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision |
1230 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track |
1231 | /// of its movement if necessary. |
1232 | /// @{ |
1233 | void replaceElements(DINodeArray Elements) { |
1234 | #ifndef NDEBUG |
1235 | for (DINode *Op : getElements()) |
1236 | assert(is_contained(Elements->operands(), Op) && |
1237 | "Lost a member during member list replacement" ); |
1238 | #endif |
1239 | replaceOperandWith(4, Elements.get()); |
1240 | } |
1241 | |
1242 | void replaceVTableHolder(DIType *VTableHolder) { |
1243 | replaceOperandWith(5, VTableHolder); |
1244 | } |
1245 | |
1246 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { |
1247 | replaceOperandWith(6, TemplateParams.get()); |
1248 | } |
1249 | /// @} |
1250 | |
1251 | static bool classof(const Metadata *MD) { |
1252 | return MD->getMetadataID() == DICompositeTypeKind; |
1253 | } |
1254 | }; |
1255 | |
1256 | /// Type array for a subprogram. |
1257 | /// |
1258 | /// TODO: Fold the array of types in directly as operands. |
1259 | class DISubroutineType : public DIType { |
1260 | friend class LLVMContextImpl; |
1261 | friend class MDNode; |
1262 | |
1263 | /// The calling convention used with DW_AT_calling_convention. Actually of |
1264 | /// type dwarf::CallingConvention. |
1265 | uint8_t CC; |
1266 | |
1267 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, |
1268 | uint8_t CC, ArrayRef<Metadata *> Ops) |
1269 | : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, |
1270 | 0, 0, 0, 0, Flags, Ops), |
1271 | CC(CC) {} |
1272 | ~DISubroutineType() = default; |
1273 | |
1274 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, |
1275 | uint8_t CC, DITypeRefArray TypeArray, |
1276 | StorageType Storage, |
1277 | bool ShouldCreate = true) { |
1278 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); |
1279 | } |
1280 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, |
1281 | uint8_t CC, Metadata *TypeArray, |
1282 | StorageType Storage, |
1283 | bool ShouldCreate = true); |
1284 | |
1285 | TempDISubroutineType cloneImpl() const { |
1286 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); |
1287 | } |
1288 | |
1289 | public: |
1290 | DEFINE_MDNODE_GET(DISubroutineType, |
1291 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), |
1292 | (Flags, CC, TypeArray)) |
1293 | DEFINE_MDNODE_GET(DISubroutineType, |
1294 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), |
1295 | (Flags, CC, TypeArray)) |
1296 | |
1297 | TempDISubroutineType clone() const { return cloneImpl(); } |
1298 | |
1299 | uint8_t getCC() const { return CC; } |
1300 | |
1301 | DITypeRefArray getTypeArray() const { |
1302 | return cast_or_null<MDTuple>(getRawTypeArray()); |
1303 | } |
1304 | |
1305 | Metadata *getRawTypeArray() const { return getOperand(3); } |
1306 | |
1307 | static bool classof(const Metadata *MD) { |
1308 | return MD->getMetadataID() == DISubroutineTypeKind; |
1309 | } |
1310 | }; |
1311 | |
1312 | /// Compile unit. |
1313 | class DICompileUnit : public DIScope { |
1314 | friend class LLVMContextImpl; |
1315 | friend class MDNode; |
1316 | |
1317 | public: |
1318 | enum DebugEmissionKind : unsigned { |
1319 | NoDebug = 0, |
1320 | FullDebug, |
1321 | LineTablesOnly, |
1322 | DebugDirectivesOnly, |
1323 | LastEmissionKind = DebugDirectivesOnly |
1324 | }; |
1325 | |
1326 | enum class DebugNameTableKind : unsigned { |
1327 | Default = 0, |
1328 | |
---|