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