LLVM 22.0.0git
LLVMContextImpl.h
Go to the documentation of this file.
1//===- LLVMContextImpl.h - The LLVMContextImpl opaque class -----*- 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// This file declares LLVMContextImpl, the opaque implementation
10// of LLVMContext.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H
15#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H
16
17#include "ConstantsContext.h"
18#include "llvm/ADT/APFloat.h"
19#include "llvm/ADT/APInt.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/DenseSet.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/ADT/Hashing.h"
26#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/StringMap.h"
31#include "llvm/IR/Constants.h"
34#include "llvm/IR/LLVMContext.h"
35#include "llvm/IR/Metadata.h"
36#include "llvm/IR/Module.h"
38#include "llvm/IR/Type.h"
39#include "llvm/IR/Value.h"
43#include <algorithm>
44#include <cassert>
45#include <cstddef>
46#include <cstdint>
47#include <memory>
48#include <optional>
49#include <string>
50#include <utility>
51#include <vector>
52
53namespace llvm {
54
55class AttributeImpl;
56class AttributeListImpl;
57class AttributeSetNode;
58class BasicBlock;
59class ConstantRangeAttributeImpl;
60class ConstantRangeListAttributeImpl;
61struct DiagnosticHandler;
62class DbgMarker;
63class ElementCount;
64class Function;
65class GlobalObject;
66class GlobalValue;
67class InlineAsm;
68class LLVMRemarkStreamer;
69class OptPassGate;
70namespace remarks {
71class RemarkStreamer;
72}
73template <typename T> class StringMapEntry;
74class StringRef;
75class TypedPointerType;
76class ValueHandleBase;
77
78template <> struct DenseMapInfo<APFloat> {
79 static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus(), 1); }
80 static inline APFloat getTombstoneKey() {
81 return APFloat(APFloat::Bogus(), 2);
82 }
83
84 static unsigned getHashValue(const APFloat &Key) {
85 return static_cast<unsigned>(hash_value(Key));
86 }
87
88 static bool isEqual(const APFloat &LHS, const APFloat &RHS) {
89 return LHS.bitwiseIsEqual(RHS);
90 }
91};
92
94 struct KeyTy {
97
98 KeyTy(const ArrayRef<Type *> &E, bool P) : ETypes(E), isPacked(P) {}
99
100 KeyTy(const StructType *ST)
101 : ETypes(ST->elements()), isPacked(ST->isPacked()) {}
102
103 bool operator==(const KeyTy &that) const {
104 if (isPacked != that.isPacked)
105 return false;
106 if (ETypes != that.ETypes)
107 return false;
108 return true;
109 }
110 bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
111 };
112
113 static inline StructType *getEmptyKey() {
115 }
116
117 static inline StructType *getTombstoneKey() {
119 }
120
121 static unsigned getHashValue(const KeyTy &Key) {
122 return hash_combine(hash_combine_range(Key.ETypes), Key.isPacked);
123 }
124
125 static unsigned getHashValue(const StructType *ST) {
126 return getHashValue(KeyTy(ST));
127 }
128
129 static bool isEqual(const KeyTy &LHS, const StructType *RHS) {
130 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
131 return false;
132 return LHS == KeyTy(RHS);
133 }
134
135 static bool isEqual(const StructType *LHS, const StructType *RHS) {
136 return LHS == RHS;
137 }
138};
139
141 struct KeyTy {
145
146 KeyTy(const Type *R, const ArrayRef<Type *> &P, bool V)
147 : ReturnType(R), Params(P), isVarArg(V) {}
149 : ReturnType(FT->getReturnType()), Params(FT->params()),
150 isVarArg(FT->isVarArg()) {}
151
152 bool operator==(const KeyTy &that) const {
153 if (ReturnType != that.ReturnType)
154 return false;
155 if (isVarArg != that.isVarArg)
156 return false;
157 if (Params != that.Params)
158 return false;
159 return true;
160 }
161 bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
162 };
163
164 static inline FunctionType *getEmptyKey() {
166 }
167
168 static inline FunctionType *getTombstoneKey() {
170 }
171
172 static unsigned getHashValue(const KeyTy &Key) {
173 return hash_combine(Key.ReturnType, hash_combine_range(Key.Params),
174 Key.isVarArg);
175 }
176
177 static unsigned getHashValue(const FunctionType *FT) {
178 return getHashValue(KeyTy(FT));
179 }
180
181 static bool isEqual(const KeyTy &LHS, const FunctionType *RHS) {
182 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
183 return false;
184 return LHS == KeyTy(RHS);
185 }
186
187 static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) {
188 return LHS == RHS;
189 }
190};
191
193 struct KeyTy {
197
199 : Name(N), TypeParams(TP), IntParams(IP) {}
201 : Name(TT->getName()), TypeParams(TT->type_params()),
202 IntParams(TT->int_params()) {}
203
204 bool operator==(const KeyTy &that) const {
205 return Name == that.Name && TypeParams == that.TypeParams &&
206 IntParams == that.IntParams;
207 }
208 bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
209 };
210
211 static inline TargetExtType *getEmptyKey() {
213 }
214
217 }
218
219 static unsigned getHashValue(const KeyTy &Key) {
220 return hash_combine(Key.Name, hash_combine_range(Key.TypeParams),
221 hash_combine_range(Key.IntParams));
222 }
223
224 static unsigned getHashValue(const TargetExtType *FT) {
225 return getHashValue(KeyTy(FT));
226 }
227
228 static bool isEqual(const KeyTy &LHS, const TargetExtType *RHS) {
229 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
230 return false;
231 return LHS == KeyTy(RHS);
232 }
233
234 static bool isEqual(const TargetExtType *LHS, const TargetExtType *RHS) {
235 return LHS == RHS;
236 }
237};
238
239/// Structure for hashing arbitrary MDNode operands.
243 unsigned Hash;
244
245protected:
247 : RawOps(Ops), Hash(calculateHash(Ops)) {}
248
249 template <class NodeTy>
250 MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0)
251 : Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
252
253 template <class NodeTy>
254 bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
255 if (getHash() != RHS->getHash())
256 return false;
257
258 assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
259 return RawOps.empty() ? compareOps(Ops, RHS, Offset)
260 : compareOps(RawOps, RHS, Offset);
261 }
262
263 static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
264
265private:
266 template <class T>
267 static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
268 if (Ops.size() != RHS->getNumOperands() - Offset)
269 return false;
270 return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
271 }
272
273 static unsigned calculateHash(ArrayRef<Metadata *> Ops);
274
275public:
276 unsigned getHash() const { return Hash; }
277};
278
279template <class NodeTy> struct MDNodeKeyImpl;
280
281/// Configuration point for MDNodeInfo::isEqual().
282template <class NodeTy> struct MDNodeSubsetEqualImpl {
284
285 static bool isSubsetEqual(const KeyTy &LHS, const NodeTy *RHS) {
286 return false;
287 }
288
289 static bool isSubsetEqual(const NodeTy *LHS, const NodeTy *RHS) {
290 return false;
291 }
292};
293
294/// DenseMapInfo for MDTuple.
295///
296/// Note that we don't need the is-function-local bit, since that's implicit in
297/// the operands.
298template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {
301
302 bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); }
303
304 unsigned getHashValue() const { return getHash(); }
305
306 static unsigned calculateHash(MDTuple *N) {
308 }
309};
310
311/// DenseMapInfo for DILocation.
312template <> struct MDNodeKeyImpl<DILocation> {
317 unsigned Line;
320
321 MDNodeKeyImpl(unsigned Line, uint16_t Column, Metadata *Scope,
322 Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup,
323 uint8_t AtomRank)
324 : Scope(Scope), InlinedAt(InlinedAt), AtomGroup(AtomGroup),
325 AtomRank(AtomRank), Line(Line), Column(Column),
326 ImplicitCode(ImplicitCode) {}
327
329 : Scope(L->getRawScope()), InlinedAt(L->getRawInlinedAt()),
330 AtomGroup(L->getAtomGroup()), AtomRank(L->getAtomRank()),
331 Line(L->getLine()), Column(L->getColumn()),
332 ImplicitCode(L->isImplicitCode()) {}
333
334 bool isKeyOf(const DILocation *RHS) const {
335 return Line == RHS->getLine() && Column == RHS->getColumn() &&
336 Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() &&
337 ImplicitCode == RHS->isImplicitCode() &&
338 AtomGroup == RHS->getAtomGroup() && AtomRank == RHS->getAtomRank();
339 }
340
341 unsigned getHashValue() const {
342 // Hashing AtomGroup and AtomRank substantially impacts performance whether
343 // Key Instructions is enabled or not. We can't detect whether it's enabled
344 // here cheaply; avoiding hashing zero values is a good approximation. This
345 // affects Key Instruction builds too, but any potential costs incurred by
346 // messing with the hash distribution* appear to still be massively
347 // outweighed by the overall compile time savings by performing this check.
348 // * (hash_combine(x) != hash_combine(x, 0))
349 if (AtomGroup || AtomRank)
350 return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode,
351 AtomGroup, (uint8_t)AtomRank);
352 return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode);
353 }
354};
355
356/// DenseMapInfo for GenericDINode.
358 unsigned Tag;
360
361 MDNodeKeyImpl(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)
362 : MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
364 : MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getRawHeader()) {}
365
366 bool isKeyOf(const GenericDINode *RHS) const {
367 return Tag == RHS->getTag() && Header == RHS->getRawHeader() &&
368 compareOps(RHS, 1);
369 }
370
371 unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); }
372
373 static unsigned calculateHash(GenericDINode *N) {
375 }
376};
377
378template <> struct MDNodeKeyImpl<DISubrange> {
383
384 MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,
385 Metadata *Stride)
386 : CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),
387 Stride(Stride) {}
389 : CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),
390 UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}
391
392 bool isKeyOf(const DISubrange *RHS) const {
393 auto BoundsEqual = [=](Metadata *Node1, Metadata *Node2) -> bool {
394 if (Node1 == Node2)
395 return true;
396
397 ConstantAsMetadata *MD1 = dyn_cast_or_null<ConstantAsMetadata>(Node1);
398 ConstantAsMetadata *MD2 = dyn_cast_or_null<ConstantAsMetadata>(Node2);
399 if (MD1 && MD2) {
400 ConstantInt *CV1 = cast<ConstantInt>(MD1->getValue());
401 ConstantInt *CV2 = cast<ConstantInt>(MD2->getValue());
402 if (CV1->getSExtValue() == CV2->getSExtValue())
403 return true;
404 }
405 return false;
406 };
407
408 return BoundsEqual(CountNode, RHS->getRawCountNode()) &&
409 BoundsEqual(LowerBound, RHS->getRawLowerBound()) &&
410 BoundsEqual(UpperBound, RHS->getRawUpperBound()) &&
411 BoundsEqual(Stride, RHS->getRawStride());
412 }
413
414 unsigned getHashValue() const {
415 if (CountNode)
416 if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
417 return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
418 LowerBound, UpperBound, Stride);
419 return hash_combine(CountNode, LowerBound, UpperBound, Stride);
420 }
421};
422
423template <> struct MDNodeKeyImpl<DIGenericSubrange> {
428
429 MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,
430 Metadata *Stride)
431 : CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),
432 Stride(Stride) {}
434 : CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),
435 UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}
436
437 bool isKeyOf(const DIGenericSubrange *RHS) const {
438 return (CountNode == RHS->getRawCountNode()) &&
439 (LowerBound == RHS->getRawLowerBound()) &&
440 (UpperBound == RHS->getRawUpperBound()) &&
441 (Stride == RHS->getRawStride());
442 }
443
444 unsigned getHashValue() const {
445 auto *MD = dyn_cast_or_null<ConstantAsMetadata>(CountNode);
446 if (CountNode && MD)
447 return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
448 LowerBound, UpperBound, Stride);
449 return hash_combine(CountNode, LowerBound, UpperBound, Stride);
450 }
451};
452
453template <> struct MDNodeKeyImpl<DIEnumerator> {
457
459 : Value(std::move(Value)), Name(Name), IsUnsigned(IsUnsigned) {}
460 MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
461 : Value(APInt(64, Value, !IsUnsigned)), Name(Name),
462 IsUnsigned(IsUnsigned) {}
464 : Value(N->getValue()), Name(N->getRawName()),
465 IsUnsigned(N->isUnsigned()) {}
466
467 bool isKeyOf(const DIEnumerator *RHS) const {
468 return Value.getBitWidth() == RHS->getValue().getBitWidth() &&
469 Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&
470 Name == RHS->getRawName();
471 }
472
473 unsigned getHashValue() const { return hash_combine(Value, Name); }
474};
475
476template <> struct MDNodeKeyImpl<DIBasicType> {
477 unsigned Tag;
481 unsigned Encoding;
483 unsigned Flags;
484
485 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *SizeInBits,
486 uint32_t AlignInBits, unsigned Encoding,
487 uint32_t NumExtraInhabitants, unsigned Flags)
488 : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
489 Encoding(Encoding), NumExtraInhabitants(NumExtraInhabitants),
490 Flags(Flags) {}
492 : Tag(N->getTag()), Name(N->getRawName()),
493 SizeInBits(N->getRawSizeInBits()), AlignInBits(N->getAlignInBits()),
494 Encoding(N->getEncoding()),
495 NumExtraInhabitants(N->getNumExtraInhabitants()), Flags(N->getFlags()) {
496 }
497
498 bool isKeyOf(const DIBasicType *RHS) const {
499 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
500 SizeInBits == RHS->getRawSizeInBits() &&
501 AlignInBits == RHS->getAlignInBits() &&
502 Encoding == RHS->getEncoding() &&
503 NumExtraInhabitants == RHS->getNumExtraInhabitants() &&
504 Flags == RHS->getFlags();
505 }
506
507 unsigned getHashValue() const {
508 return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
509 }
510};
511
512template <> struct MDNodeKeyImpl<DIFixedPointType> {
513 unsigned Tag;
517 unsigned Encoding;
518 unsigned Flags;
519 unsigned Kind;
523
524 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *SizeInBits,
525 uint32_t AlignInBits, unsigned Encoding, unsigned Flags,
526 unsigned Kind, int Factor, APInt Numerator, APInt Denominator)
527 : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
528 Encoding(Encoding), Flags(Flags), Kind(Kind), Factor(Factor),
529 Numerator(Numerator), Denominator(Denominator) {}
531 : Tag(N->getTag()), Name(N->getRawName()),
532 SizeInBits(N->getRawSizeInBits()), AlignInBits(N->getAlignInBits()),
533 Encoding(N->getEncoding()), Flags(N->getFlags()), Kind(N->getKind()),
534 Factor(N->getFactorRaw()), Numerator(N->getNumeratorRaw()),
535 Denominator(N->getDenominatorRaw()) {}
536
537 bool isKeyOf(const DIFixedPointType *RHS) const {
538 return Name == RHS->getRawName() && SizeInBits == RHS->getRawSizeInBits() &&
539 AlignInBits == RHS->getAlignInBits() && Kind == RHS->getKind() &&
540 (RHS->isRational() ? (Numerator == RHS->getNumerator() &&
541 Denominator == RHS->getDenominator())
542 : Factor == RHS->getFactor());
543 }
544
545 unsigned getHashValue() const {
546 return hash_combine(Name, Flags, Kind, Factor, Numerator, Denominator);
547 }
548};
549
550template <> struct MDNodeKeyImpl<DIStringType> {
551 unsigned Tag;
558 unsigned Encoding;
559
560 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength,
561 Metadata *StringLengthExp, Metadata *StringLocationExp,
562 Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding)
563 : Tag(Tag), Name(Name), StringLength(StringLength),
564 StringLengthExp(StringLengthExp), StringLocationExp(StringLocationExp),
565 SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding) {}
567 : Tag(N->getTag()), Name(N->getRawName()),
568 StringLength(N->getRawStringLength()),
569 StringLengthExp(N->getRawStringLengthExp()),
570 StringLocationExp(N->getRawStringLocationExp()),
571 SizeInBits(N->getRawSizeInBits()), AlignInBits(N->getAlignInBits()),
572 Encoding(N->getEncoding()) {}
573
574 bool isKeyOf(const DIStringType *RHS) const {
575 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
576 StringLength == RHS->getRawStringLength() &&
577 StringLengthExp == RHS->getRawStringLengthExp() &&
578 StringLocationExp == RHS->getRawStringLocationExp() &&
579 SizeInBits == RHS->getRawSizeInBits() &&
580 AlignInBits == RHS->getAlignInBits() &&
581 Encoding == RHS->getEncoding();
582 }
583 unsigned getHashValue() const {
584 // Intentionally computes the hash on a subset of the operands for
585 // performance reason. The subset has to be significant enough to avoid
586 // collision "most of the time". There is no correctness issue in case of
587 // collision because of the full check above.
588 return hash_combine(Tag, Name, StringLength, Encoding);
589 }
590};
591
592template <> struct MDNodeKeyImpl<DIDerivedType> {
593 unsigned Tag;
596 unsigned Line;
602 std::optional<unsigned> DWARFAddressSpace;
603 std::optional<DIDerivedType::PtrAuthData> PtrAuthData;
604 unsigned Flags;
607
608 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
609 Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,
610 uint32_t AlignInBits, Metadata *OffsetInBits,
611 std::optional<unsigned> DWARFAddressSpace,
612 std::optional<DIDerivedType::PtrAuthData> PtrAuthData,
613 unsigned Flags, Metadata *ExtraData, Metadata *Annotations)
614 : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
615 BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
616 AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace),
617 PtrAuthData(PtrAuthData), Flags(Flags), ExtraData(ExtraData),
620 : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
621 Line(N->getLine()), Scope(N->getRawScope()),
622 BaseType(N->getRawBaseType()), SizeInBits(N->getRawSizeInBits()),
623 OffsetInBits(N->getRawOffsetInBits()), AlignInBits(N->getAlignInBits()),
624 DWARFAddressSpace(N->getDWARFAddressSpace()),
625 PtrAuthData(N->getPtrAuthData()), Flags(N->getFlags()),
626 ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {}
627
628 bool isKeyOf(const DIDerivedType *RHS) const {
629 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
630 File == RHS->getRawFile() && Line == RHS->getLine() &&
631 Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
632 SizeInBits == RHS->getRawSizeInBits() &&
633 AlignInBits == RHS->getAlignInBits() &&
634 OffsetInBits == RHS->getRawOffsetInBits() &&
635 DWARFAddressSpace == RHS->getDWARFAddressSpace() &&
636 PtrAuthData == RHS->getPtrAuthData() && Flags == RHS->getFlags() &&
637 ExtraData == RHS->getRawExtraData() &&
638 Annotations == RHS->getRawAnnotations();
639 }
640
641 unsigned getHashValue() const {
642 // If this is a member inside an ODR type, only hash the type and the name.
643 // Otherwise the hash will be stronger than
644 // MDNodeSubsetEqualImpl::isODRMember().
645 if (Tag == dwarf::DW_TAG_member && Name)
646 if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
647 if (CT->getRawIdentifier())
648 return hash_combine(Name, Scope);
649
650 // Intentionally computes the hash on a subset of the operands for
651 // performance reason. The subset has to be significant enough to avoid
652 // collision "most of the time". There is no correctness issue in case of
653 // collision because of the full check above.
654 return hash_combine(Tag, Name, File, Line, Scope, BaseType, Flags);
655 }
656};
657
658template <> struct MDNodeKeyImpl<DISubrangeType> {
661 unsigned Line;
665 unsigned Flags;
671
672 MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
673 Metadata *SizeInBits, uint32_t AlignInBits, unsigned Flags,
674 Metadata *BaseType, Metadata *LowerBound, Metadata *UpperBound,
675 Metadata *Stride, Metadata *Bias)
676 : Name(Name), File(File), Line(Line), Scope(Scope),
677 SizeInBits(SizeInBits), AlignInBits(AlignInBits), Flags(Flags),
678 BaseType(BaseType), LowerBound(LowerBound), UpperBound(UpperBound),
679 Stride(Stride), Bias(Bias) {}
681 : Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
682 Scope(N->getRawScope()), SizeInBits(N->getRawSizeInBits()),
683 AlignInBits(N->getAlignInBits()), Flags(N->getFlags()),
684 BaseType(N->getRawBaseType()), LowerBound(N->getRawLowerBound()),
685 UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()),
686 Bias(N->getRawBias()) {}
687
688 bool isKeyOf(const DISubrangeType *RHS) const {
689 auto BoundsEqual = [=](Metadata *Node1, Metadata *Node2) -> bool {
690 if (Node1 == Node2)
691 return true;
692
693 ConstantAsMetadata *MD1 = dyn_cast_or_null<ConstantAsMetadata>(Node1);
694 ConstantAsMetadata *MD2 = dyn_cast_or_null<ConstantAsMetadata>(Node2);
695 if (MD1 && MD2) {
696 ConstantInt *CV1 = cast<ConstantInt>(MD1->getValue());
697 ConstantInt *CV2 = cast<ConstantInt>(MD2->getValue());
698 if (CV1->getSExtValue() == CV2->getSExtValue())
699 return true;
700 }
701 return false;
702 };
703
704 return Name == RHS->getRawName() && File == RHS->getRawFile() &&
705 Line == RHS->getLine() && Scope == RHS->getRawScope() &&
706 SizeInBits == RHS->getRawSizeInBits() &&
707 AlignInBits == RHS->getAlignInBits() && Flags == RHS->getFlags() &&
708 BaseType == RHS->getRawBaseType() &&
709 BoundsEqual(LowerBound, RHS->getRawLowerBound()) &&
710 BoundsEqual(UpperBound, RHS->getRawUpperBound()) &&
711 BoundsEqual(Stride, RHS->getRawStride()) &&
712 BoundsEqual(Bias, RHS->getRawBias());
713 }
714
715 unsigned getHashValue() const {
716 unsigned val = 0;
717 auto HashBound = [&](Metadata *Node) -> void {
718 ConstantAsMetadata *MD = dyn_cast_or_null<ConstantAsMetadata>(Node);
719 if (MD) {
720 ConstantInt *CV = cast<ConstantInt>(MD->getValue());
721 val = hash_combine(val, CV->getSExtValue());
722 } else {
723 val = hash_combine(val, Node);
724 }
725 };
726
727 HashBound(LowerBound);
728 HashBound(UpperBound);
729 HashBound(Stride);
730 HashBound(Bias);
731
732 return hash_combine(val, Name, File, Line, Scope, BaseType, Flags);
733 }
734};
735
738
739 static bool isSubsetEqual(const KeyTy &LHS, const DIDerivedType *RHS) {
740 return isODRMember(LHS.Tag, LHS.Scope, LHS.Name, RHS);
741 }
742
743 static bool isSubsetEqual(const DIDerivedType *LHS,
744 const DIDerivedType *RHS) {
745 return isODRMember(LHS->getTag(), LHS->getRawScope(), LHS->getRawName(),
746 RHS);
747 }
748
749 /// Subprograms compare equal if they declare the same function in an ODR
750 /// type.
751 static bool isODRMember(unsigned Tag, const Metadata *Scope,
752 const MDString *Name, const DIDerivedType *RHS) {
753 // Check whether the LHS is eligible.
754 if (Tag != dwarf::DW_TAG_member || !Name)
755 return false;
756
757 auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
758 if (!CT || !CT->getRawIdentifier())
759 return false;
760
761 // Compare to the RHS.
762 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
763 Scope == RHS->getRawScope();
764 }
765};
766
767template <> struct MDNodeKeyImpl<DICompositeType> {
768 unsigned Tag;
771 unsigned Line;
777 unsigned Flags;
779 unsigned RuntimeLang;
792
793 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
794 Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,
795 uint32_t AlignInBits, Metadata *OffsetInBits, unsigned Flags,
796 Metadata *Elements, unsigned RuntimeLang,
797 Metadata *VTableHolder, Metadata *TemplateParams,
798 MDString *Identifier, Metadata *Discriminator,
799 Metadata *DataLocation, Metadata *Associated,
800 Metadata *Allocated, Metadata *Rank, Metadata *Annotations,
801 Metadata *Specification, uint32_t NumExtraInhabitants,
802 Metadata *BitStride)
803 : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
804 BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
805 AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
806 RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
807 TemplateParams(TemplateParams), Identifier(Identifier),
808 Discriminator(Discriminator), DataLocation(DataLocation),
809 Associated(Associated), Allocated(Allocated), Rank(Rank),
810 Annotations(Annotations), Specification(Specification),
811 NumExtraInhabitants(NumExtraInhabitants), BitStride(BitStride) {}
813 : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
814 Line(N->getLine()), Scope(N->getRawScope()),
815 BaseType(N->getRawBaseType()), SizeInBits(N->getRawSizeInBits()),
816 OffsetInBits(N->getRawOffsetInBits()), AlignInBits(N->getAlignInBits()),
817 Flags(N->getFlags()), Elements(N->getRawElements()),
818 RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
819 TemplateParams(N->getRawTemplateParams()),
820 Identifier(N->getRawIdentifier()),
821 Discriminator(N->getRawDiscriminator()),
822 DataLocation(N->getRawDataLocation()),
823 Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()),
824 Rank(N->getRawRank()), Annotations(N->getRawAnnotations()),
825 Specification(N->getSpecification()),
826 NumExtraInhabitants(N->getNumExtraInhabitants()),
827 BitStride(N->getRawBitStride()) {}
828
829 bool isKeyOf(const DICompositeType *RHS) const {
830 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
831 File == RHS->getRawFile() && Line == RHS->getLine() &&
832 Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
833 SizeInBits == RHS->getRawSizeInBits() &&
834 AlignInBits == RHS->getAlignInBits() &&
835 OffsetInBits == RHS->getRawOffsetInBits() &&
836 Flags == RHS->getFlags() && Elements == RHS->getRawElements() &&
837 RuntimeLang == RHS->getRuntimeLang() &&
838 VTableHolder == RHS->getRawVTableHolder() &&
839 TemplateParams == RHS->getRawTemplateParams() &&
840 Identifier == RHS->getRawIdentifier() &&
841 Discriminator == RHS->getRawDiscriminator() &&
842 DataLocation == RHS->getRawDataLocation() &&
843 Associated == RHS->getRawAssociated() &&
844 Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() &&
845 Annotations == RHS->getRawAnnotations() &&
846 Specification == RHS->getSpecification() &&
847 NumExtraInhabitants == RHS->getNumExtraInhabitants() &&
848 BitStride == RHS->getRawBitStride();
849 }
850
851 unsigned getHashValue() const {
852 // Intentionally computes the hash on a subset of the operands for
853 // performance reason. The subset has to be significant enough to avoid
854 // collision "most of the time". There is no correctness issue in case of
855 // collision because of the full check above.
856 return hash_combine(Name, File, Line, BaseType, Scope, Elements,
857 TemplateParams, Annotations);
858 }
859};
860
861template <> struct MDNodeKeyImpl<DISubroutineType> {
862 unsigned Flags;
865
866 MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
867 : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
869 : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
870
871 bool isKeyOf(const DISubroutineType *RHS) const {
872 return Flags == RHS->getFlags() && CC == RHS->getCC() &&
873 TypeArray == RHS->getRawTypeArray();
874 }
875
876 unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
877};
878
879template <> struct MDNodeKeyImpl<DIFile> {
882 std::optional<DIFile::ChecksumInfo<MDString *>> Checksum;
884
885 MDNodeKeyImpl(MDString *Filename, MDString *Directory,
886 std::optional<DIFile::ChecksumInfo<MDString *>> Checksum,
887 MDString *Source)
888 : Filename(Filename), Directory(Directory), Checksum(Checksum),
889 Source(Source) {}
891 : Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
892 Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
893
894 bool isKeyOf(const DIFile *RHS) const {
895 return Filename == RHS->getRawFilename() &&
896 Directory == RHS->getRawDirectory() &&
897 Checksum == RHS->getRawChecksum() && Source == RHS->getRawSource();
898 }
899
900 unsigned getHashValue() const {
901 return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0,
902 Checksum ? Checksum->Value : nullptr, Source);
903 }
904};
905
906template <> struct MDNodeKeyImpl<DISubprogram> {
911 unsigned Line;
912 unsigned ScopeLine;
915 unsigned VirtualIndex;
917 unsigned Flags;
918 unsigned SPFlags;
927
929 Metadata *File, unsigned Line, Metadata *Type,
930 unsigned ScopeLine, Metadata *ContainingType,
931 unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
932 unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams,
933 Metadata *Declaration, Metadata *RetainedNodes,
934 Metadata *ThrownTypes, Metadata *Annotations,
935 MDString *TargetFuncName, bool UsesKeyInstructions)
936 : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
937 Line(Line), ScopeLine(ScopeLine), Type(Type),
938 ContainingType(ContainingType), VirtualIndex(VirtualIndex),
939 ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags),
940 Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration),
941 RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes),
942 Annotations(Annotations), TargetFuncName(TargetFuncName),
943 UsesKeyInstructions(UsesKeyInstructions) {}
945 : Scope(N->getRawScope()), Name(N->getRawName()),
946 LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
947 Line(N->getLine()), ScopeLine(N->getScopeLine()), Type(N->getRawType()),
948 ContainingType(N->getRawContainingType()),
949 VirtualIndex(N->getVirtualIndex()),
950 ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),
951 SPFlags(N->getSPFlags()), Unit(N->getRawUnit()),
952 TemplateParams(N->getRawTemplateParams()),
953 Declaration(N->getRawDeclaration()),
954 RetainedNodes(N->getRawRetainedNodes()),
955 ThrownTypes(N->getRawThrownTypes()),
956 Annotations(N->getRawAnnotations()),
957 TargetFuncName(N->getRawTargetFuncName()),
958 UsesKeyInstructions(N->getKeyInstructionsEnabled()) {}
959
960 bool isKeyOf(const DISubprogram *RHS) const {
961 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
962 LinkageName == RHS->getRawLinkageName() &&
963 File == RHS->getRawFile() && Line == RHS->getLine() &&
964 Type == RHS->getRawType() && ScopeLine == RHS->getScopeLine() &&
965 ContainingType == RHS->getRawContainingType() &&
966 VirtualIndex == RHS->getVirtualIndex() &&
967 ThisAdjustment == RHS->getThisAdjustment() &&
968 Flags == RHS->getFlags() && SPFlags == RHS->getSPFlags() &&
969 Unit == RHS->getUnit() &&
970 TemplateParams == RHS->getRawTemplateParams() &&
971 Declaration == RHS->getRawDeclaration() &&
972 RetainedNodes == RHS->getRawRetainedNodes() &&
973 ThrownTypes == RHS->getRawThrownTypes() &&
974 Annotations == RHS->getRawAnnotations() &&
975 TargetFuncName == RHS->getRawTargetFuncName() &&
976 UsesKeyInstructions == RHS->getKeyInstructionsEnabled();
977 }
978
979 bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; }
980
981 unsigned getHashValue() const {
982 // Use the Scope's linkage name instead of using the scope directly, as the
983 // scope may be a temporary one which can replaced, which would produce a
984 // different hash for the same DISubprogram.
985 llvm::StringRef ScopeLinkageName;
986 if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
987 if (auto *ID = CT->getRawIdentifier())
988 ScopeLinkageName = ID->getString();
989
990 // If this is a declaration inside an ODR type, only hash the type and the
991 // name. Otherwise the hash will be stronger than
992 // MDNodeSubsetEqualImpl::isDeclarationOfODRMember().
993 if (!isDefinition() && LinkageName &&
994 isa_and_nonnull<DICompositeType>(Scope))
995 return hash_combine(LinkageName, ScopeLinkageName);
996
997 // Intentionally computes the hash on a subset of the operands for
998 // performance reason. The subset has to be significant enough to avoid
999 // collision "most of the time". There is no correctness issue in case of
1000 // collision because of the full check above.
1001 return hash_combine(Name, ScopeLinkageName, File, Type, Line);
1002 }
1003};
1004
1007
1008 static bool isSubsetEqual(const KeyTy &LHS, const DISubprogram *RHS) {
1009 return isDeclarationOfODRMember(LHS.isDefinition(), LHS.Scope,
1010 LHS.LinkageName, LHS.TemplateParams, RHS);
1011 }
1012
1013 static bool isSubsetEqual(const DISubprogram *LHS, const DISubprogram *RHS) {
1014 return isDeclarationOfODRMember(LHS->isDefinition(), LHS->getRawScope(),
1015 LHS->getRawLinkageName(),
1016 LHS->getRawTemplateParams(), RHS);
1017 }
1018
1019 /// Subprograms compare equal if they declare the same function in an ODR
1020 /// type.
1021 static bool isDeclarationOfODRMember(bool IsDefinition, const Metadata *Scope,
1022 const MDString *LinkageName,
1023 const Metadata *TemplateParams,
1024 const DISubprogram *RHS) {
1025 // Check whether the LHS is eligible.
1026 if (IsDefinition || !Scope || !LinkageName)
1027 return false;
1028
1029 auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
1030 if (!CT || !CT->getRawIdentifier())
1031 return false;
1032
1033 // Compare to the RHS.
1034 // FIXME: We need to compare template parameters here to avoid incorrect
1035 // collisions in mapMetadata when RF_ReuseAndMutateDistinctMDs and a
1036 // ODR-DISubprogram has a non-ODR template parameter (i.e., a
1037 // DICompositeType that does not have an identifier). Eventually we should
1038 // decouple ODR logic from uniquing logic.
1039 return IsDefinition == RHS->isDefinition() && Scope == RHS->getRawScope() &&
1040 LinkageName == RHS->getRawLinkageName() &&
1041 TemplateParams == RHS->getRawTemplateParams();
1042 }
1043};
1044
1045template <> struct MDNodeKeyImpl<DILexicalBlock> {
1048 unsigned Line;
1049 unsigned Column;
1050
1051 MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)
1052 : Scope(Scope), File(File), Line(Line), Column(Column) {}
1054 : Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()),
1055 Column(N->getColumn()) {}
1056
1057 bool isKeyOf(const DILexicalBlock *RHS) const {
1058 return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
1059 Line == RHS->getLine() && Column == RHS->getColumn();
1060 }
1061
1062 unsigned getHashValue() const {
1063 return hash_combine(Scope, File, Line, Column);
1064 }
1065};
1066
1071
1072 MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
1073 : Scope(Scope), File(File), Discriminator(Discriminator) {}
1075 : Scope(N->getRawScope()), File(N->getRawFile()),
1076 Discriminator(N->getDiscriminator()) {}
1077
1078 bool isKeyOf(const DILexicalBlockFile *RHS) const {
1079 return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
1080 Discriminator == RHS->getDiscriminator();
1081 }
1082
1083 unsigned getHashValue() const {
1084 return hash_combine(Scope, File, Discriminator);
1085 }
1086};
1087
1088template <> struct MDNodeKeyImpl<DINamespace> {
1092
1093 MDNodeKeyImpl(Metadata *Scope, MDString *Name, bool ExportSymbols)
1094 : Scope(Scope), Name(Name), ExportSymbols(ExportSymbols) {}
1096 : Scope(N->getRawScope()), Name(N->getRawName()),
1097 ExportSymbols(N->getExportSymbols()) {}
1098
1099 bool isKeyOf(const DINamespace *RHS) const {
1100 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
1101 ExportSymbols == RHS->getExportSymbols();
1102 }
1103
1104 unsigned getHashValue() const { return hash_combine(Scope, Name); }
1105};
1106
1107template <> struct MDNodeKeyImpl<DICommonBlock> {
1112 unsigned LineNo;
1113
1115 unsigned LineNo)
1116 : Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo) {}
1118 : Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()),
1119 File(N->getRawFile()), LineNo(N->getLineNo()) {}
1120
1121 bool isKeyOf(const DICommonBlock *RHS) const {
1122 return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() &&
1123 Name == RHS->getRawName() && File == RHS->getRawFile() &&
1124 LineNo == RHS->getLineNo();
1125 }
1126
1127 unsigned getHashValue() const {
1128 return hash_combine(Scope, Decl, Name, File, LineNo);
1129 }
1130};
1131
1132template <> struct MDNodeKeyImpl<DIModule> {
1139 unsigned LineNo;
1141
1143 MDString *ConfigurationMacros, MDString *IncludePath,
1144 MDString *APINotesFile, unsigned LineNo, bool IsDecl)
1145 : File(File), Scope(Scope), Name(Name),
1146 ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath),
1147 APINotesFile(APINotesFile), LineNo(LineNo), IsDecl(IsDecl) {}
1149 : File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()),
1150 ConfigurationMacros(N->getRawConfigurationMacros()),
1151 IncludePath(N->getRawIncludePath()),
1152 APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()),
1153 IsDecl(N->getIsDecl()) {}
1154
1155 bool isKeyOf(const DIModule *RHS) const {
1156 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
1157 ConfigurationMacros == RHS->getRawConfigurationMacros() &&
1158 IncludePath == RHS->getRawIncludePath() &&
1159 APINotesFile == RHS->getRawAPINotesFile() &&
1160 File == RHS->getRawFile() && LineNo == RHS->getLineNo() &&
1161 IsDecl == RHS->getIsDecl();
1162 }
1163
1164 unsigned getHashValue() const {
1165 return hash_combine(Scope, Name, ConfigurationMacros, IncludePath);
1166 }
1167};
1168
1173
1175 : Name(Name), Type(Type), IsDefault(IsDefault) {}
1177 : Name(N->getRawName()), Type(N->getRawType()),
1178 IsDefault(N->isDefault()) {}
1179
1181 return Name == RHS->getRawName() && Type == RHS->getRawType() &&
1182 IsDefault == RHS->isDefault();
1183 }
1184
1185 unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }
1186};
1187
1189 unsigned Tag;
1194
1195 MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,
1196 Metadata *Value)
1197 : Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}
1199 : Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),
1200 IsDefault(N->isDefault()), Value(N->getValue()) {}
1201
1203 return Tag == RHS->getTag() && Name == RHS->getRawName() &&
1204 Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&
1205 Value == RHS->getValue();
1206 }
1207
1208 unsigned getHashValue() const {
1209 return hash_combine(Tag, Name, Type, IsDefault, Value);
1210 }
1211};
1212
1213template <> struct MDNodeKeyImpl<DIGlobalVariable> {
1218 unsigned Line;
1226
1228 Metadata *File, unsigned Line, Metadata *Type,
1229 bool IsLocalToUnit, bool IsDefinition,
1230 Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
1231 uint32_t AlignInBits, Metadata *Annotations)
1232 : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
1233 Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
1234 IsDefinition(IsDefinition),
1235 StaticDataMemberDeclaration(StaticDataMemberDeclaration),
1236 TemplateParams(TemplateParams), AlignInBits(AlignInBits),
1239 : Scope(N->getRawScope()), Name(N->getRawName()),
1240 LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
1241 Line(N->getLine()), Type(N->getRawType()),
1242 IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
1243 StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()),
1244 TemplateParams(N->getRawTemplateParams()),
1245 AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {}
1246
1247 bool isKeyOf(const DIGlobalVariable *RHS) const {
1248 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
1249 LinkageName == RHS->getRawLinkageName() &&
1250 File == RHS->getRawFile() && Line == RHS->getLine() &&
1251 Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() &&
1252 IsDefinition == RHS->isDefinition() &&
1253 StaticDataMemberDeclaration ==
1254 RHS->getRawStaticDataMemberDeclaration() &&
1255 TemplateParams == RHS->getRawTemplateParams() &&
1256 AlignInBits == RHS->getAlignInBits() &&
1257 Annotations == RHS->getRawAnnotations();
1258 }
1259
1260 unsigned getHashValue() const {
1261 // We do not use AlignInBits in hashing function here on purpose:
1262 // in most cases this param for local variable is zero (for function param
1263 // it is always zero). This leads to lots of hash collisions and errors on
1264 // cases with lots of similar variables.
1265 // clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
1266 // generated IR is random for each run and test fails with Align included.
1267 // TODO: make hashing work fine with such situations
1268 return hash_combine(Scope, Name, LinkageName, File, Line, Type,
1269 IsLocalToUnit, IsDefinition, /* AlignInBits, */
1270 StaticDataMemberDeclaration, Annotations);
1271 }
1272};
1273
1274template <> struct MDNodeKeyImpl<DILocalVariable> {
1278 unsigned Line;
1280 unsigned Arg;
1281 unsigned Flags;
1284
1285 MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line,
1286 Metadata *Type, unsigned Arg, unsigned Flags,
1287 uint32_t AlignInBits, Metadata *Annotations)
1288 : Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg),
1289 Flags(Flags), AlignInBits(AlignInBits), Annotations(Annotations) {}
1291 : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
1292 Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()),
1293 Flags(N->getFlags()), AlignInBits(N->getAlignInBits()),
1294 Annotations(N->getRawAnnotations()) {}
1295
1296 bool isKeyOf(const DILocalVariable *RHS) const {
1297 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
1298 File == RHS->getRawFile() && Line == RHS->getLine() &&
1299 Type == RHS->getRawType() && Arg == RHS->getArg() &&
1300 Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits() &&
1301 Annotations == RHS->getRawAnnotations();
1302 }
1303
1304 unsigned getHashValue() const {
1305 // We do not use AlignInBits in hashing function here on purpose:
1306 // in most cases this param for local variable is zero (for function param
1307 // it is always zero). This leads to lots of hash collisions and errors on
1308 // cases with lots of similar variables.
1309 // clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
1310 // generated IR is random for each run and test fails with Align included.
1311 // TODO: make hashing work fine with such situations
1312 return hash_combine(Scope, Name, File, Line, Type, Arg, Flags, Annotations);
1313 }
1314};
1315
1316template <> struct MDNodeKeyImpl<DILabel> {
1320 unsigned Line;
1321 unsigned Column;
1323 std::optional<unsigned> CoroSuspendIdx;
1324
1325 MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line,
1326 unsigned Column, bool IsArtificial,
1327 std::optional<unsigned> CoroSuspendIdx)
1328 : Scope(Scope), Name(Name), File(File), Line(Line), Column(Column),
1329 IsArtificial(IsArtificial), CoroSuspendIdx(CoroSuspendIdx) {}
1331 : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
1332 Line(N->getLine()), Column(N->getColumn()),
1333 IsArtificial(N->isArtificial()),
1334 CoroSuspendIdx(N->getCoroSuspendIdx()) {}
1335
1336 bool isKeyOf(const DILabel *RHS) const {
1337 return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
1338 File == RHS->getRawFile() && Line == RHS->getLine() &&
1339 Column == RHS->getColumn() && IsArtificial == RHS->isArtificial() &&
1340 CoroSuspendIdx == RHS->getCoroSuspendIdx();
1341 }
1342
1343 /// Using name and line to get hash value. It should already be mostly unique.
1344 unsigned getHashValue() const {
1345 return hash_combine(Scope, Name, Line, Column, IsArtificial,
1346 CoroSuspendIdx);
1347 }
1348};
1349
1350template <> struct MDNodeKeyImpl<DIExpression> {
1352
1353 MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
1354 MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {}
1355
1356 bool isKeyOf(const DIExpression *RHS) const {
1357 return Elements == RHS->getElements();
1358 }
1359
1360 unsigned getHashValue() const { return hash_combine_range(Elements); }
1361};
1362
1366
1368 : Variable(Variable), Expression(Expression) {}
1370 : Variable(N->getRawVariable()), Expression(N->getRawExpression()) {}
1371
1373 return Variable == RHS->getRawVariable() &&
1374 Expression == RHS->getRawExpression();
1375 }
1376
1377 unsigned getHashValue() const { return hash_combine(Variable, Expression); }
1378};
1379
1380template <> struct MDNodeKeyImpl<DIObjCProperty> {
1383 unsigned Line;
1386 unsigned Attributes;
1388
1389 MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line,
1390 MDString *GetterName, MDString *SetterName, unsigned Attributes,
1391 Metadata *Type)
1392 : Name(Name), File(File), Line(Line), GetterName(GetterName),
1393 SetterName(SetterName), Attributes(Attributes), Type(Type) {}
1395 : Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
1396 GetterName(N->getRawGetterName()), SetterName(N->getRawSetterName()),
1397 Attributes(N->getAttributes()), Type(N->getRawType()) {}
1398
1399 bool isKeyOf(const DIObjCProperty *RHS) const {
1400 return Name == RHS->getRawName() && File == RHS->getRawFile() &&
1401 Line == RHS->getLine() && GetterName == RHS->getRawGetterName() &&
1402 SetterName == RHS->getRawSetterName() &&
1403 Attributes == RHS->getAttributes() && Type == RHS->getRawType();
1404 }
1405
1406 unsigned getHashValue() const {
1407 return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,
1408 Type);
1409 }
1410};
1411
1412template <> struct MDNodeKeyImpl<DIImportedEntity> {
1413 unsigned Tag;
1417 unsigned Line;
1420
1421 MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File,
1422 unsigned Line, MDString *Name, Metadata *Elements)
1423 : Tag(Tag), Scope(Scope), Entity(Entity), File(File), Line(Line),
1424 Name(Name), Elements(Elements) {}
1426 : Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()),
1427 File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()),
1428 Elements(N->getRawElements()) {}
1429
1430 bool isKeyOf(const DIImportedEntity *RHS) const {
1431 return Tag == RHS->getTag() && Scope == RHS->getRawScope() &&
1432 Entity == RHS->getRawEntity() && File == RHS->getFile() &&
1433 Line == RHS->getLine() && Name == RHS->getRawName() &&
1434 Elements == RHS->getRawElements();
1435 }
1436
1437 unsigned getHashValue() const {
1438 return hash_combine(Tag, Scope, Entity, File, Line, Name, Elements);
1439 }
1440};
1441
1442template <> struct MDNodeKeyImpl<DIMacro> {
1443 unsigned MIType;
1444 unsigned Line;
1447
1448 MDNodeKeyImpl(unsigned MIType, unsigned Line, MDString *Name, MDString *Value)
1449 : MIType(MIType), Line(Line), Name(Name), Value(Value) {}
1451 : MIType(N->getMacinfoType()), Line(N->getLine()), Name(N->getRawName()),
1452 Value(N->getRawValue()) {}
1453
1454 bool isKeyOf(const DIMacro *RHS) const {
1455 return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
1456 Name == RHS->getRawName() && Value == RHS->getRawValue();
1457 }
1458
1459 unsigned getHashValue() const {
1460 return hash_combine(MIType, Line, Name, Value);
1461 }
1462};
1463
1464template <> struct MDNodeKeyImpl<DIMacroFile> {
1465 unsigned MIType;
1466 unsigned Line;
1469
1470 MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File,
1471 Metadata *Elements)
1472 : MIType(MIType), Line(Line), File(File), Elements(Elements) {}
1474 : MIType(N->getMacinfoType()), Line(N->getLine()), File(N->getRawFile()),
1475 Elements(N->getRawElements()) {}
1476
1477 bool isKeyOf(const DIMacroFile *RHS) const {
1478 return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
1479 File == RHS->getRawFile() && Elements == RHS->getRawElements();
1480 }
1481
1482 unsigned getHashValue() const {
1483 return hash_combine(MIType, Line, File, Elements);
1484 }
1485};
1486
1487// DIArgLists are not MDNodes, but we still want to unique them in a DenseSet
1488// based on a hash of their arguments.
1491
1493 DIArgListKeyInfo(const DIArgList *N) : Args(N->getArgs()) {}
1494
1495 bool isKeyOf(const DIArgList *RHS) const { return Args == RHS->getArgs(); }
1496
1497 unsigned getHashValue() const { return hash_combine_range(Args); }
1498};
1499
1500/// DenseMapInfo for DIArgList.
1503
1504 static inline DIArgList *getEmptyKey() {
1506 }
1507
1508 static inline DIArgList *getTombstoneKey() {
1510 }
1511
1512 static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }
1513
1514 static unsigned getHashValue(const DIArgList *N) {
1515 return KeyTy(N).getHashValue();
1516 }
1517
1518 static bool isEqual(const KeyTy &LHS, const DIArgList *RHS) {
1519 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
1520 return false;
1521 return LHS.isKeyOf(RHS);
1522 }
1523
1524 static bool isEqual(const DIArgList *LHS, const DIArgList *RHS) {
1525 return LHS == RHS;
1526 }
1527};
1528
1529/// DenseMapInfo for MDNode subclasses.
1530template <class NodeTy> struct MDNodeInfo {
1533
1534 static inline NodeTy *getEmptyKey() {
1536 }
1537
1538 static inline NodeTy *getTombstoneKey() {
1540 }
1541
1542 static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }
1543
1544 static unsigned getHashValue(const NodeTy *N) {
1545 return KeyTy(N).getHashValue();
1546 }
1547
1548 static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) {
1549 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
1550 return false;
1551 return SubsetEqualTy::isSubsetEqual(LHS, RHS) || LHS.isKeyOf(RHS);
1552 }
1553
1554 static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) {
1555 if (LHS == RHS)
1556 return true;
1557 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
1558 return false;
1560 }
1561};
1562
1563#define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;
1564#include "llvm/IR/Metadata.def"
1565
1566/// Multimap-like storage for metadata attachments.
1568public:
1569 struct Attachment {
1570 unsigned MDKind;
1572 };
1573
1574private:
1575 SmallVector<Attachment, 1> Attachments;
1576
1577public:
1578 bool empty() const { return Attachments.empty(); }
1579 size_t size() const { return Attachments.size(); }
1580
1581 /// Returns the first attachment with the given ID or nullptr if no such
1582 /// attachment exists.
1583 MDNode *lookup(unsigned ID) const;
1584
1585 /// Appends all attachments with the given ID to \c Result in insertion order.
1586 /// If the global has no attachments with the given ID, or if ID is invalid,
1587 /// leaves Result unchanged.
1588 void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;
1589
1590 /// Appends all attachments for the global to \c Result, sorting by attachment
1591 /// ID. Attachments with the same ID appear in insertion order. This function
1592 /// does \em not clear \c Result.
1593 void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
1594
1595 /// Set an attachment to a particular node.
1596 ///
1597 /// Set the \c ID attachment to \c MD, replacing the current attachments at \c
1598 /// ID (if anyway).
1599 void set(unsigned ID, MDNode *MD);
1600
1601 /// Adds an attachment to a particular node.
1602 void insert(unsigned ID, MDNode &MD);
1603
1604 /// Remove attachments with the given ID.
1605 ///
1606 /// Remove the attachments at \c ID, if any.
1607 bool erase(unsigned ID);
1608
1609 /// Erase matching attachments.
1610 ///
1611 /// Erases all attachments matching the \c shouldRemove predicate.
1612 template <class PredTy> void remove_if(PredTy shouldRemove) {
1613 llvm::erase_if(Attachments, shouldRemove);
1614 }
1615};
1616
1618public:
1619 /// OwnedModules - The set of modules instantiated in this context, and which
1620 /// will be automatically deleted if this context is deleted.
1622
1623 /// MachineFunctionNums - Keep the next available unique number available for
1624 /// a MachineFunction in given module. Module must in OwnedModules.
1626
1627 /// The main remark streamer used by all the other streamers (e.g. IR, MIR,
1628 /// frontends, etc.). This should only be used by the specific streamers, and
1629 /// never directly.
1630 std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;
1631
1632 std::unique_ptr<DiagnosticHandler> DiagHandler;
1635 /// The minimum hotness value a diagnostic needs in order to be included in
1636 /// optimization diagnostics.
1637 ///
1638 /// The threshold is an Optional value, which maps to one of the 3 states:
1639 /// 1). 0 => threshold disabled. All emarks will be printed.
1640 /// 2). positive int => manual threshold by user. Remarks with hotness exceed
1641 /// threshold will be printed.
1642 /// 3). None => 'auto' threshold by user. The actual value is not
1643 /// available at command line, but will be synced with
1644 /// hotness threhold from profile summary during
1645 /// compilation.
1646 ///
1647 /// State 1 and 2 are considered as terminal states. State transition is
1648 /// only allowed from 3 to 2, when the threshold is first synced with profile
1649 /// summary. This ensures that the threshold is set only once and stays
1650 /// constant.
1651 ///
1652 /// If threshold option is not specified, it is disabled (0) by default.
1653 std::optional<uint64_t> DiagnosticsHotnessThreshold = 0;
1654
1655 /// The percentage of difference between profiling branch weights and
1656 /// llvm.expect branch weights to tolerate when emiting MisExpect diagnostics
1657 std::optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
1659
1660 /// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
1661 std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
1662
1664 void *YieldOpaqueHandle = nullptr;
1665
1667
1671 DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantInt>>
1673
1675 DenseMap<std::pair<ElementCount, APFloat>, std::unique_ptr<ConstantFP>>
1677
1681
1686
1687#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
1688 DenseSet<CLASS *, CLASS##Info> CLASS##s;
1689#include "llvm/IR/Metadata.def"
1690
1691 // Optional map for looking up composite types by identifier.
1692 std::optional<DenseMap<const MDString *, DICompositeType *>> DITypeMap;
1693
1694 // MDNodes may be uniqued or not uniqued. When they're not uniqued, they
1695 // aren't in the MDNodeSet, but they're still shared between objects, so no
1696 // one object can destroy them. Keep track of them here so we can delete
1697 // them on context teardown.
1698 std::vector<MDNode *> DistinctMDNodes;
1699
1700 // ConstantRangeListAttributeImpl is a TrailingObjects/ArrayRef of
1701 // ConstantRange. Since this is a dynamically sized class, it's not
1702 // possible to use SpecificBumpPtrAllocator. Instead, we use normal Alloc
1703 // for allocation and record all allocated pointers in this vector. In the
1704 // LLVMContext destructor, call the destuctors of everything in the vector.
1705 std::vector<ConstantRangeListAttributeImpl *> ConstantRangeListAttributes;
1706
1708
1711
1714
1717
1719
1721
1723
1725
1727
1729
1731
1733
1735
1737
1739
1742
1743 // Basic type instances.
1748
1749 std::unique_ptr<ConstantTokenNone> TheNoneToken;
1750
1755
1757
1764
1767
1770 PointerType *AS0PointerType = nullptr; // AddrSpace = 0
1773
1774 /// ValueHandles - This map keeps track of all of the value handles that are
1775 /// watching a Value*. The Value::HasValueHandle bit is used to know
1776 /// whether or not a value has an entry in this map.
1779
1780 /// CustomMDKindNames - Map to hold the metadata string to ID mapping.
1782
1783 /// Collection of metadata used in this context.
1785
1786 /// Map DIAssignID -> Instructions with that attachment.
1787 /// Managed by Instruction via Instruction::updateDIAssignIDMapping.
1788 /// Query using the at:: functions defined in DebugInfo.h.
1790
1791 /// Collection of per-GlobalObject sections used in this context.
1793
1794 /// Collection of per-GlobalValue partitions used in this context.
1796
1799
1800 /// DiscriminatorTable - This table maps file:line locations to an
1801 /// integer representing the next DWARF path discriminator to assign to
1802 /// instructions in different blocks at the same location.
1804
1805 /// A set of interned tags for operand bundles. The StringMap maps
1806 /// bundle tags to their IDs.
1807 ///
1808 /// \see LLVMContext::getOperandBundleTagID
1810
1814
1815 /// A set of interned synchronization scopes. The StringMap maps
1816 /// synchronization scope names to their respective synchronization scope IDs.
1818
1819 /// getOrInsertSyncScopeID - Maps synchronization scope name to
1820 /// synchronization scope ID. Every synchronization scope registered with
1821 /// LLVMContext has unique ID except pre-defined ones.
1823
1824 /// getSyncScopeNames - Populates client supplied SmallVector with
1825 /// synchronization scope names registered with LLVMContext. Synchronization
1826 /// scope names are ordered by increasing synchronization scope IDs.
1828
1829 /// getSyncScopeName - Returns the name of a SyncScope::ID
1830 /// registered with LLVMContext, if any.
1831 std::optional<StringRef> getSyncScopeName(SyncScope::ID Id) const;
1832
1833 /// Maintain the GC name for each function.
1834 ///
1835 /// This saves allocating an additional word in Function for programs which
1836 /// do not use GC (i.e., most programs) at the cost of increased overhead for
1837 /// clients which do use GC.
1839
1840 /// Flag to indicate if Value (other than GlobalValue) retains their name or
1841 /// not.
1842 bool DiscardValueNames = false;
1843
1846
1847 mutable OptPassGate *OPG = nullptr;
1848
1849 /// Access the object which can disable optional passes and individual
1850 /// optimizations at compile time.
1851 OptPassGate &getOptPassGate() const;
1852
1853 /// Set the object which can disable optional passes and individual
1854 /// optimizations at compile time.
1855 ///
1856 /// The lifetime of the object must be guaranteed to extend as long as the
1857 /// LLVMContext is used by compilation.
1859
1860 /// Mapping of blocks to collections of "trailing" DbgVariableRecords. As part
1861 /// of the "RemoveDIs" project, debug-info variable location records are going
1862 /// to cease being instructions... which raises the problem of where should
1863 /// they be recorded when we remove the terminator of a blocks, such as:
1864 ///
1865 /// %foo = add i32 0, 0
1866 /// br label %bar
1867 ///
1868 /// If the branch is removed, a legitimate transient state while editing a
1869 /// block, any debug-records between those two instructions will not have a
1870 /// location. Each block thus records any DbgVariableRecord records that
1871 /// "trail" in such a way. These are stored in LLVMContext because typically
1872 /// LLVM only edits a small number of blocks at a time, so there's no need to
1873 /// bloat BasicBlock with such a data structure.
1875
1876 // Set, get and delete operations for TrailingDbgRecords.
1878 assert(!TrailingDbgRecords.count(B));
1879 TrailingDbgRecords[B] = M;
1880 }
1881
1883 return TrailingDbgRecords.lookup(B);
1884 }
1885
1887
1888 std::string DefaultTargetCPU;
1890
1891 /// The next available source atom group number. The front end is responsible
1892 /// for assigning source atom numbers, but certain optimisations need to
1893 /// assign new group numbers to a set of instructions. Most often code
1894 /// duplication optimisations like loop unroll. Tracking a global maximum
1895 /// value means we can know (cheaply) we're never using a group number that's
1896 /// already used within this function.
1897 ///
1898 /// Start a 1 because 0 means the source location isn't part of an atom group.
1900};
1901
1902} // end namespace llvm
1903
1904#endif // LLVM_LIB_IR_LLVMCONTEXTIMPL_H
static std::optional< unsigned > getTag(const TargetRegisterInfo *TRI, const MachineInstr &MI, const LoadInfo &LI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
AMDGPU Kernel Attributes
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file contains constants used for implementing Dwarf debug support.
std::string Name
This file defines a hash set that can be used to remove duplication of nodes in a graph.
Module.h This file contains the declarations for the Module class.
This file contains the declarations for metadata subclasses.
#define P(N)
static StringRef getName(Value *V)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static uint32_t getFlags(const Symbol *Sym)
Definition: TapiFile.cpp:26
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
Annotations lets you mark points and ranges inside source code, for tests:
Definition: Annotations.h:53
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:136
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
iterator begin() const
Definition: ArrayRef.h:135
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
Class to represent array types.
Definition: DerivedTypes.h:398
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:67
Constant * getValue() const
Definition: Metadata.h:543
This is the shared class of boolean and integer constants.
Definition: Constants.h:87
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition: Constants.h:169
List of ValueAsMetadata, to be used as an argument to a dbg.value intrinsic.
Basic type, like 'int' or 'float'.
Debug common block.
Enumeration value.
DWARF expression.
A pair of DIGlobalVariable and DIExpression.
An imported module (C++ using directive or similar).
Debug lexical block.
Debug location.
Represents a module in the programming language, for example, a Clang module, or a Fortran module.
Debug lexical block.
String type, Fortran CHARACTER(n)
Subprogram description. Uses SubclassData1.
Array subrange.
Type array for a subprogram.
Per-instruction record of debug-info.
Implements a dense probed hash-table based set.
Definition: DenseSet.h:263
Class representing an expression and its matching format.
FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...
Definition: FoldingSet.h:539
Class to represent function types.
Definition: DerivedTypes.h:105
Generic tagged DWARF-like metadata node.
Class to represent integer types.
Definition: DerivedTypes.h:42
DenseMap< const GlobalValue *, StringRef > GlobalValuePartitions
Collection of per-GlobalValue partitions used in this context.
DenseMap< const GlobalValue *, GlobalValue::SanitizerMetadata > GlobalValueSanitizerMetadata
DenseMap< unsigned, std::unique_ptr< ConstantInt > > IntOneConstants
void getSyncScopeNames(SmallVectorImpl< StringRef > &SSNs) const
getSyncScopeNames - Populates client supplied SmallVector with synchronization scope names registered...
DenseMap< unsigned, std::unique_ptr< ConstantInt > > IntZeroConstants
DenseMap< Metadata *, MetadataAsValue * > MetadataAsValues
DenseMap< APFloat, std::unique_ptr< ConstantFP > > FPConstants
SmallPtrSet< Module *, 4 > OwnedModules
OwnedModules - The set of modules instantiated in this context, and which will be automatically delet...
DenseMap< PointerType *, std::unique_ptr< ConstantPointerNull > > CPNConstants
DenseMap< Type *, std::unique_ptr< ConstantAggregateZero > > CAZConstants
StringMap< MDString, BumpPtrAllocator > MDStringCache
TargetExtTypeSet TargetExtTypes
DenseMap< DIAssignID *, SmallVector< Instruction *, 1 > > AssignmentIDToInstrs
Map DIAssignID -> Instructions with that attachment.
DenseMap< Type *, std::unique_ptr< PoisonValue > > PVConstants
DenseMap< APInt, std::unique_ptr< ConstantInt > > IntConstants
std::vector< MDNode * > DistinctMDNodes
std::optional< uint32_t > DiagnosticsMisExpectTolerance
The percentage of difference between profiling branch weights and llvm.expect branch weights to toler...
FoldingSet< AttributeImpl > AttrsSet
StructTypeSet AnonStructTypes
std::unique_ptr< ConstantTokenNone > TheNoneToken
DenseMap< const Value *, ValueName * > ValueNames
SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
void setOptPassGate(OptPassGate &)
Set the object which can disable optional passes and individual optimizations at compile time.
VectorConstantsTy VectorConstants
std::unique_ptr< LLVMRemarkStreamer > LLVMRS
The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
bool DiscardValueNames
Flag to indicate if Value (other than GlobalValue) retains their name or not.
DenseMap< const GlobalValue *, NoCFIValue * > NoCFIValues
DenseMap< const Function *, std::string > GCNames
Maintain the GC name for each function.
DenseMap< const BasicBlock *, BlockAddress * > BlockAddresses
DenseMap< Type *, std::unique_ptr< UndefValue > > UVConstants
OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time.
DenseMap< std::pair< Type *, unsigned >, TypedPointerType * > ASTypedPointerTypes
DenseMap< std::pair< Type *, uint64_t >, ArrayType * > ArrayTypes
std::string DefaultTargetFeatures
DenseMap< const Value *, MDAttachments > ValueMetadata
Collection of metadata used in this context.
DenseMap< Module *, unsigned > MachineFunctionNums
MachineFunctionNums - Keep the next available unique number available for a MachineFunction in given ...
StringMap< unsigned > CustomMDKindNames
CustomMDKindNames - Map to hold the metadata string to ID mapping.
StringMapEntry< uint32_t > * getOrInsertBundleTag(StringRef Tag)
std::unique_ptr< DiagnosticHandler > DiagHandler
StringMap< uint32_t > BundleTagCache
A set of interned tags for operand bundles.
DbgMarker * getTrailingDbgRecords(BasicBlock *B)
BumpPtrAllocator Alloc
DenseMap< const GlobalObject *, StringRef > GlobalObjectSections
Collection of per-GlobalObject sections used in this context.
StringMap< std::unique_ptr< ConstantDataSequential > > CDSConstants
StructConstantsTy StructConstants
DenseMap< std::pair< Type *, ElementCount >, VectorType * > VectorTypes
std::unique_ptr< remarks::RemarkStreamer > MainRemarkStreamer
The main remark streamer used by all the other streamers (e.g.
void getOperandBundleTags(SmallVectorImpl< StringRef > &Tags) const
void deleteTrailingDbgRecords(BasicBlock *B)
FoldingSet< AttributeSetNode > AttrsSetNodes
FoldingSet< AttributeListImpl > AttrsLists
ConstantUniqueMap< ConstantPtrAuth > ConstantPtrAuths
DenseMap< TargetExtType *, std::unique_ptr< ConstantTargetNone > > CTNConstants
SpecificBumpPtrAllocator< ConstantRangeAttributeImpl > ConstantRangeAttributeAlloc
std::optional< uint64_t > DiagnosticsHotnessThreshold
The minimum hotness value a diagnostic needs in order to be included in optimization diagnostics.
ConstantUniqueMap< ConstantExpr > ExprConstants
uint32_t getOperandBundleTagID(StringRef Tag) const
StringMap< SyncScope::ID > SSC
A set of interned synchronization scopes.
DenseMap< unsigned, PointerType * > PointerTypes
void setTrailingDbgRecords(BasicBlock *B, DbgMarker *M)
DenseMap< std::pair< ElementCount, APInt >, std::unique_ptr< ConstantInt > > IntSplatConstants
UniqueStringSaver Saver
LLVMContext::YieldCallbackTy YieldCallback
DenseMap< unsigned, IntegerType * > IntegerTypes
StringMap< StructType * > NamedStructTypes
std::vector< ConstantRangeListAttributeImpl * > ConstantRangeListAttributes
PointerType * AS0PointerType
DenseSet< DIArgList *, DIArgListInfo > DIArgLists
ValueHandlesTy ValueHandles
std::optional< StringRef > getSyncScopeName(SyncScope::ID Id) const
getSyncScopeName - Returns the name of a SyncScope::ID registered with LLVMContext,...
ArrayConstantsTy ArrayConstants
DenseMap< Value *, ValueAsMetadata * > ValuesAsMetadata
ConstantUniqueMap< InlineAsm > InlineAsms
DenseMap< std::pair< const char *, unsigned >, unsigned > DiscriminatorTable
DiscriminatorTable - This table maps file:line locations to an integer representing the next DWARF pa...
uint64_t NextAtomGroup
The next available source atom group number.
DenseMap< const GlobalValue *, DSOLocalEquivalent * > DSOLocalEquivalents
SmallDenseMap< BasicBlock *, DbgMarker * > TrailingDbgRecords
Mapping of blocks to collections of "trailing" DbgVariableRecords.
FunctionTypeSet FunctionTypes
std::optional< DenseMap< const MDString *, DICompositeType * > > DITypeMap
DenseMap< std::pair< ElementCount, APFloat >, std::unique_ptr< ConstantFP > > FPSplatConstants
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
void(*)(LLVMContext *Context, void *OpaqueHandle) YieldCallbackTy
Defines the type of a yield callback.
Definition: LLVMContext.h:170
Multimap-like storage for metadata attachments.
void insert(unsigned ID, MDNode &MD)
Adds an attachment to a particular node.
Definition: Metadata.cpp:1518
void remove_if(PredTy shouldRemove)
Erase matching attachments.
void get(unsigned ID, SmallVectorImpl< MDNode * > &Result) const
Appends all attachments with the given ID to Result in insertion order.
Definition: Metadata.cpp:1495
void getAll(SmallVectorImpl< std::pair< unsigned, MDNode * > > &Result) const
Appends all attachments for the global to Result, sorting by attachment ID.
Definition: Metadata.cpp:1501
void set(unsigned ID, MDNode *MD)
Set an attachment to a particular node.
Definition: Metadata.cpp:1512
MDNode * lookup(unsigned ID) const
Returns the first attachment with the given ID or nullptr if no such attachment exists.
Definition: Metadata.cpp:1488
bool erase(unsigned ID)
Remove attachments with the given ID.
Definition: Metadata.cpp:1522
Structure for hashing arbitrary MDNode operands.
MDNodeOpsKey(const NodeTy *N, unsigned Offset=0)
bool compareOps(const NodeTy *RHS, unsigned Offset=0) const
unsigned getHash() const
MDNodeOpsKey(ArrayRef< Metadata * > Ops)
static unsigned calculateHash(MDNode *N, unsigned Offset=0)
Metadata node.
Definition: Metadata.h:1077
A single uniqued string.
Definition: Metadata.h:720
Tuple of metadata.
Definition: Metadata.h:1493
Root of the metadata hierarchy.
Definition: Metadata.h:63
Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...
Definition: OptBisect.h:26
Class to represent pointers.
Definition: DerivedTypes.h:700
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
Definition: Allocator.h:390
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:133
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Class to represent struct types.
Definition: DerivedTypes.h:218
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:781
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
A few GPU targets, such as DXIL and SPIR-V, have typed pointers.
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
Definition: StringSaver.h:45
LLVM Value Representation.
Definition: Value.h:75
Base class of all SIMD vector types.
Definition: DerivedTypes.h:430
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:81
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
hash_code hash_value(const FixedPointSemantics &Val)
Definition: APFixedPoint.h:137
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:2139
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:595
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition: Hashing.h:469
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
#define N
static LLVM_ABI const fltSemantics & Bogus() LLVM_READNONE
A Pseudo fltsemantic used to construct APFloats that cannot conflict with anything real.
Definition: APFloat.cpp:292
KeyTy(const ArrayRef< Type * > &E, bool P)
bool operator==(const KeyTy &that) const
bool operator!=(const KeyTy &that) const
static StructType * getEmptyKey()
static bool isEqual(const StructType *LHS, const StructType *RHS)
static unsigned getHashValue(const StructType *ST)
static unsigned getHashValue(const KeyTy &Key)
static StructType * getTombstoneKey()
static bool isEqual(const KeyTy &LHS, const StructType *RHS)
DenseMapInfo for DIArgList.
static unsigned getHashValue(const KeyTy &Key)
static DIArgList * getEmptyKey()
static unsigned getHashValue(const DIArgList *N)
static bool isEqual(const DIArgList *LHS, const DIArgList *RHS)
DIArgListKeyInfo KeyTy
static DIArgList * getTombstoneKey()
static bool isEqual(const KeyTy &LHS, const DIArgList *RHS)
ArrayRef< ValueAsMetadata * > Args
DIArgListKeyInfo(const DIArgList *N)
DIArgListKeyInfo(ArrayRef< ValueAsMetadata * > Args)
unsigned getHashValue() const
bool isKeyOf(const DIArgList *RHS) const
A single checksum, represented by a Kind and a Value (a string).
static bool isEqual(const APFloat &LHS, const APFloat &RHS)
static APFloat getTombstoneKey()
static unsigned getHashValue(const APFloat &Key)
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:54
bool operator==(const KeyTy &that) const
bool operator!=(const KeyTy &that) const
KeyTy(const Type *R, const ArrayRef< Type * > &P, bool V)
KeyTy(const FunctionType *FT)
static unsigned getHashValue(const FunctionType *FT)
static FunctionType * getTombstoneKey()
static bool isEqual(const KeyTy &LHS, const FunctionType *RHS)
static unsigned getHashValue(const KeyTy &Key)
static bool isEqual(const FunctionType *LHS, const FunctionType *RHS)
static FunctionType * getEmptyKey()
DenseMapInfo for MDNode subclasses.
static unsigned getHashValue(const KeyTy &Key)
static bool isEqual(const NodeTy *LHS, const NodeTy *RHS)
static bool isEqual(const KeyTy &LHS, const NodeTy *RHS)
static unsigned getHashValue(const NodeTy *N)
MDNodeKeyImpl< NodeTy > KeyTy
static NodeTy * getTombstoneKey()
static NodeTy * getEmptyKey()
bool isKeyOf(const DIBasicType *RHS) const
MDNodeKeyImpl(const DIBasicType *N)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding, uint32_t NumExtraInhabitants, unsigned Flags)
bool isKeyOf(const DICommonBlock *RHS) const
MDNodeKeyImpl(const DICommonBlock *N)
MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, Metadata *File, unsigned LineNo)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, unsigned Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, Metadata *Specification, uint32_t NumExtraInhabitants, Metadata *BitStride)
MDNodeKeyImpl(const DICompositeType *N)
bool isKeyOf(const DICompositeType *RHS) const
std::optional< DIDerivedType::PtrAuthData > PtrAuthData
MDNodeKeyImpl(const DIDerivedType *N)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, std::optional< unsigned > DWARFAddressSpace, std::optional< DIDerivedType::PtrAuthData > PtrAuthData, unsigned Flags, Metadata *ExtraData, Metadata *Annotations)
bool isKeyOf(const DIDerivedType *RHS) const
std::optional< unsigned > DWARFAddressSpace
MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
bool isKeyOf(const DIEnumerator *RHS) const
MDNodeKeyImpl(const DIEnumerator *N)
bool isKeyOf(const DIExpression *RHS) const
MDNodeKeyImpl(const DIExpression *N)
MDNodeKeyImpl(ArrayRef< uint64_t > Elements)
std::optional< DIFile::ChecksumInfo< MDString * > > Checksum
bool isKeyOf(const DIFile *RHS) const
MDNodeKeyImpl(MDString *Filename, MDString *Directory, std::optional< DIFile::ChecksumInfo< MDString * > > Checksum, MDString *Source)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding, unsigned Flags, unsigned Kind, int Factor, APInt Numerator, APInt Denominator)
MDNodeKeyImpl(const DIFixedPointType *N)
bool isKeyOf(const DIFixedPointType *RHS) const
bool isKeyOf(const DIGenericSubrange *RHS) const
MDNodeKeyImpl(const DIGenericSubrange *N)
MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound, Metadata *Stride)
MDNodeKeyImpl(Metadata *Variable, Metadata *Expression)
bool isKeyOf(const DIGlobalVariableExpression *RHS) const
MDNodeKeyImpl(const DIGlobalVariableExpression *N)
bool isKeyOf(const DIGlobalVariable *RHS) const
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, uint32_t AlignInBits, Metadata *Annotations)
MDNodeKeyImpl(const DIGlobalVariable *N)
bool isKeyOf(const DIImportedEntity *RHS) const
MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File, unsigned Line, MDString *Name, Metadata *Elements)
MDNodeKeyImpl(const DIImportedEntity *N)
unsigned getHashValue() const
Using name and line to get hash value. It should already be mostly unique.
bool isKeyOf(const DILabel *RHS) const
std::optional< unsigned > CoroSuspendIdx
MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, unsigned Column, bool IsArtificial, std::optional< unsigned > CoroSuspendIdx)
MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
MDNodeKeyImpl(const DILexicalBlockFile *N)
bool isKeyOf(const DILexicalBlockFile *RHS) const
bool isKeyOf(const DILexicalBlock *RHS) const
MDNodeKeyImpl(const DILexicalBlock *N)
MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)
bool isKeyOf(const DILocalVariable *RHS) const
MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags, uint32_t AlignInBits, Metadata *Annotations)
MDNodeKeyImpl(const DILocalVariable *N)
MDNodeKeyImpl(const DILocation *L)
MDNodeKeyImpl(unsigned Line, uint16_t Column, Metadata *Scope, Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup, uint8_t AtomRank)
bool isKeyOf(const DILocation *RHS) const
MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File, Metadata *Elements)
bool isKeyOf(const DIMacroFile *RHS) const
MDNodeKeyImpl(unsigned MIType, unsigned Line, MDString *Name, MDString *Value)
bool isKeyOf(const DIMacro *RHS) const
MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, MDString *IncludePath, MDString *APINotesFile, unsigned LineNo, bool IsDecl)
bool isKeyOf(const DIModule *RHS) const
MDNodeKeyImpl(Metadata *Scope, MDString *Name, bool ExportSymbols)
bool isKeyOf(const DINamespace *RHS) const
MDNodeKeyImpl(const DIObjCProperty *N)
bool isKeyOf(const DIObjCProperty *RHS) const
MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line, MDString *GetterName, MDString *SetterName, unsigned Attributes, Metadata *Type)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength, Metadata *StringLengthExp, Metadata *StringLocationExp, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding)
MDNodeKeyImpl(const DIStringType *N)
bool isKeyOf(const DIStringType *RHS) const
bool isKeyOf(const DISubprogram *RHS) const
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName, bool UsesKeyInstructions)
MDNodeKeyImpl(const DISubprogram *N)
MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *SizeInBits, uint32_t AlignInBits, unsigned Flags, Metadata *BaseType, Metadata *LowerBound, Metadata *UpperBound, Metadata *Stride, Metadata *Bias)
bool isKeyOf(const DISubrangeType *RHS) const
MDNodeKeyImpl(const DISubrangeType *N)
MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound, Metadata *Stride)
bool isKeyOf(const DISubrange *RHS) const
MDNodeKeyImpl(const DISubrange *N)
bool isKeyOf(const DISubroutineType *RHS) const
MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
MDNodeKeyImpl(const DISubroutineType *N)
MDNodeKeyImpl(const DITemplateTypeParameter *N)
bool isKeyOf(const DITemplateTypeParameter *RHS) const
MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)
MDNodeKeyImpl(const DITemplateValueParameter *N)
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault, Metadata *Value)
bool isKeyOf(const DITemplateValueParameter *RHS) const
static unsigned calculateHash(GenericDINode *N)
MDNodeKeyImpl(const GenericDINode *N)
MDNodeKeyImpl(unsigned Tag, MDString *Header, ArrayRef< Metadata * > DwarfOps)
bool isKeyOf(const GenericDINode *RHS) const
bool isKeyOf(const MDTuple *RHS) const
MDNodeKeyImpl(ArrayRef< Metadata * > Ops)
static unsigned calculateHash(MDTuple *N)
static bool isSubsetEqual(const DIDerivedType *LHS, const DIDerivedType *RHS)
static bool isSubsetEqual(const KeyTy &LHS, const DIDerivedType *RHS)
static bool isODRMember(unsigned Tag, const Metadata *Scope, const MDString *Name, const DIDerivedType *RHS)
Subprograms compare equal if they declare the same function in an ODR type.
static bool isSubsetEqual(const DISubprogram *LHS, const DISubprogram *RHS)
static bool isSubsetEqual(const KeyTy &LHS, const DISubprogram *RHS)
static bool isDeclarationOfODRMember(bool IsDefinition, const Metadata *Scope, const MDString *LinkageName, const Metadata *TemplateParams, const DISubprogram *RHS)
Subprograms compare equal if they declare the same function in an ODR type.
Configuration point for MDNodeInfo::isEqual().
static bool isSubsetEqual(const KeyTy &LHS, const NodeTy *RHS)
static bool isSubsetEqual(const NodeTy *LHS, const NodeTy *RHS)
KeyTy(StringRef N, const ArrayRef< Type * > &TP, const ArrayRef< unsigned > &IP)
bool operator==(const KeyTy &that) const
KeyTy(const TargetExtType *TT)
bool operator!=(const KeyTy &that) const
static unsigned getHashValue(const TargetExtType *FT)
static bool isEqual(const TargetExtType *LHS, const TargetExtType *RHS)
static bool isEqual(const KeyTy &LHS, const TargetExtType *RHS)
static unsigned getHashValue(const KeyTy &Key)
static TargetExtType * getTombstoneKey()
static TargetExtType * getEmptyKey()