xref: /openbsd/gnu/llvm/llvm/lib/IR/LLVMContextImpl.h (revision d415bd75)
109467b48Spatrick //===- LLVMContextImpl.h - The LLVMContextImpl opaque class -----*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick //  This file declares LLVMContextImpl, the opaque implementation
1009467b48Spatrick //  of LLVMContext.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H
1509467b48Spatrick #define LLVM_LIB_IR_LLVMCONTEXTIMPL_H
1609467b48Spatrick 
1709467b48Spatrick #include "ConstantsContext.h"
1809467b48Spatrick #include "llvm/ADT/APFloat.h"
1909467b48Spatrick #include "llvm/ADT/APInt.h"
2009467b48Spatrick #include "llvm/ADT/ArrayRef.h"
2109467b48Spatrick #include "llvm/ADT/DenseMap.h"
2209467b48Spatrick #include "llvm/ADT/DenseMapInfo.h"
2309467b48Spatrick #include "llvm/ADT/DenseSet.h"
2409467b48Spatrick #include "llvm/ADT/FoldingSet.h"
2509467b48Spatrick #include "llvm/ADT/Hashing.h"
2609467b48Spatrick #include "llvm/ADT/STLExtras.h"
2709467b48Spatrick #include "llvm/ADT/SmallPtrSet.h"
2809467b48Spatrick #include "llvm/ADT/SmallVector.h"
2909467b48Spatrick #include "llvm/ADT/StringMap.h"
3009467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
3109467b48Spatrick #include "llvm/IR/Constants.h"
3209467b48Spatrick #include "llvm/IR/DebugInfoMetadata.h"
3309467b48Spatrick #include "llvm/IR/DerivedTypes.h"
3409467b48Spatrick #include "llvm/IR/LLVMContext.h"
3509467b48Spatrick #include "llvm/IR/Metadata.h"
36*d415bd75Srobert #include "llvm/IR/Module.h"
3709467b48Spatrick #include "llvm/IR/TrackingMDRef.h"
38*d415bd75Srobert #include "llvm/IR/Type.h"
39*d415bd75Srobert #include "llvm/IR/Value.h"
4009467b48Spatrick #include "llvm/Support/Allocator.h"
4109467b48Spatrick #include "llvm/Support/Casting.h"
4209467b48Spatrick #include "llvm/Support/StringSaver.h"
4309467b48Spatrick #include <algorithm>
4409467b48Spatrick #include <cassert>
4509467b48Spatrick #include <cstddef>
4609467b48Spatrick #include <cstdint>
4709467b48Spatrick #include <memory>
48*d415bd75Srobert #include <optional>
4909467b48Spatrick #include <string>
5009467b48Spatrick #include <utility>
5109467b48Spatrick #include <vector>
5209467b48Spatrick 
5309467b48Spatrick namespace llvm {
5409467b48Spatrick 
55*d415bd75Srobert class AttributeImpl;
56*d415bd75Srobert class AttributeListImpl;
57*d415bd75Srobert class AttributeSetNode;
58*d415bd75Srobert class BasicBlock;
59*d415bd75Srobert struct DiagnosticHandler;
60*d415bd75Srobert class ElementCount;
61*d415bd75Srobert class Function;
62*d415bd75Srobert class GlobalObject;
63*d415bd75Srobert class GlobalValue;
64*d415bd75Srobert class InlineAsm;
65*d415bd75Srobert class LLVMRemarkStreamer;
66*d415bd75Srobert class OptPassGate;
67*d415bd75Srobert namespace remarks {
68*d415bd75Srobert class RemarkStreamer;
69*d415bd75Srobert }
70*d415bd75Srobert template <typename T> class StringMapEntry;
71097a140dSpatrick class StringRef;
72*d415bd75Srobert class TypedPointerType;
7309467b48Spatrick class ValueHandleBase;
7409467b48Spatrick 
7573471bf0Spatrick using DenseMapAPIntKeyInfo = DenseMapInfo<APInt>;
7609467b48Spatrick 
7709467b48Spatrick struct DenseMapAPFloatKeyInfo {
getEmptyKeyDenseMapAPFloatKeyInfo7809467b48Spatrick   static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus(), 1); }
getTombstoneKeyDenseMapAPFloatKeyInfo79*d415bd75Srobert   static inline APFloat getTombstoneKey() {
80*d415bd75Srobert     return APFloat(APFloat::Bogus(), 2);
81*d415bd75Srobert   }
8209467b48Spatrick 
getHashValueDenseMapAPFloatKeyInfo8309467b48Spatrick   static unsigned getHashValue(const APFloat &Key) {
8409467b48Spatrick     return static_cast<unsigned>(hash_value(Key));
8509467b48Spatrick   }
8609467b48Spatrick 
isEqualDenseMapAPFloatKeyInfo8709467b48Spatrick   static bool isEqual(const APFloat &LHS, const APFloat &RHS) {
8809467b48Spatrick     return LHS.bitwiseIsEqual(RHS);
8909467b48Spatrick   }
9009467b48Spatrick };
9109467b48Spatrick 
9209467b48Spatrick struct AnonStructTypeKeyInfo {
9309467b48Spatrick   struct KeyTy {
9409467b48Spatrick     ArrayRef<Type *> ETypes;
9509467b48Spatrick     bool isPacked;
9609467b48Spatrick 
KeyTyAnonStructTypeKeyInfo::KeyTy97*d415bd75Srobert     KeyTy(const ArrayRef<Type *> &E, bool P) : ETypes(E), isPacked(P) {}
9809467b48Spatrick 
KeyTyAnonStructTypeKeyInfo::KeyTy9909467b48Spatrick     KeyTy(const StructType *ST)
10009467b48Spatrick         : ETypes(ST->elements()), isPacked(ST->isPacked()) {}
10109467b48Spatrick 
10209467b48Spatrick     bool operator==(const KeyTy &that) const {
10309467b48Spatrick       if (isPacked != that.isPacked)
10409467b48Spatrick         return false;
10509467b48Spatrick       if (ETypes != that.ETypes)
10609467b48Spatrick         return false;
10709467b48Spatrick       return true;
10809467b48Spatrick     }
109*d415bd75Srobert     bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
11009467b48Spatrick   };
11109467b48Spatrick 
getEmptyKeyAnonStructTypeKeyInfo11209467b48Spatrick   static inline StructType *getEmptyKey() {
11309467b48Spatrick     return DenseMapInfo<StructType *>::getEmptyKey();
11409467b48Spatrick   }
11509467b48Spatrick 
getTombstoneKeyAnonStructTypeKeyInfo11609467b48Spatrick   static inline StructType *getTombstoneKey() {
11709467b48Spatrick     return DenseMapInfo<StructType *>::getTombstoneKey();
11809467b48Spatrick   }
11909467b48Spatrick 
getHashValueAnonStructTypeKeyInfo12009467b48Spatrick   static unsigned getHashValue(const KeyTy &Key) {
121*d415bd75Srobert     return hash_combine(
122*d415bd75Srobert         hash_combine_range(Key.ETypes.begin(), Key.ETypes.end()), Key.isPacked);
12309467b48Spatrick   }
12409467b48Spatrick 
getHashValueAnonStructTypeKeyInfo12509467b48Spatrick   static unsigned getHashValue(const StructType *ST) {
12609467b48Spatrick     return getHashValue(KeyTy(ST));
12709467b48Spatrick   }
12809467b48Spatrick 
isEqualAnonStructTypeKeyInfo12909467b48Spatrick   static bool isEqual(const KeyTy &LHS, const StructType *RHS) {
13009467b48Spatrick     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
13109467b48Spatrick       return false;
13209467b48Spatrick     return LHS == KeyTy(RHS);
13309467b48Spatrick   }
13409467b48Spatrick 
isEqualAnonStructTypeKeyInfo13509467b48Spatrick   static bool isEqual(const StructType *LHS, const StructType *RHS) {
13609467b48Spatrick     return LHS == RHS;
13709467b48Spatrick   }
13809467b48Spatrick };
13909467b48Spatrick 
14009467b48Spatrick struct FunctionTypeKeyInfo {
14109467b48Spatrick   struct KeyTy {
14209467b48Spatrick     const Type *ReturnType;
14309467b48Spatrick     ArrayRef<Type *> Params;
14409467b48Spatrick     bool isVarArg;
14509467b48Spatrick 
KeyTyFunctionTypeKeyInfo::KeyTy146*d415bd75Srobert     KeyTy(const Type *R, const ArrayRef<Type *> &P, bool V)
147*d415bd75Srobert         : ReturnType(R), Params(P), isVarArg(V) {}
KeyTyFunctionTypeKeyInfo::KeyTy14809467b48Spatrick     KeyTy(const FunctionType *FT)
14909467b48Spatrick         : ReturnType(FT->getReturnType()), Params(FT->params()),
15009467b48Spatrick           isVarArg(FT->isVarArg()) {}
15109467b48Spatrick 
15209467b48Spatrick     bool operator==(const KeyTy &that) const {
15309467b48Spatrick       if (ReturnType != that.ReturnType)
15409467b48Spatrick         return false;
15509467b48Spatrick       if (isVarArg != that.isVarArg)
15609467b48Spatrick         return false;
15709467b48Spatrick       if (Params != that.Params)
15809467b48Spatrick         return false;
15909467b48Spatrick       return true;
16009467b48Spatrick     }
161*d415bd75Srobert     bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
16209467b48Spatrick   };
16309467b48Spatrick 
getEmptyKeyFunctionTypeKeyInfo16409467b48Spatrick   static inline FunctionType *getEmptyKey() {
16509467b48Spatrick     return DenseMapInfo<FunctionType *>::getEmptyKey();
16609467b48Spatrick   }
16709467b48Spatrick 
getTombstoneKeyFunctionTypeKeyInfo16809467b48Spatrick   static inline FunctionType *getTombstoneKey() {
16909467b48Spatrick     return DenseMapInfo<FunctionType *>::getTombstoneKey();
17009467b48Spatrick   }
17109467b48Spatrick 
getHashValueFunctionTypeKeyInfo17209467b48Spatrick   static unsigned getHashValue(const KeyTy &Key) {
173*d415bd75Srobert     return hash_combine(
174*d415bd75Srobert         Key.ReturnType,
175*d415bd75Srobert         hash_combine_range(Key.Params.begin(), Key.Params.end()), Key.isVarArg);
17609467b48Spatrick   }
17709467b48Spatrick 
getHashValueFunctionTypeKeyInfo17809467b48Spatrick   static unsigned getHashValue(const FunctionType *FT) {
17909467b48Spatrick     return getHashValue(KeyTy(FT));
18009467b48Spatrick   }
18109467b48Spatrick 
isEqualFunctionTypeKeyInfo18209467b48Spatrick   static bool isEqual(const KeyTy &LHS, const FunctionType *RHS) {
18309467b48Spatrick     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
18409467b48Spatrick       return false;
18509467b48Spatrick     return LHS == KeyTy(RHS);
18609467b48Spatrick   }
18709467b48Spatrick 
isEqualFunctionTypeKeyInfo18809467b48Spatrick   static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) {
18909467b48Spatrick     return LHS == RHS;
19009467b48Spatrick   }
19109467b48Spatrick };
19209467b48Spatrick 
193*d415bd75Srobert struct TargetExtTypeKeyInfo {
194*d415bd75Srobert   struct KeyTy {
195*d415bd75Srobert     StringRef Name;
196*d415bd75Srobert     ArrayRef<Type *> TypeParams;
197*d415bd75Srobert     ArrayRef<unsigned> IntParams;
198*d415bd75Srobert 
KeyTyTargetExtTypeKeyInfo::KeyTy199*d415bd75Srobert     KeyTy(StringRef N, const ArrayRef<Type *> &TP, const ArrayRef<unsigned> &IP)
200*d415bd75Srobert         : Name(N), TypeParams(TP), IntParams(IP) {}
KeyTyTargetExtTypeKeyInfo::KeyTy201*d415bd75Srobert     KeyTy(const TargetExtType *TT)
202*d415bd75Srobert         : Name(TT->getName()), TypeParams(TT->type_params()),
203*d415bd75Srobert           IntParams(TT->int_params()) {}
204*d415bd75Srobert 
205*d415bd75Srobert     bool operator==(const KeyTy &that) const {
206*d415bd75Srobert       return Name == that.Name && TypeParams == that.TypeParams &&
207*d415bd75Srobert              IntParams == that.IntParams;
208*d415bd75Srobert     }
209*d415bd75Srobert     bool operator!=(const KeyTy &that) const { return !this->operator==(that); }
210*d415bd75Srobert   };
211*d415bd75Srobert 
getEmptyKeyTargetExtTypeKeyInfo212*d415bd75Srobert   static inline TargetExtType *getEmptyKey() {
213*d415bd75Srobert     return DenseMapInfo<TargetExtType *>::getEmptyKey();
214*d415bd75Srobert   }
215*d415bd75Srobert 
getTombstoneKeyTargetExtTypeKeyInfo216*d415bd75Srobert   static inline TargetExtType *getTombstoneKey() {
217*d415bd75Srobert     return DenseMapInfo<TargetExtType *>::getTombstoneKey();
218*d415bd75Srobert   }
219*d415bd75Srobert 
getHashValueTargetExtTypeKeyInfo220*d415bd75Srobert   static unsigned getHashValue(const KeyTy &Key) {
221*d415bd75Srobert     return hash_combine(
222*d415bd75Srobert         Key.Name,
223*d415bd75Srobert         hash_combine_range(Key.TypeParams.begin(), Key.TypeParams.end()),
224*d415bd75Srobert         hash_combine_range(Key.IntParams.begin(), Key.IntParams.end()));
225*d415bd75Srobert   }
226*d415bd75Srobert 
getHashValueTargetExtTypeKeyInfo227*d415bd75Srobert   static unsigned getHashValue(const TargetExtType *FT) {
228*d415bd75Srobert     return getHashValue(KeyTy(FT));
229*d415bd75Srobert   }
230*d415bd75Srobert 
isEqualTargetExtTypeKeyInfo231*d415bd75Srobert   static bool isEqual(const KeyTy &LHS, const TargetExtType *RHS) {
232*d415bd75Srobert     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
233*d415bd75Srobert       return false;
234*d415bd75Srobert     return LHS == KeyTy(RHS);
235*d415bd75Srobert   }
236*d415bd75Srobert 
isEqualTargetExtTypeKeyInfo237*d415bd75Srobert   static bool isEqual(const TargetExtType *LHS, const TargetExtType *RHS) {
238*d415bd75Srobert     return LHS == RHS;
239*d415bd75Srobert   }
240*d415bd75Srobert };
241*d415bd75Srobert 
24209467b48Spatrick /// Structure for hashing arbitrary MDNode operands.
24309467b48Spatrick class MDNodeOpsKey {
24409467b48Spatrick   ArrayRef<Metadata *> RawOps;
24509467b48Spatrick   ArrayRef<MDOperand> Ops;
24609467b48Spatrick   unsigned Hash;
24709467b48Spatrick 
24809467b48Spatrick protected:
MDNodeOpsKey(ArrayRef<Metadata * > Ops)24909467b48Spatrick   MDNodeOpsKey(ArrayRef<Metadata *> Ops)
25009467b48Spatrick       : RawOps(Ops), Hash(calculateHash(Ops)) {}
25109467b48Spatrick 
25209467b48Spatrick   template <class NodeTy>
25309467b48Spatrick   MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0)
25409467b48Spatrick       : Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
25509467b48Spatrick 
25609467b48Spatrick   template <class NodeTy>
25709467b48Spatrick   bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
25809467b48Spatrick     if (getHash() != RHS->getHash())
25909467b48Spatrick       return false;
26009467b48Spatrick 
26109467b48Spatrick     assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
26209467b48Spatrick     return RawOps.empty() ? compareOps(Ops, RHS, Offset)
26309467b48Spatrick                           : compareOps(RawOps, RHS, Offset);
26409467b48Spatrick   }
26509467b48Spatrick 
26609467b48Spatrick   static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
26709467b48Spatrick 
26809467b48Spatrick private:
26909467b48Spatrick   template <class T>
compareOps(ArrayRef<T> Ops,const MDNode * RHS,unsigned Offset)27009467b48Spatrick   static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
27109467b48Spatrick     if (Ops.size() != RHS->getNumOperands() - Offset)
27209467b48Spatrick       return false;
27309467b48Spatrick     return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
27409467b48Spatrick   }
27509467b48Spatrick 
27609467b48Spatrick   static unsigned calculateHash(ArrayRef<Metadata *> Ops);
27709467b48Spatrick 
27809467b48Spatrick public:
getHash()27909467b48Spatrick   unsigned getHash() const { return Hash; }
28009467b48Spatrick };
28109467b48Spatrick 
28209467b48Spatrick template <class NodeTy> struct MDNodeKeyImpl;
28309467b48Spatrick 
28409467b48Spatrick /// Configuration point for MDNodeInfo::isEqual().
28509467b48Spatrick template <class NodeTy> struct MDNodeSubsetEqualImpl {
28609467b48Spatrick   using KeyTy = MDNodeKeyImpl<NodeTy>;
28709467b48Spatrick 
isSubsetEqualMDNodeSubsetEqualImpl28809467b48Spatrick   static bool isSubsetEqual(const KeyTy &LHS, const NodeTy *RHS) {
28909467b48Spatrick     return false;
29009467b48Spatrick   }
29109467b48Spatrick 
isSubsetEqualMDNodeSubsetEqualImpl29209467b48Spatrick   static bool isSubsetEqual(const NodeTy *LHS, const NodeTy *RHS) {
29309467b48Spatrick     return false;
29409467b48Spatrick   }
29509467b48Spatrick };
29609467b48Spatrick 
29709467b48Spatrick /// DenseMapInfo for MDTuple.
29809467b48Spatrick ///
29909467b48Spatrick /// Note that we don't need the is-function-local bit, since that's implicit in
30009467b48Spatrick /// the operands.
30109467b48Spatrick template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {
30209467b48Spatrick   MDNodeKeyImpl(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {}
30309467b48Spatrick   MDNodeKeyImpl(const MDTuple *N) : MDNodeOpsKey(N) {}
30409467b48Spatrick 
30509467b48Spatrick   bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); }
30609467b48Spatrick 
30709467b48Spatrick   unsigned getHashValue() const { return getHash(); }
30809467b48Spatrick 
30909467b48Spatrick   static unsigned calculateHash(MDTuple *N) {
31009467b48Spatrick     return MDNodeOpsKey::calculateHash(N);
31109467b48Spatrick   }
31209467b48Spatrick };
31309467b48Spatrick 
31409467b48Spatrick /// DenseMapInfo for DILocation.
31509467b48Spatrick template <> struct MDNodeKeyImpl<DILocation> {
31609467b48Spatrick   unsigned Line;
31709467b48Spatrick   unsigned Column;
31809467b48Spatrick   Metadata *Scope;
31909467b48Spatrick   Metadata *InlinedAt;
32009467b48Spatrick   bool ImplicitCode;
32109467b48Spatrick 
32209467b48Spatrick   MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope,
32309467b48Spatrick                 Metadata *InlinedAt, bool ImplicitCode)
32409467b48Spatrick       : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt),
32509467b48Spatrick         ImplicitCode(ImplicitCode) {}
32609467b48Spatrick   MDNodeKeyImpl(const DILocation *L)
32709467b48Spatrick       : Line(L->getLine()), Column(L->getColumn()), Scope(L->getRawScope()),
32809467b48Spatrick         InlinedAt(L->getRawInlinedAt()), ImplicitCode(L->isImplicitCode()) {}
32909467b48Spatrick 
33009467b48Spatrick   bool isKeyOf(const DILocation *RHS) const {
33109467b48Spatrick     return Line == RHS->getLine() && Column == RHS->getColumn() &&
33209467b48Spatrick            Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() &&
33309467b48Spatrick            ImplicitCode == RHS->isImplicitCode();
33409467b48Spatrick   }
33509467b48Spatrick 
33609467b48Spatrick   unsigned getHashValue() const {
33709467b48Spatrick     return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode);
33809467b48Spatrick   }
33909467b48Spatrick };
34009467b48Spatrick 
34109467b48Spatrick /// DenseMapInfo for GenericDINode.
34209467b48Spatrick template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey {
34309467b48Spatrick   unsigned Tag;
34409467b48Spatrick   MDString *Header;
34509467b48Spatrick 
34609467b48Spatrick   MDNodeKeyImpl(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)
34709467b48Spatrick       : MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
34809467b48Spatrick   MDNodeKeyImpl(const GenericDINode *N)
34909467b48Spatrick       : MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getRawHeader()) {}
35009467b48Spatrick 
35109467b48Spatrick   bool isKeyOf(const GenericDINode *RHS) const {
35209467b48Spatrick     return Tag == RHS->getTag() && Header == RHS->getRawHeader() &&
35309467b48Spatrick            compareOps(RHS, 1);
35409467b48Spatrick   }
35509467b48Spatrick 
35609467b48Spatrick   unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); }
35709467b48Spatrick 
35809467b48Spatrick   static unsigned calculateHash(GenericDINode *N) {
35909467b48Spatrick     return MDNodeOpsKey::calculateHash(N, 1);
36009467b48Spatrick   }
36109467b48Spatrick };
36209467b48Spatrick 
36309467b48Spatrick template <> struct MDNodeKeyImpl<DISubrange> {
36409467b48Spatrick   Metadata *CountNode;
365097a140dSpatrick   Metadata *LowerBound;
366097a140dSpatrick   Metadata *UpperBound;
367097a140dSpatrick   Metadata *Stride;
36809467b48Spatrick 
369097a140dSpatrick   MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,
370097a140dSpatrick                 Metadata *Stride)
371097a140dSpatrick       : CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),
372097a140dSpatrick         Stride(Stride) {}
37309467b48Spatrick   MDNodeKeyImpl(const DISubrange *N)
374097a140dSpatrick       : CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),
375097a140dSpatrick         UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}
37609467b48Spatrick 
37709467b48Spatrick   bool isKeyOf(const DISubrange *RHS) const {
378097a140dSpatrick     auto BoundsEqual = [=](Metadata *Node1, Metadata *Node2) -> bool {
379097a140dSpatrick       if (Node1 == Node2)
38009467b48Spatrick         return true;
38109467b48Spatrick 
382097a140dSpatrick       ConstantAsMetadata *MD1 = dyn_cast_or_null<ConstantAsMetadata>(Node1);
383097a140dSpatrick       ConstantAsMetadata *MD2 = dyn_cast_or_null<ConstantAsMetadata>(Node2);
384097a140dSpatrick       if (MD1 && MD2) {
385097a140dSpatrick         ConstantInt *CV1 = cast<ConstantInt>(MD1->getValue());
386097a140dSpatrick         ConstantInt *CV2 = cast<ConstantInt>(MD2->getValue());
387097a140dSpatrick         if (CV1->getSExtValue() == CV2->getSExtValue())
388097a140dSpatrick           return true;
389097a140dSpatrick       }
390097a140dSpatrick       return false;
391097a140dSpatrick     };
392097a140dSpatrick 
393097a140dSpatrick     return BoundsEqual(CountNode, RHS->getRawCountNode()) &&
394097a140dSpatrick            BoundsEqual(LowerBound, RHS->getRawLowerBound()) &&
395097a140dSpatrick            BoundsEqual(UpperBound, RHS->getRawUpperBound()) &&
396097a140dSpatrick            BoundsEqual(Stride, RHS->getRawStride());
39709467b48Spatrick   }
39809467b48Spatrick 
39909467b48Spatrick   unsigned getHashValue() const {
400097a140dSpatrick     if (CountNode)
40109467b48Spatrick       if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
40209467b48Spatrick         return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
403097a140dSpatrick                             LowerBound, UpperBound, Stride);
404097a140dSpatrick     return hash_combine(CountNode, LowerBound, UpperBound, Stride);
40509467b48Spatrick   }
40609467b48Spatrick };
40709467b48Spatrick 
40873471bf0Spatrick template <> struct MDNodeKeyImpl<DIGenericSubrange> {
40973471bf0Spatrick   Metadata *CountNode;
41073471bf0Spatrick   Metadata *LowerBound;
41173471bf0Spatrick   Metadata *UpperBound;
41273471bf0Spatrick   Metadata *Stride;
41373471bf0Spatrick 
41473471bf0Spatrick   MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,
41573471bf0Spatrick                 Metadata *Stride)
41673471bf0Spatrick       : CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),
41773471bf0Spatrick         Stride(Stride) {}
41873471bf0Spatrick   MDNodeKeyImpl(const DIGenericSubrange *N)
41973471bf0Spatrick       : CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),
42073471bf0Spatrick         UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}
42173471bf0Spatrick 
42273471bf0Spatrick   bool isKeyOf(const DIGenericSubrange *RHS) const {
42373471bf0Spatrick     return (CountNode == RHS->getRawCountNode()) &&
42473471bf0Spatrick            (LowerBound == RHS->getRawLowerBound()) &&
42573471bf0Spatrick            (UpperBound == RHS->getRawUpperBound()) &&
42673471bf0Spatrick            (Stride == RHS->getRawStride());
42773471bf0Spatrick   }
42873471bf0Spatrick 
42973471bf0Spatrick   unsigned getHashValue() const {
43073471bf0Spatrick     auto *MD = dyn_cast_or_null<ConstantAsMetadata>(CountNode);
43173471bf0Spatrick     if (CountNode && MD)
43273471bf0Spatrick       return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
43373471bf0Spatrick                           LowerBound, UpperBound, Stride);
43473471bf0Spatrick     return hash_combine(CountNode, LowerBound, UpperBound, Stride);
43573471bf0Spatrick   }
43673471bf0Spatrick };
43773471bf0Spatrick 
43809467b48Spatrick template <> struct MDNodeKeyImpl<DIEnumerator> {
439097a140dSpatrick   APInt Value;
44009467b48Spatrick   MDString *Name;
44109467b48Spatrick   bool IsUnsigned;
44209467b48Spatrick 
443097a140dSpatrick   MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)
44409467b48Spatrick       : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
445097a140dSpatrick   MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
446097a140dSpatrick       : Value(APInt(64, Value, !IsUnsigned)), Name(Name),
447097a140dSpatrick         IsUnsigned(IsUnsigned) {}
44809467b48Spatrick   MDNodeKeyImpl(const DIEnumerator *N)
44909467b48Spatrick       : Value(N->getValue()), Name(N->getRawName()),
45009467b48Spatrick         IsUnsigned(N->isUnsigned()) {}
45109467b48Spatrick 
45209467b48Spatrick   bool isKeyOf(const DIEnumerator *RHS) const {
453*d415bd75Srobert     return Value.getBitWidth() == RHS->getValue().getBitWidth() &&
454*d415bd75Srobert            Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&
455*d415bd75Srobert            Name == RHS->getRawName();
45609467b48Spatrick   }
45709467b48Spatrick 
45809467b48Spatrick   unsigned getHashValue() const { return hash_combine(Value, Name); }
45909467b48Spatrick };
46009467b48Spatrick 
46109467b48Spatrick template <> struct MDNodeKeyImpl<DIBasicType> {
46209467b48Spatrick   unsigned Tag;
46309467b48Spatrick   MDString *Name;
46409467b48Spatrick   uint64_t SizeInBits;
46509467b48Spatrick   uint32_t AlignInBits;
46609467b48Spatrick   unsigned Encoding;
46709467b48Spatrick   unsigned Flags;
46809467b48Spatrick 
46909467b48Spatrick   MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,
47009467b48Spatrick                 uint32_t AlignInBits, unsigned Encoding, unsigned Flags)
47109467b48Spatrick       : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
47209467b48Spatrick         Encoding(Encoding), Flags(Flags) {}
47309467b48Spatrick   MDNodeKeyImpl(const DIBasicType *N)
47409467b48Spatrick       : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),
475*d415bd75Srobert         AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()),
476*d415bd75Srobert         Flags(N->getFlags()) {}
47709467b48Spatrick 
47809467b48Spatrick   bool isKeyOf(const DIBasicType *RHS) const {
47909467b48Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
48009467b48Spatrick            SizeInBits == RHS->getSizeInBits() &&
48109467b48Spatrick            AlignInBits == RHS->getAlignInBits() &&
482*d415bd75Srobert            Encoding == RHS->getEncoding() && Flags == RHS->getFlags();
48309467b48Spatrick   }
48409467b48Spatrick 
48509467b48Spatrick   unsigned getHashValue() const {
48609467b48Spatrick     return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
48709467b48Spatrick   }
48809467b48Spatrick };
48909467b48Spatrick 
49073471bf0Spatrick template <> struct MDNodeKeyImpl<DIStringType> {
49173471bf0Spatrick   unsigned Tag;
49273471bf0Spatrick   MDString *Name;
49373471bf0Spatrick   Metadata *StringLength;
49473471bf0Spatrick   Metadata *StringLengthExp;
495*d415bd75Srobert   Metadata *StringLocationExp;
49673471bf0Spatrick   uint64_t SizeInBits;
49773471bf0Spatrick   uint32_t AlignInBits;
49873471bf0Spatrick   unsigned Encoding;
49973471bf0Spatrick 
50073471bf0Spatrick   MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength,
501*d415bd75Srobert                 Metadata *StringLengthExp, Metadata *StringLocationExp,
502*d415bd75Srobert                 uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding)
50373471bf0Spatrick       : Tag(Tag), Name(Name), StringLength(StringLength),
504*d415bd75Srobert         StringLengthExp(StringLengthExp), StringLocationExp(StringLocationExp),
505*d415bd75Srobert         SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding) {}
50673471bf0Spatrick   MDNodeKeyImpl(const DIStringType *N)
50773471bf0Spatrick       : Tag(N->getTag()), Name(N->getRawName()),
50873471bf0Spatrick         StringLength(N->getRawStringLength()),
50973471bf0Spatrick         StringLengthExp(N->getRawStringLengthExp()),
510*d415bd75Srobert         StringLocationExp(N->getRawStringLocationExp()),
51173471bf0Spatrick         SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
51273471bf0Spatrick         Encoding(N->getEncoding()) {}
51373471bf0Spatrick 
51473471bf0Spatrick   bool isKeyOf(const DIStringType *RHS) const {
51573471bf0Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
51673471bf0Spatrick            SizeInBits == RHS->getSizeInBits() &&
51773471bf0Spatrick            AlignInBits == RHS->getAlignInBits() &&
51873471bf0Spatrick            Encoding == RHS->getEncoding();
51973471bf0Spatrick   }
52073471bf0Spatrick   unsigned getHashValue() const { return hash_combine(Tag, Name, Encoding); }
52173471bf0Spatrick };
52273471bf0Spatrick 
52309467b48Spatrick template <> struct MDNodeKeyImpl<DIDerivedType> {
52409467b48Spatrick   unsigned Tag;
52509467b48Spatrick   MDString *Name;
52609467b48Spatrick   Metadata *File;
52709467b48Spatrick   unsigned Line;
52809467b48Spatrick   Metadata *Scope;
52909467b48Spatrick   Metadata *BaseType;
53009467b48Spatrick   uint64_t SizeInBits;
53109467b48Spatrick   uint64_t OffsetInBits;
53209467b48Spatrick   uint32_t AlignInBits;
533*d415bd75Srobert   std::optional<unsigned> DWARFAddressSpace;
53409467b48Spatrick   unsigned Flags;
53509467b48Spatrick   Metadata *ExtraData;
536*d415bd75Srobert   Metadata *Annotations;
53709467b48Spatrick 
53809467b48Spatrick   MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
53909467b48Spatrick                 Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
54009467b48Spatrick                 uint32_t AlignInBits, uint64_t OffsetInBits,
541*d415bd75Srobert                 std::optional<unsigned> DWARFAddressSpace, unsigned Flags,
542*d415bd75Srobert                 Metadata *ExtraData, Metadata *Annotations)
54309467b48Spatrick       : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
54409467b48Spatrick         BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
54509467b48Spatrick         AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace),
546*d415bd75Srobert         Flags(Flags), ExtraData(ExtraData), Annotations(Annotations) {}
54709467b48Spatrick   MDNodeKeyImpl(const DIDerivedType *N)
54809467b48Spatrick       : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
54909467b48Spatrick         Line(N->getLine()), Scope(N->getRawScope()),
55009467b48Spatrick         BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),
55109467b48Spatrick         OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),
55209467b48Spatrick         DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()),
553*d415bd75Srobert         ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {}
55409467b48Spatrick 
55509467b48Spatrick   bool isKeyOf(const DIDerivedType *RHS) const {
55609467b48Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
55709467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine() &&
55809467b48Spatrick            Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
55909467b48Spatrick            SizeInBits == RHS->getSizeInBits() &&
56009467b48Spatrick            AlignInBits == RHS->getAlignInBits() &&
56109467b48Spatrick            OffsetInBits == RHS->getOffsetInBits() &&
56209467b48Spatrick            DWARFAddressSpace == RHS->getDWARFAddressSpace() &&
563*d415bd75Srobert            Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData() &&
564*d415bd75Srobert            Annotations == RHS->getRawAnnotations();
56509467b48Spatrick   }
56609467b48Spatrick 
56709467b48Spatrick   unsigned getHashValue() const {
56809467b48Spatrick     // If this is a member inside an ODR type, only hash the type and the name.
56909467b48Spatrick     // Otherwise the hash will be stronger than
57009467b48Spatrick     // MDNodeSubsetEqualImpl::isODRMember().
57109467b48Spatrick     if (Tag == dwarf::DW_TAG_member && Name)
57209467b48Spatrick       if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
57309467b48Spatrick         if (CT->getRawIdentifier())
57409467b48Spatrick           return hash_combine(Name, Scope);
57509467b48Spatrick 
57609467b48Spatrick     // Intentionally computes the hash on a subset of the operands for
57709467b48Spatrick     // performance reason. The subset has to be significant enough to avoid
57809467b48Spatrick     // collision "most of the time". There is no correctness issue in case of
57909467b48Spatrick     // collision because of the full check above.
58009467b48Spatrick     return hash_combine(Tag, Name, File, Line, Scope, BaseType, Flags);
58109467b48Spatrick   }
58209467b48Spatrick };
58309467b48Spatrick 
58409467b48Spatrick template <> struct MDNodeSubsetEqualImpl<DIDerivedType> {
58509467b48Spatrick   using KeyTy = MDNodeKeyImpl<DIDerivedType>;
58609467b48Spatrick 
58709467b48Spatrick   static bool isSubsetEqual(const KeyTy &LHS, const DIDerivedType *RHS) {
58809467b48Spatrick     return isODRMember(LHS.Tag, LHS.Scope, LHS.Name, RHS);
58909467b48Spatrick   }
59009467b48Spatrick 
591*d415bd75Srobert   static bool isSubsetEqual(const DIDerivedType *LHS,
592*d415bd75Srobert                             const DIDerivedType *RHS) {
59309467b48Spatrick     return isODRMember(LHS->getTag(), LHS->getRawScope(), LHS->getRawName(),
59409467b48Spatrick                        RHS);
59509467b48Spatrick   }
59609467b48Spatrick 
59709467b48Spatrick   /// Subprograms compare equal if they declare the same function in an ODR
59809467b48Spatrick   /// type.
59909467b48Spatrick   static bool isODRMember(unsigned Tag, const Metadata *Scope,
60009467b48Spatrick                           const MDString *Name, const DIDerivedType *RHS) {
60109467b48Spatrick     // Check whether the LHS is eligible.
60209467b48Spatrick     if (Tag != dwarf::DW_TAG_member || !Name)
60309467b48Spatrick       return false;
60409467b48Spatrick 
60509467b48Spatrick     auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
60609467b48Spatrick     if (!CT || !CT->getRawIdentifier())
60709467b48Spatrick       return false;
60809467b48Spatrick 
60909467b48Spatrick     // Compare to the RHS.
61009467b48Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
61109467b48Spatrick            Scope == RHS->getRawScope();
61209467b48Spatrick   }
61309467b48Spatrick };
61409467b48Spatrick 
61509467b48Spatrick template <> struct MDNodeKeyImpl<DICompositeType> {
61609467b48Spatrick   unsigned Tag;
61709467b48Spatrick   MDString *Name;
61809467b48Spatrick   Metadata *File;
61909467b48Spatrick   unsigned Line;
62009467b48Spatrick   Metadata *Scope;
62109467b48Spatrick   Metadata *BaseType;
62209467b48Spatrick   uint64_t SizeInBits;
62309467b48Spatrick   uint64_t OffsetInBits;
62409467b48Spatrick   uint32_t AlignInBits;
62509467b48Spatrick   unsigned Flags;
62609467b48Spatrick   Metadata *Elements;
62709467b48Spatrick   unsigned RuntimeLang;
62809467b48Spatrick   Metadata *VTableHolder;
62909467b48Spatrick   Metadata *TemplateParams;
63009467b48Spatrick   MDString *Identifier;
63109467b48Spatrick   Metadata *Discriminator;
632097a140dSpatrick   Metadata *DataLocation;
63373471bf0Spatrick   Metadata *Associated;
63473471bf0Spatrick   Metadata *Allocated;
63573471bf0Spatrick   Metadata *Rank;
636*d415bd75Srobert   Metadata *Annotations;
63709467b48Spatrick 
63809467b48Spatrick   MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
63909467b48Spatrick                 Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
64009467b48Spatrick                 uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
64109467b48Spatrick                 Metadata *Elements, unsigned RuntimeLang,
64209467b48Spatrick                 Metadata *VTableHolder, Metadata *TemplateParams,
643097a140dSpatrick                 MDString *Identifier, Metadata *Discriminator,
64473471bf0Spatrick                 Metadata *DataLocation, Metadata *Associated,
645*d415bd75Srobert                 Metadata *Allocated, Metadata *Rank, Metadata *Annotations)
64609467b48Spatrick       : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
64709467b48Spatrick         BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
64809467b48Spatrick         AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
64909467b48Spatrick         RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
65009467b48Spatrick         TemplateParams(TemplateParams), Identifier(Identifier),
65173471bf0Spatrick         Discriminator(Discriminator), DataLocation(DataLocation),
652*d415bd75Srobert         Associated(Associated), Allocated(Allocated), Rank(Rank),
653*d415bd75Srobert         Annotations(Annotations) {}
65409467b48Spatrick   MDNodeKeyImpl(const DICompositeType *N)
65509467b48Spatrick       : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
65609467b48Spatrick         Line(N->getLine()), Scope(N->getRawScope()),
65709467b48Spatrick         BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),
65809467b48Spatrick         OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),
65909467b48Spatrick         Flags(N->getFlags()), Elements(N->getRawElements()),
66009467b48Spatrick         RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
66109467b48Spatrick         TemplateParams(N->getRawTemplateParams()),
66209467b48Spatrick         Identifier(N->getRawIdentifier()),
663097a140dSpatrick         Discriminator(N->getRawDiscriminator()),
66473471bf0Spatrick         DataLocation(N->getRawDataLocation()),
66573471bf0Spatrick         Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()),
666*d415bd75Srobert         Rank(N->getRawRank()), Annotations(N->getRawAnnotations()) {}
66709467b48Spatrick 
66809467b48Spatrick   bool isKeyOf(const DICompositeType *RHS) const {
66909467b48Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
67009467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine() &&
67109467b48Spatrick            Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
67209467b48Spatrick            SizeInBits == RHS->getSizeInBits() &&
67309467b48Spatrick            AlignInBits == RHS->getAlignInBits() &&
67409467b48Spatrick            OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
67509467b48Spatrick            Elements == RHS->getRawElements() &&
67609467b48Spatrick            RuntimeLang == RHS->getRuntimeLang() &&
67709467b48Spatrick            VTableHolder == RHS->getRawVTableHolder() &&
67809467b48Spatrick            TemplateParams == RHS->getRawTemplateParams() &&
67909467b48Spatrick            Identifier == RHS->getRawIdentifier() &&
680097a140dSpatrick            Discriminator == RHS->getRawDiscriminator() &&
68173471bf0Spatrick            DataLocation == RHS->getRawDataLocation() &&
68273471bf0Spatrick            Associated == RHS->getRawAssociated() &&
683*d415bd75Srobert            Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() &&
684*d415bd75Srobert            Annotations == RHS->getRawAnnotations();
68509467b48Spatrick   }
68609467b48Spatrick 
68709467b48Spatrick   unsigned getHashValue() const {
68809467b48Spatrick     // Intentionally computes the hash on a subset of the operands for
68909467b48Spatrick     // performance reason. The subset has to be significant enough to avoid
69009467b48Spatrick     // collision "most of the time". There is no correctness issue in case of
69109467b48Spatrick     // collision because of the full check above.
69209467b48Spatrick     return hash_combine(Name, File, Line, BaseType, Scope, Elements,
693*d415bd75Srobert                         TemplateParams, Annotations);
69409467b48Spatrick   }
69509467b48Spatrick };
69609467b48Spatrick 
69709467b48Spatrick template <> struct MDNodeKeyImpl<DISubroutineType> {
69809467b48Spatrick   unsigned Flags;
69909467b48Spatrick   uint8_t CC;
70009467b48Spatrick   Metadata *TypeArray;
70109467b48Spatrick 
70209467b48Spatrick   MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
70309467b48Spatrick       : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
70409467b48Spatrick   MDNodeKeyImpl(const DISubroutineType *N)
70509467b48Spatrick       : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
70609467b48Spatrick 
70709467b48Spatrick   bool isKeyOf(const DISubroutineType *RHS) const {
70809467b48Spatrick     return Flags == RHS->getFlags() && CC == RHS->getCC() &&
70909467b48Spatrick            TypeArray == RHS->getRawTypeArray();
71009467b48Spatrick   }
71109467b48Spatrick 
71209467b48Spatrick   unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
71309467b48Spatrick };
71409467b48Spatrick 
71509467b48Spatrick template <> struct MDNodeKeyImpl<DIFile> {
71609467b48Spatrick   MDString *Filename;
71709467b48Spatrick   MDString *Directory;
718*d415bd75Srobert   std::optional<DIFile::ChecksumInfo<MDString *>> Checksum;
719*d415bd75Srobert   MDString *Source;
72009467b48Spatrick 
72109467b48Spatrick   MDNodeKeyImpl(MDString *Filename, MDString *Directory,
722*d415bd75Srobert                 std::optional<DIFile::ChecksumInfo<MDString *>> Checksum,
723*d415bd75Srobert                 MDString *Source)
72409467b48Spatrick       : Filename(Filename), Directory(Directory), Checksum(Checksum),
72509467b48Spatrick         Source(Source) {}
72609467b48Spatrick   MDNodeKeyImpl(const DIFile *N)
72709467b48Spatrick       : Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
72809467b48Spatrick         Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
72909467b48Spatrick 
73009467b48Spatrick   bool isKeyOf(const DIFile *RHS) const {
73109467b48Spatrick     return Filename == RHS->getRawFilename() &&
73209467b48Spatrick            Directory == RHS->getRawDirectory() &&
733*d415bd75Srobert            Checksum == RHS->getRawChecksum() && Source == RHS->getRawSource();
73409467b48Spatrick   }
73509467b48Spatrick 
73609467b48Spatrick   unsigned getHashValue() const {
737*d415bd75Srobert     return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0,
738*d415bd75Srobert                         Checksum ? Checksum->Value : nullptr, Source);
73909467b48Spatrick   }
74009467b48Spatrick };
74109467b48Spatrick 
74209467b48Spatrick template <> struct MDNodeKeyImpl<DISubprogram> {
74309467b48Spatrick   Metadata *Scope;
74409467b48Spatrick   MDString *Name;
74509467b48Spatrick   MDString *LinkageName;
74609467b48Spatrick   Metadata *File;
74709467b48Spatrick   unsigned Line;
74809467b48Spatrick   Metadata *Type;
74909467b48Spatrick   unsigned ScopeLine;
75009467b48Spatrick   Metadata *ContainingType;
75109467b48Spatrick   unsigned VirtualIndex;
75209467b48Spatrick   int ThisAdjustment;
75309467b48Spatrick   unsigned Flags;
75409467b48Spatrick   unsigned SPFlags;
75509467b48Spatrick   Metadata *Unit;
75609467b48Spatrick   Metadata *TemplateParams;
75709467b48Spatrick   Metadata *Declaration;
75809467b48Spatrick   Metadata *RetainedNodes;
75909467b48Spatrick   Metadata *ThrownTypes;
760*d415bd75Srobert   Metadata *Annotations;
761*d415bd75Srobert   MDString *TargetFuncName;
76209467b48Spatrick 
76309467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
76409467b48Spatrick                 Metadata *File, unsigned Line, Metadata *Type,
76509467b48Spatrick                 unsigned ScopeLine, Metadata *ContainingType,
76609467b48Spatrick                 unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
76709467b48Spatrick                 unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams,
76809467b48Spatrick                 Metadata *Declaration, Metadata *RetainedNodes,
769*d415bd75Srobert                 Metadata *ThrownTypes, Metadata *Annotations,
770*d415bd75Srobert                 MDString *TargetFuncName)
77109467b48Spatrick       : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
77209467b48Spatrick         Line(Line), Type(Type), ScopeLine(ScopeLine),
77309467b48Spatrick         ContainingType(ContainingType), VirtualIndex(VirtualIndex),
77409467b48Spatrick         ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags),
77509467b48Spatrick         Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration),
776*d415bd75Srobert         RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes),
777*d415bd75Srobert         Annotations(Annotations), TargetFuncName(TargetFuncName) {}
77809467b48Spatrick   MDNodeKeyImpl(const DISubprogram *N)
77909467b48Spatrick       : Scope(N->getRawScope()), Name(N->getRawName()),
78009467b48Spatrick         LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
78109467b48Spatrick         Line(N->getLine()), Type(N->getRawType()), ScopeLine(N->getScopeLine()),
78209467b48Spatrick         ContainingType(N->getRawContainingType()),
78309467b48Spatrick         VirtualIndex(N->getVirtualIndex()),
78409467b48Spatrick         ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),
78509467b48Spatrick         SPFlags(N->getSPFlags()), Unit(N->getRawUnit()),
78609467b48Spatrick         TemplateParams(N->getRawTemplateParams()),
78709467b48Spatrick         Declaration(N->getRawDeclaration()),
78809467b48Spatrick         RetainedNodes(N->getRawRetainedNodes()),
789*d415bd75Srobert         ThrownTypes(N->getRawThrownTypes()),
790*d415bd75Srobert         Annotations(N->getRawAnnotations()),
791*d415bd75Srobert         TargetFuncName(N->getRawTargetFuncName()) {}
79209467b48Spatrick 
79309467b48Spatrick   bool isKeyOf(const DISubprogram *RHS) const {
79409467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
79509467b48Spatrick            LinkageName == RHS->getRawLinkageName() &&
79609467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine() &&
79709467b48Spatrick            Type == RHS->getRawType() && ScopeLine == RHS->getScopeLine() &&
79809467b48Spatrick            ContainingType == RHS->getRawContainingType() &&
79909467b48Spatrick            VirtualIndex == RHS->getVirtualIndex() &&
80009467b48Spatrick            ThisAdjustment == RHS->getThisAdjustment() &&
80109467b48Spatrick            Flags == RHS->getFlags() && SPFlags == RHS->getSPFlags() &&
80209467b48Spatrick            Unit == RHS->getUnit() &&
80309467b48Spatrick            TemplateParams == RHS->getRawTemplateParams() &&
80409467b48Spatrick            Declaration == RHS->getRawDeclaration() &&
80509467b48Spatrick            RetainedNodes == RHS->getRawRetainedNodes() &&
806*d415bd75Srobert            ThrownTypes == RHS->getRawThrownTypes() &&
807*d415bd75Srobert            Annotations == RHS->getRawAnnotations() &&
808*d415bd75Srobert            TargetFuncName == RHS->getRawTargetFuncName();
80909467b48Spatrick   }
81009467b48Spatrick 
81109467b48Spatrick   bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; }
81209467b48Spatrick 
81309467b48Spatrick   unsigned getHashValue() const {
81409467b48Spatrick     // If this is a declaration inside an ODR type, only hash the type and the
81509467b48Spatrick     // name.  Otherwise the hash will be stronger than
81609467b48Spatrick     // MDNodeSubsetEqualImpl::isDeclarationOfODRMember().
81709467b48Spatrick     if (!isDefinition() && LinkageName)
81809467b48Spatrick       if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
81909467b48Spatrick         if (CT->getRawIdentifier())
82009467b48Spatrick           return hash_combine(LinkageName, Scope);
82109467b48Spatrick 
82209467b48Spatrick     // Intentionally computes the hash on a subset of the operands for
82309467b48Spatrick     // performance reason. The subset has to be significant enough to avoid
82409467b48Spatrick     // collision "most of the time". There is no correctness issue in case of
82509467b48Spatrick     // collision because of the full check above.
82609467b48Spatrick     return hash_combine(Name, Scope, File, Type, Line);
82709467b48Spatrick   }
82809467b48Spatrick };
82909467b48Spatrick 
83009467b48Spatrick template <> struct MDNodeSubsetEqualImpl<DISubprogram> {
83109467b48Spatrick   using KeyTy = MDNodeKeyImpl<DISubprogram>;
83209467b48Spatrick 
83309467b48Spatrick   static bool isSubsetEqual(const KeyTy &LHS, const DISubprogram *RHS) {
83409467b48Spatrick     return isDeclarationOfODRMember(LHS.isDefinition(), LHS.Scope,
83509467b48Spatrick                                     LHS.LinkageName, LHS.TemplateParams, RHS);
83609467b48Spatrick   }
83709467b48Spatrick 
83809467b48Spatrick   static bool isSubsetEqual(const DISubprogram *LHS, const DISubprogram *RHS) {
83909467b48Spatrick     return isDeclarationOfODRMember(LHS->isDefinition(), LHS->getRawScope(),
84009467b48Spatrick                                     LHS->getRawLinkageName(),
84109467b48Spatrick                                     LHS->getRawTemplateParams(), RHS);
84209467b48Spatrick   }
84309467b48Spatrick 
84409467b48Spatrick   /// Subprograms compare equal if they declare the same function in an ODR
84509467b48Spatrick   /// type.
84609467b48Spatrick   static bool isDeclarationOfODRMember(bool IsDefinition, const Metadata *Scope,
84709467b48Spatrick                                        const MDString *LinkageName,
84809467b48Spatrick                                        const Metadata *TemplateParams,
84909467b48Spatrick                                        const DISubprogram *RHS) {
85009467b48Spatrick     // Check whether the LHS is eligible.
85109467b48Spatrick     if (IsDefinition || !Scope || !LinkageName)
85209467b48Spatrick       return false;
85309467b48Spatrick 
85409467b48Spatrick     auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
85509467b48Spatrick     if (!CT || !CT->getRawIdentifier())
85609467b48Spatrick       return false;
85709467b48Spatrick 
85809467b48Spatrick     // Compare to the RHS.
85909467b48Spatrick     // FIXME: We need to compare template parameters here to avoid incorrect
86073471bf0Spatrick     // collisions in mapMetadata when RF_ReuseAndMutateDistinctMDs and a
86173471bf0Spatrick     // ODR-DISubprogram has a non-ODR template parameter (i.e., a
86273471bf0Spatrick     // DICompositeType that does not have an identifier). Eventually we should
86373471bf0Spatrick     // decouple ODR logic from uniquing logic.
86409467b48Spatrick     return IsDefinition == RHS->isDefinition() && Scope == RHS->getRawScope() &&
86509467b48Spatrick            LinkageName == RHS->getRawLinkageName() &&
86609467b48Spatrick            TemplateParams == RHS->getRawTemplateParams();
86709467b48Spatrick   }
86809467b48Spatrick };
86909467b48Spatrick 
87009467b48Spatrick template <> struct MDNodeKeyImpl<DILexicalBlock> {
87109467b48Spatrick   Metadata *Scope;
87209467b48Spatrick   Metadata *File;
87309467b48Spatrick   unsigned Line;
87409467b48Spatrick   unsigned Column;
87509467b48Spatrick 
87609467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)
87709467b48Spatrick       : Scope(Scope), File(File), Line(Line), Column(Column) {}
87809467b48Spatrick   MDNodeKeyImpl(const DILexicalBlock *N)
87909467b48Spatrick       : Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()),
88009467b48Spatrick         Column(N->getColumn()) {}
88109467b48Spatrick 
88209467b48Spatrick   bool isKeyOf(const DILexicalBlock *RHS) const {
88309467b48Spatrick     return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
88409467b48Spatrick            Line == RHS->getLine() && Column == RHS->getColumn();
88509467b48Spatrick   }
88609467b48Spatrick 
88709467b48Spatrick   unsigned getHashValue() const {
88809467b48Spatrick     return hash_combine(Scope, File, Line, Column);
88909467b48Spatrick   }
89009467b48Spatrick };
89109467b48Spatrick 
89209467b48Spatrick template <> struct MDNodeKeyImpl<DILexicalBlockFile> {
89309467b48Spatrick   Metadata *Scope;
89409467b48Spatrick   Metadata *File;
89509467b48Spatrick   unsigned Discriminator;
89609467b48Spatrick 
89709467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
89809467b48Spatrick       : Scope(Scope), File(File), Discriminator(Discriminator) {}
89909467b48Spatrick   MDNodeKeyImpl(const DILexicalBlockFile *N)
90009467b48Spatrick       : Scope(N->getRawScope()), File(N->getRawFile()),
90109467b48Spatrick         Discriminator(N->getDiscriminator()) {}
90209467b48Spatrick 
90309467b48Spatrick   bool isKeyOf(const DILexicalBlockFile *RHS) const {
90409467b48Spatrick     return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
90509467b48Spatrick            Discriminator == RHS->getDiscriminator();
90609467b48Spatrick   }
90709467b48Spatrick 
90809467b48Spatrick   unsigned getHashValue() const {
90909467b48Spatrick     return hash_combine(Scope, File, Discriminator);
91009467b48Spatrick   }
91109467b48Spatrick };
91209467b48Spatrick 
91309467b48Spatrick template <> struct MDNodeKeyImpl<DINamespace> {
91409467b48Spatrick   Metadata *Scope;
91509467b48Spatrick   MDString *Name;
91609467b48Spatrick   bool ExportSymbols;
91709467b48Spatrick 
91809467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, MDString *Name, bool ExportSymbols)
91909467b48Spatrick       : Scope(Scope), Name(Name), ExportSymbols(ExportSymbols) {}
92009467b48Spatrick   MDNodeKeyImpl(const DINamespace *N)
92109467b48Spatrick       : Scope(N->getRawScope()), Name(N->getRawName()),
92209467b48Spatrick         ExportSymbols(N->getExportSymbols()) {}
92309467b48Spatrick 
92409467b48Spatrick   bool isKeyOf(const DINamespace *RHS) const {
92509467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
92609467b48Spatrick            ExportSymbols == RHS->getExportSymbols();
92709467b48Spatrick   }
92809467b48Spatrick 
929*d415bd75Srobert   unsigned getHashValue() const { return hash_combine(Scope, Name); }
93009467b48Spatrick };
93109467b48Spatrick 
93209467b48Spatrick template <> struct MDNodeKeyImpl<DICommonBlock> {
93309467b48Spatrick   Metadata *Scope;
93409467b48Spatrick   Metadata *Decl;
93509467b48Spatrick   MDString *Name;
93609467b48Spatrick   Metadata *File;
93709467b48Spatrick   unsigned LineNo;
93809467b48Spatrick 
939*d415bd75Srobert   MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, Metadata *File,
940*d415bd75Srobert                 unsigned LineNo)
94109467b48Spatrick       : Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo) {}
94209467b48Spatrick   MDNodeKeyImpl(const DICommonBlock *N)
94309467b48Spatrick       : Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()),
94409467b48Spatrick         File(N->getRawFile()), LineNo(N->getLineNo()) {}
94509467b48Spatrick 
94609467b48Spatrick   bool isKeyOf(const DICommonBlock *RHS) const {
94709467b48Spatrick     return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() &&
94809467b48Spatrick            Name == RHS->getRawName() && File == RHS->getRawFile() &&
94909467b48Spatrick            LineNo == RHS->getLineNo();
95009467b48Spatrick   }
95109467b48Spatrick 
95209467b48Spatrick   unsigned getHashValue() const {
95309467b48Spatrick     return hash_combine(Scope, Decl, Name, File, LineNo);
95409467b48Spatrick   }
95509467b48Spatrick };
95609467b48Spatrick 
95709467b48Spatrick template <> struct MDNodeKeyImpl<DIModule> {
958097a140dSpatrick   Metadata *File;
95909467b48Spatrick   Metadata *Scope;
96009467b48Spatrick   MDString *Name;
96109467b48Spatrick   MDString *ConfigurationMacros;
96209467b48Spatrick   MDString *IncludePath;
963097a140dSpatrick   MDString *APINotesFile;
964097a140dSpatrick   unsigned LineNo;
96573471bf0Spatrick   bool IsDecl;
96609467b48Spatrick 
967097a140dSpatrick   MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name,
968097a140dSpatrick                 MDString *ConfigurationMacros, MDString *IncludePath,
96973471bf0Spatrick                 MDString *APINotesFile, unsigned LineNo, bool IsDecl)
970097a140dSpatrick       : File(File), Scope(Scope), Name(Name),
971097a140dSpatrick         ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath),
97273471bf0Spatrick         APINotesFile(APINotesFile), LineNo(LineNo), IsDecl(IsDecl) {}
97309467b48Spatrick   MDNodeKeyImpl(const DIModule *N)
974097a140dSpatrick       : File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()),
97509467b48Spatrick         ConfigurationMacros(N->getRawConfigurationMacros()),
976097a140dSpatrick         IncludePath(N->getRawIncludePath()),
97773471bf0Spatrick         APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()),
97873471bf0Spatrick         IsDecl(N->getIsDecl()) {}
97909467b48Spatrick 
98009467b48Spatrick   bool isKeyOf(const DIModule *RHS) const {
98109467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
98209467b48Spatrick            ConfigurationMacros == RHS->getRawConfigurationMacros() &&
98309467b48Spatrick            IncludePath == RHS->getRawIncludePath() &&
984097a140dSpatrick            APINotesFile == RHS->getRawAPINotesFile() &&
98573471bf0Spatrick            File == RHS->getRawFile() && LineNo == RHS->getLineNo() &&
98673471bf0Spatrick            IsDecl == RHS->getIsDecl();
98709467b48Spatrick   }
98809467b48Spatrick 
98909467b48Spatrick   unsigned getHashValue() const {
990097a140dSpatrick     return hash_combine(Scope, Name, ConfigurationMacros, IncludePath);
99109467b48Spatrick   }
99209467b48Spatrick };
99309467b48Spatrick 
99409467b48Spatrick template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {
99509467b48Spatrick   MDString *Name;
99609467b48Spatrick   Metadata *Type;
997097a140dSpatrick   bool IsDefault;
99809467b48Spatrick 
999097a140dSpatrick   MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)
1000097a140dSpatrick       : Name(Name), Type(Type), IsDefault(IsDefault) {}
100109467b48Spatrick   MDNodeKeyImpl(const DITemplateTypeParameter *N)
1002097a140dSpatrick       : Name(N->getRawName()), Type(N->getRawType()),
1003097a140dSpatrick         IsDefault(N->isDefault()) {}
100409467b48Spatrick 
100509467b48Spatrick   bool isKeyOf(const DITemplateTypeParameter *RHS) const {
1006097a140dSpatrick     return Name == RHS->getRawName() && Type == RHS->getRawType() &&
1007097a140dSpatrick            IsDefault == RHS->isDefault();
100809467b48Spatrick   }
100909467b48Spatrick 
1010097a140dSpatrick   unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }
101109467b48Spatrick };
101209467b48Spatrick 
101309467b48Spatrick template <> struct MDNodeKeyImpl<DITemplateValueParameter> {
101409467b48Spatrick   unsigned Tag;
101509467b48Spatrick   MDString *Name;
101609467b48Spatrick   Metadata *Type;
1017097a140dSpatrick   bool IsDefault;
101809467b48Spatrick   Metadata *Value;
101909467b48Spatrick 
1020097a140dSpatrick   MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,
1021097a140dSpatrick                 Metadata *Value)
1022097a140dSpatrick       : Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}
102309467b48Spatrick   MDNodeKeyImpl(const DITemplateValueParameter *N)
102409467b48Spatrick       : Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),
1025097a140dSpatrick         IsDefault(N->isDefault()), Value(N->getValue()) {}
102609467b48Spatrick 
102709467b48Spatrick   bool isKeyOf(const DITemplateValueParameter *RHS) const {
102809467b48Spatrick     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
1029097a140dSpatrick            Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&
1030097a140dSpatrick            Value == RHS->getValue();
103109467b48Spatrick   }
103209467b48Spatrick 
1033097a140dSpatrick   unsigned getHashValue() const {
1034097a140dSpatrick     return hash_combine(Tag, Name, Type, IsDefault, Value);
1035097a140dSpatrick   }
103609467b48Spatrick };
103709467b48Spatrick 
103809467b48Spatrick template <> struct MDNodeKeyImpl<DIGlobalVariable> {
103909467b48Spatrick   Metadata *Scope;
104009467b48Spatrick   MDString *Name;
104109467b48Spatrick   MDString *LinkageName;
104209467b48Spatrick   Metadata *File;
104309467b48Spatrick   unsigned Line;
104409467b48Spatrick   Metadata *Type;
104509467b48Spatrick   bool IsLocalToUnit;
104609467b48Spatrick   bool IsDefinition;
104709467b48Spatrick   Metadata *StaticDataMemberDeclaration;
104809467b48Spatrick   Metadata *TemplateParams;
104909467b48Spatrick   uint32_t AlignInBits;
1050*d415bd75Srobert   Metadata *Annotations;
105109467b48Spatrick 
105209467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
105309467b48Spatrick                 Metadata *File, unsigned Line, Metadata *Type,
105409467b48Spatrick                 bool IsLocalToUnit, bool IsDefinition,
105509467b48Spatrick                 Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
1056*d415bd75Srobert                 uint32_t AlignInBits, Metadata *Annotations)
105709467b48Spatrick       : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
105809467b48Spatrick         Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
105909467b48Spatrick         IsDefinition(IsDefinition),
106009467b48Spatrick         StaticDataMemberDeclaration(StaticDataMemberDeclaration),
1061*d415bd75Srobert         TemplateParams(TemplateParams), AlignInBits(AlignInBits),
1062*d415bd75Srobert         Annotations(Annotations) {}
106309467b48Spatrick   MDNodeKeyImpl(const DIGlobalVariable *N)
106409467b48Spatrick       : Scope(N->getRawScope()), Name(N->getRawName()),
106509467b48Spatrick         LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
106609467b48Spatrick         Line(N->getLine()), Type(N->getRawType()),
106709467b48Spatrick         IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
106809467b48Spatrick         StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()),
106909467b48Spatrick         TemplateParams(N->getRawTemplateParams()),
1070*d415bd75Srobert         AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {}
107109467b48Spatrick 
107209467b48Spatrick   bool isKeyOf(const DIGlobalVariable *RHS) const {
107309467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
107409467b48Spatrick            LinkageName == RHS->getRawLinkageName() &&
107509467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine() &&
107609467b48Spatrick            Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() &&
107709467b48Spatrick            IsDefinition == RHS->isDefinition() &&
107809467b48Spatrick            StaticDataMemberDeclaration ==
107909467b48Spatrick                RHS->getRawStaticDataMemberDeclaration() &&
108009467b48Spatrick            TemplateParams == RHS->getRawTemplateParams() &&
1081*d415bd75Srobert            AlignInBits == RHS->getAlignInBits() &&
1082*d415bd75Srobert            Annotations == RHS->getRawAnnotations();
108309467b48Spatrick   }
108409467b48Spatrick 
108509467b48Spatrick   unsigned getHashValue() const {
108609467b48Spatrick     // We do not use AlignInBits in hashing function here on purpose:
108709467b48Spatrick     // in most cases this param for local variable is zero (for function param
108809467b48Spatrick     // it is always zero). This leads to lots of hash collisions and errors on
108909467b48Spatrick     // cases with lots of similar variables.
109009467b48Spatrick     // clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
109109467b48Spatrick     // generated IR is random for each run and test fails with Align included.
109209467b48Spatrick     // TODO: make hashing work fine with such situations
109309467b48Spatrick     return hash_combine(Scope, Name, LinkageName, File, Line, Type,
109409467b48Spatrick                         IsLocalToUnit, IsDefinition, /* AlignInBits, */
1095*d415bd75Srobert                         StaticDataMemberDeclaration, Annotations);
109609467b48Spatrick   }
109709467b48Spatrick };
109809467b48Spatrick 
109909467b48Spatrick template <> struct MDNodeKeyImpl<DILocalVariable> {
110009467b48Spatrick   Metadata *Scope;
110109467b48Spatrick   MDString *Name;
110209467b48Spatrick   Metadata *File;
110309467b48Spatrick   unsigned Line;
110409467b48Spatrick   Metadata *Type;
110509467b48Spatrick   unsigned Arg;
110609467b48Spatrick   unsigned Flags;
110709467b48Spatrick   uint32_t AlignInBits;
1108*d415bd75Srobert   Metadata *Annotations;
110909467b48Spatrick 
111009467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line,
111109467b48Spatrick                 Metadata *Type, unsigned Arg, unsigned Flags,
1112*d415bd75Srobert                 uint32_t AlignInBits, Metadata *Annotations)
111309467b48Spatrick       : Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg),
1114*d415bd75Srobert         Flags(Flags), AlignInBits(AlignInBits), Annotations(Annotations) {}
111509467b48Spatrick   MDNodeKeyImpl(const DILocalVariable *N)
111609467b48Spatrick       : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
111709467b48Spatrick         Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()),
1118*d415bd75Srobert         Flags(N->getFlags()), AlignInBits(N->getAlignInBits()),
1119*d415bd75Srobert         Annotations(N->getRawAnnotations()) {}
112009467b48Spatrick 
112109467b48Spatrick   bool isKeyOf(const DILocalVariable *RHS) const {
112209467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
112309467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine() &&
112409467b48Spatrick            Type == RHS->getRawType() && Arg == RHS->getArg() &&
1125*d415bd75Srobert            Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits() &&
1126*d415bd75Srobert            Annotations == RHS->getRawAnnotations();
112709467b48Spatrick   }
112809467b48Spatrick 
112909467b48Spatrick   unsigned getHashValue() const {
113009467b48Spatrick     // We do not use AlignInBits in hashing function here on purpose:
113109467b48Spatrick     // in most cases this param for local variable is zero (for function param
113209467b48Spatrick     // it is always zero). This leads to lots of hash collisions and errors on
113309467b48Spatrick     // cases with lots of similar variables.
113409467b48Spatrick     // clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
113509467b48Spatrick     // generated IR is random for each run and test fails with Align included.
113609467b48Spatrick     // TODO: make hashing work fine with such situations
1137*d415bd75Srobert     return hash_combine(Scope, Name, File, Line, Type, Arg, Flags, Annotations);
113809467b48Spatrick   }
113909467b48Spatrick };
114009467b48Spatrick 
114109467b48Spatrick template <> struct MDNodeKeyImpl<DILabel> {
114209467b48Spatrick   Metadata *Scope;
114309467b48Spatrick   MDString *Name;
114409467b48Spatrick   Metadata *File;
114509467b48Spatrick   unsigned Line;
114609467b48Spatrick 
114709467b48Spatrick   MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line)
114809467b48Spatrick       : Scope(Scope), Name(Name), File(File), Line(Line) {}
114909467b48Spatrick   MDNodeKeyImpl(const DILabel *N)
115009467b48Spatrick       : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
115109467b48Spatrick         Line(N->getLine()) {}
115209467b48Spatrick 
115309467b48Spatrick   bool isKeyOf(const DILabel *RHS) const {
115409467b48Spatrick     return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
115509467b48Spatrick            File == RHS->getRawFile() && Line == RHS->getLine();
115609467b48Spatrick   }
115709467b48Spatrick 
115809467b48Spatrick   /// Using name and line to get hash value. It should already be mostly unique.
1159*d415bd75Srobert   unsigned getHashValue() const { return hash_combine(Scope, Name, Line); }
116009467b48Spatrick };
116109467b48Spatrick 
116209467b48Spatrick template <> struct MDNodeKeyImpl<DIExpression> {
116309467b48Spatrick   ArrayRef<uint64_t> Elements;
116409467b48Spatrick 
116509467b48Spatrick   MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
116609467b48Spatrick   MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {}
116709467b48Spatrick 
116809467b48Spatrick   bool isKeyOf(const DIExpression *RHS) const {
116909467b48Spatrick     return Elements == RHS->getElements();
117009467b48Spatrick   }
117109467b48Spatrick 
117209467b48Spatrick   unsigned getHashValue() const {
117309467b48Spatrick     return hash_combine_range(Elements.begin(), Elements.end());
117409467b48Spatrick   }
117509467b48Spatrick };
117609467b48Spatrick 
117709467b48Spatrick template <> struct MDNodeKeyImpl<DIGlobalVariableExpression> {
117809467b48Spatrick   Metadata *Variable;
117909467b48Spatrick   Metadata *Expression;
118009467b48Spatrick 
118109467b48Spatrick   MDNodeKeyImpl(Metadata *Variable, Metadata *Expression)
118209467b48Spatrick       : Variable(Variable), Expression(Expression) {}
118309467b48Spatrick   MDNodeKeyImpl(const DIGlobalVariableExpression *N)
118409467b48Spatrick       : Variable(N->getRawVariable()), Expression(N->getRawExpression()) {}
118509467b48Spatrick 
118609467b48Spatrick   bool isKeyOf(const DIGlobalVariableExpression *RHS) const {
118709467b48Spatrick     return Variable == RHS->getRawVariable() &&
118809467b48Spatrick            Expression == RHS->getRawExpression();
118909467b48Spatrick   }
119009467b48Spatrick 
119109467b48Spatrick   unsigned getHashValue() const { return hash_combine(Variable, Expression); }
119209467b48Spatrick };
119309467b48Spatrick 
119409467b48Spatrick template <> struct MDNodeKeyImpl<DIObjCProperty> {
119509467b48Spatrick   MDString *Name;
119609467b48Spatrick   Metadata *File;
119709467b48Spatrick   unsigned Line;
119809467b48Spatrick   MDString *GetterName;
119909467b48Spatrick   MDString *SetterName;
120009467b48Spatrick   unsigned Attributes;
120109467b48Spatrick   Metadata *Type;
120209467b48Spatrick 
120309467b48Spatrick   MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line,
120409467b48Spatrick                 MDString *GetterName, MDString *SetterName, unsigned Attributes,
120509467b48Spatrick                 Metadata *Type)
120609467b48Spatrick       : Name(Name), File(File), Line(Line), GetterName(GetterName),
120709467b48Spatrick         SetterName(SetterName), Attributes(Attributes), Type(Type) {}
120809467b48Spatrick   MDNodeKeyImpl(const DIObjCProperty *N)
120909467b48Spatrick       : Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
121009467b48Spatrick         GetterName(N->getRawGetterName()), SetterName(N->getRawSetterName()),
121109467b48Spatrick         Attributes(N->getAttributes()), Type(N->getRawType()) {}
121209467b48Spatrick 
121309467b48Spatrick   bool isKeyOf(const DIObjCProperty *RHS) const {
121409467b48Spatrick     return Name == RHS->getRawName() && File == RHS->getRawFile() &&
121509467b48Spatrick            Line == RHS->getLine() && GetterName == RHS->getRawGetterName() &&
121609467b48Spatrick            SetterName == RHS->getRawSetterName() &&
121709467b48Spatrick            Attributes == RHS->getAttributes() && Type == RHS->getRawType();
121809467b48Spatrick   }
121909467b48Spatrick 
122009467b48Spatrick   unsigned getHashValue() const {
122109467b48Spatrick     return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,
122209467b48Spatrick                         Type);
122309467b48Spatrick   }
122409467b48Spatrick };
122509467b48Spatrick 
122609467b48Spatrick template <> struct MDNodeKeyImpl<DIImportedEntity> {
122709467b48Spatrick   unsigned Tag;
122809467b48Spatrick   Metadata *Scope;
122909467b48Spatrick   Metadata *Entity;
123009467b48Spatrick   Metadata *File;
123109467b48Spatrick   unsigned Line;
123209467b48Spatrick   MDString *Name;
1233*d415bd75Srobert   Metadata *Elements;
123409467b48Spatrick 
123509467b48Spatrick   MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File,
1236*d415bd75Srobert                 unsigned Line, MDString *Name, Metadata *Elements)
123709467b48Spatrick       : Tag(Tag), Scope(Scope), Entity(Entity), File(File), Line(Line),
1238*d415bd75Srobert         Name(Name), Elements(Elements) {}
123909467b48Spatrick   MDNodeKeyImpl(const DIImportedEntity *N)
124009467b48Spatrick       : Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()),
1241*d415bd75Srobert         File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()),
1242*d415bd75Srobert         Elements(N->getRawElements()) {}
124309467b48Spatrick 
124409467b48Spatrick   bool isKeyOf(const DIImportedEntity *RHS) const {
124509467b48Spatrick     return Tag == RHS->getTag() && Scope == RHS->getRawScope() &&
124609467b48Spatrick            Entity == RHS->getRawEntity() && File == RHS->getFile() &&
1247*d415bd75Srobert            Line == RHS->getLine() && Name == RHS->getRawName() &&
1248*d415bd75Srobert            Elements == RHS->getRawElements();
124909467b48Spatrick   }
125009467b48Spatrick 
125109467b48Spatrick   unsigned getHashValue() const {
1252*d415bd75Srobert     return hash_combine(Tag, Scope, Entity, File, Line, Name, Elements);
125309467b48Spatrick   }
125409467b48Spatrick };
125509467b48Spatrick 
125609467b48Spatrick template <> struct MDNodeKeyImpl<DIMacro> {
125709467b48Spatrick   unsigned MIType;
125809467b48Spatrick   unsigned Line;
125909467b48Spatrick   MDString *Name;
126009467b48Spatrick   MDString *Value;
126109467b48Spatrick 
126209467b48Spatrick   MDNodeKeyImpl(unsigned MIType, unsigned Line, MDString *Name, MDString *Value)
126309467b48Spatrick       : MIType(MIType), Line(Line), Name(Name), Value(Value) {}
126409467b48Spatrick   MDNodeKeyImpl(const DIMacro *N)
126509467b48Spatrick       : MIType(N->getMacinfoType()), Line(N->getLine()), Name(N->getRawName()),
126609467b48Spatrick         Value(N->getRawValue()) {}
126709467b48Spatrick 
126809467b48Spatrick   bool isKeyOf(const DIMacro *RHS) const {
126909467b48Spatrick     return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
127009467b48Spatrick            Name == RHS->getRawName() && Value == RHS->getRawValue();
127109467b48Spatrick   }
127209467b48Spatrick 
127309467b48Spatrick   unsigned getHashValue() const {
127409467b48Spatrick     return hash_combine(MIType, Line, Name, Value);
127509467b48Spatrick   }
127609467b48Spatrick };
127709467b48Spatrick 
127809467b48Spatrick template <> struct MDNodeKeyImpl<DIMacroFile> {
127909467b48Spatrick   unsigned MIType;
128009467b48Spatrick   unsigned Line;
128109467b48Spatrick   Metadata *File;
128209467b48Spatrick   Metadata *Elements;
128309467b48Spatrick 
128409467b48Spatrick   MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File,
128509467b48Spatrick                 Metadata *Elements)
128609467b48Spatrick       : MIType(MIType), Line(Line), File(File), Elements(Elements) {}
128709467b48Spatrick   MDNodeKeyImpl(const DIMacroFile *N)
128809467b48Spatrick       : MIType(N->getMacinfoType()), Line(N->getLine()), File(N->getRawFile()),
128909467b48Spatrick         Elements(N->getRawElements()) {}
129009467b48Spatrick 
129109467b48Spatrick   bool isKeyOf(const DIMacroFile *RHS) const {
129209467b48Spatrick     return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
129309467b48Spatrick            File == RHS->getRawFile() && Elements == RHS->getRawElements();
129409467b48Spatrick   }
129509467b48Spatrick 
129609467b48Spatrick   unsigned getHashValue() const {
129709467b48Spatrick     return hash_combine(MIType, Line, File, Elements);
129809467b48Spatrick   }
129909467b48Spatrick };
130009467b48Spatrick 
130173471bf0Spatrick template <> struct MDNodeKeyImpl<DIArgList> {
130273471bf0Spatrick   ArrayRef<ValueAsMetadata *> Args;
130373471bf0Spatrick 
130473471bf0Spatrick   MDNodeKeyImpl(ArrayRef<ValueAsMetadata *> Args) : Args(Args) {}
130573471bf0Spatrick   MDNodeKeyImpl(const DIArgList *N) : Args(N->getArgs()) {}
130673471bf0Spatrick 
130773471bf0Spatrick   bool isKeyOf(const DIArgList *RHS) const { return Args == RHS->getArgs(); }
130873471bf0Spatrick 
130973471bf0Spatrick   unsigned getHashValue() const {
131073471bf0Spatrick     return hash_combine_range(Args.begin(), Args.end());
131173471bf0Spatrick   }
131273471bf0Spatrick };
131373471bf0Spatrick 
131409467b48Spatrick /// DenseMapInfo for MDNode subclasses.
131509467b48Spatrick template <class NodeTy> struct MDNodeInfo {
131609467b48Spatrick   using KeyTy = MDNodeKeyImpl<NodeTy>;
131709467b48Spatrick   using SubsetEqualTy = MDNodeSubsetEqualImpl<NodeTy>;
131809467b48Spatrick 
131909467b48Spatrick   static inline NodeTy *getEmptyKey() {
132009467b48Spatrick     return DenseMapInfo<NodeTy *>::getEmptyKey();
132109467b48Spatrick   }
132209467b48Spatrick 
132309467b48Spatrick   static inline NodeTy *getTombstoneKey() {
132409467b48Spatrick     return DenseMapInfo<NodeTy *>::getTombstoneKey();
132509467b48Spatrick   }
132609467b48Spatrick 
132709467b48Spatrick   static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }
132809467b48Spatrick 
132909467b48Spatrick   static unsigned getHashValue(const NodeTy *N) {
133009467b48Spatrick     return KeyTy(N).getHashValue();
133109467b48Spatrick   }
133209467b48Spatrick 
133309467b48Spatrick   static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) {
133409467b48Spatrick     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
133509467b48Spatrick       return false;
133609467b48Spatrick     return SubsetEqualTy::isSubsetEqual(LHS, RHS) || LHS.isKeyOf(RHS);
133709467b48Spatrick   }
133809467b48Spatrick 
133909467b48Spatrick   static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) {
134009467b48Spatrick     if (LHS == RHS)
134109467b48Spatrick       return true;
134209467b48Spatrick     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
134309467b48Spatrick       return false;
134409467b48Spatrick     return SubsetEqualTy::isSubsetEqual(LHS, RHS);
134509467b48Spatrick   }
134609467b48Spatrick };
134709467b48Spatrick 
134809467b48Spatrick #define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;
134909467b48Spatrick #include "llvm/IR/Metadata.def"
135009467b48Spatrick 
135173471bf0Spatrick /// Multimap-like storage for metadata attachments.
135273471bf0Spatrick class MDAttachments {
135373471bf0Spatrick public:
135473471bf0Spatrick   struct Attachment {
135573471bf0Spatrick     unsigned MDKind;
135673471bf0Spatrick     TrackingMDNodeRef Node;
135773471bf0Spatrick   };
135873471bf0Spatrick 
135973471bf0Spatrick private:
136073471bf0Spatrick   SmallVector<Attachment, 1> Attachments;
136109467b48Spatrick 
136209467b48Spatrick public:
136309467b48Spatrick   bool empty() const { return Attachments.empty(); }
136409467b48Spatrick   size_t size() const { return Attachments.size(); }
136509467b48Spatrick 
136673471bf0Spatrick   /// Returns the first attachment with the given ID or nullptr if no such
136773471bf0Spatrick   /// attachment exists.
136809467b48Spatrick   MDNode *lookup(unsigned ID) const;
136909467b48Spatrick 
137009467b48Spatrick   /// Appends all attachments with the given ID to \c Result in insertion order.
137109467b48Spatrick   /// If the global has no attachments with the given ID, or if ID is invalid,
137209467b48Spatrick   /// leaves Result unchanged.
137309467b48Spatrick   void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;
137409467b48Spatrick 
137509467b48Spatrick   /// Appends all attachments for the global to \c Result, sorting by attachment
137609467b48Spatrick   /// ID. Attachments with the same ID appear in insertion order. This function
137709467b48Spatrick   /// does \em not clear \c Result.
137809467b48Spatrick   void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
137973471bf0Spatrick 
138073471bf0Spatrick   /// Set an attachment to a particular node.
138173471bf0Spatrick   ///
138273471bf0Spatrick   /// Set the \c ID attachment to \c MD, replacing the current attachments at \c
138373471bf0Spatrick   /// ID (if anyway).
138473471bf0Spatrick   void set(unsigned ID, MDNode *MD);
138573471bf0Spatrick 
138673471bf0Spatrick   /// Adds an attachment to a particular node.
138773471bf0Spatrick   void insert(unsigned ID, MDNode &MD);
138873471bf0Spatrick 
138973471bf0Spatrick   /// Remove attachments with the given ID.
139073471bf0Spatrick   ///
139173471bf0Spatrick   /// Remove the attachments at \c ID, if any.
139273471bf0Spatrick   bool erase(unsigned ID);
139373471bf0Spatrick 
139473471bf0Spatrick   /// Erase matching attachments.
139573471bf0Spatrick   ///
139673471bf0Spatrick   /// Erases all attachments matching the \c shouldRemove predicate.
139773471bf0Spatrick   template <class PredTy> void remove_if(PredTy shouldRemove) {
139873471bf0Spatrick     llvm::erase_if(Attachments, shouldRemove);
139973471bf0Spatrick   }
140009467b48Spatrick };
140109467b48Spatrick 
140209467b48Spatrick class LLVMContextImpl {
140309467b48Spatrick public:
140409467b48Spatrick   /// OwnedModules - The set of modules instantiated in this context, and which
140509467b48Spatrick   /// will be automatically deleted if this context is deleted.
140609467b48Spatrick   SmallPtrSet<Module *, 4> OwnedModules;
140709467b48Spatrick 
1408097a140dSpatrick   /// The main remark streamer used by all the other streamers (e.g. IR, MIR,
1409097a140dSpatrick   /// frontends, etc.). This should only be used by the specific streamers, and
1410097a140dSpatrick   /// never directly.
1411097a140dSpatrick   std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;
1412097a140dSpatrick 
141309467b48Spatrick   std::unique_ptr<DiagnosticHandler> DiagHandler;
141409467b48Spatrick   bool RespectDiagnosticFilters = false;
141509467b48Spatrick   bool DiagnosticsHotnessRequested = false;
141673471bf0Spatrick   /// The minimum hotness value a diagnostic needs in order to be included in
141773471bf0Spatrick   /// optimization diagnostics.
141873471bf0Spatrick   ///
141973471bf0Spatrick   /// The threshold is an Optional value, which maps to one of the 3 states:
142073471bf0Spatrick   /// 1). 0            => threshold disabled. All emarks will be printed.
142173471bf0Spatrick   /// 2). positive int => manual threshold by user. Remarks with hotness exceed
142273471bf0Spatrick   ///                     threshold will be printed.
142373471bf0Spatrick   /// 3). None         => 'auto' threshold by user. The actual value is not
142473471bf0Spatrick   ///                     available at command line, but will be synced with
142573471bf0Spatrick   ///                     hotness threhold from profile summary during
142673471bf0Spatrick   ///                     compilation.
142773471bf0Spatrick   ///
142873471bf0Spatrick   /// State 1 and 2 are considered as terminal states. State transition is
142973471bf0Spatrick   /// only allowed from 3 to 2, when the threshold is first synced with profile
143073471bf0Spatrick   /// summary. This ensures that the threshold is set only once and stays
143173471bf0Spatrick   /// constant.
143273471bf0Spatrick   ///
143373471bf0Spatrick   /// If threshold option is not specified, it is disabled (0) by default.
1434*d415bd75Srobert   std::optional<uint64_t> DiagnosticsHotnessThreshold = 0;
1435*d415bd75Srobert 
1436*d415bd75Srobert   /// The percentage of difference between profiling branch weights and
1437*d415bd75Srobert   /// llvm.expect branch weights to tolerate when emiting MisExpect diagnostics
1438*d415bd75Srobert   std::optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
1439*d415bd75Srobert   bool MisExpectWarningRequested = false;
144073471bf0Spatrick 
1441097a140dSpatrick   /// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
1442097a140dSpatrick   std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
144309467b48Spatrick 
144409467b48Spatrick   LLVMContext::YieldCallbackTy YieldCallback = nullptr;
144509467b48Spatrick   void *YieldOpaqueHandle = nullptr;
144609467b48Spatrick 
1447*d415bd75Srobert   DenseMap<const Value *, ValueName *> ValueNames;
1448*d415bd75Srobert 
144909467b48Spatrick   using IntMapTy =
145009467b48Spatrick       DenseMap<APInt, std::unique_ptr<ConstantInt>, DenseMapAPIntKeyInfo>;
145109467b48Spatrick   IntMapTy IntConstants;
145209467b48Spatrick 
145309467b48Spatrick   using FPMapTy =
145409467b48Spatrick       DenseMap<APFloat, std::unique_ptr<ConstantFP>, DenseMapAPFloatKeyInfo>;
145509467b48Spatrick   FPMapTy FPConstants;
145609467b48Spatrick 
145709467b48Spatrick   FoldingSet<AttributeImpl> AttrsSet;
145809467b48Spatrick   FoldingSet<AttributeListImpl> AttrsLists;
145909467b48Spatrick   FoldingSet<AttributeSetNode> AttrsSetNodes;
146009467b48Spatrick 
146109467b48Spatrick   StringMap<MDString, BumpPtrAllocator> MDStringCache;
146209467b48Spatrick   DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
146309467b48Spatrick   DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
146409467b48Spatrick 
146509467b48Spatrick #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
146609467b48Spatrick   DenseSet<CLASS *, CLASS##Info> CLASS##s;
146709467b48Spatrick #include "llvm/IR/Metadata.def"
146809467b48Spatrick 
146909467b48Spatrick   // Optional map for looking up composite types by identifier.
1470*d415bd75Srobert   std::optional<DenseMap<const MDString *, DICompositeType *>> DITypeMap;
147109467b48Spatrick 
147209467b48Spatrick   // MDNodes may be uniqued or not uniqued.  When they're not uniqued, they
147309467b48Spatrick   // aren't in the MDNodeSet, but they're still shared between objects, so no
147409467b48Spatrick   // one object can destroy them.  Keep track of them here so we can delete
147509467b48Spatrick   // them on context teardown.
147609467b48Spatrick   std::vector<MDNode *> DistinctMDNodes;
147709467b48Spatrick 
147809467b48Spatrick   DenseMap<Type *, std::unique_ptr<ConstantAggregateZero>> CAZConstants;
147909467b48Spatrick 
148009467b48Spatrick   using ArrayConstantsTy = ConstantUniqueMap<ConstantArray>;
148109467b48Spatrick   ArrayConstantsTy ArrayConstants;
148209467b48Spatrick 
148309467b48Spatrick   using StructConstantsTy = ConstantUniqueMap<ConstantStruct>;
148409467b48Spatrick   StructConstantsTy StructConstants;
148509467b48Spatrick 
148609467b48Spatrick   using VectorConstantsTy = ConstantUniqueMap<ConstantVector>;
148709467b48Spatrick   VectorConstantsTy VectorConstants;
148809467b48Spatrick 
148909467b48Spatrick   DenseMap<PointerType *, std::unique_ptr<ConstantPointerNull>> CPNConstants;
149009467b48Spatrick 
1491*d415bd75Srobert   DenseMap<TargetExtType *, std::unique_ptr<ConstantTargetNone>> CTNConstants;
1492*d415bd75Srobert 
149309467b48Spatrick   DenseMap<Type *, std::unique_ptr<UndefValue>> UVConstants;
149409467b48Spatrick 
149573471bf0Spatrick   DenseMap<Type *, std::unique_ptr<PoisonValue>> PVConstants;
149673471bf0Spatrick 
149773471bf0Spatrick   StringMap<std::unique_ptr<ConstantDataSequential>> CDSConstants;
149809467b48Spatrick 
149909467b48Spatrick   DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
150009467b48Spatrick       BlockAddresses;
150173471bf0Spatrick 
150273471bf0Spatrick   DenseMap<const GlobalValue *, DSOLocalEquivalent *> DSOLocalEquivalents;
150373471bf0Spatrick 
1504*d415bd75Srobert   DenseMap<const GlobalValue *, NoCFIValue *> NoCFIValues;
1505*d415bd75Srobert 
150609467b48Spatrick   ConstantUniqueMap<ConstantExpr> ExprConstants;
150709467b48Spatrick 
150809467b48Spatrick   ConstantUniqueMap<InlineAsm> InlineAsms;
150909467b48Spatrick 
151009467b48Spatrick   ConstantInt *TheTrueVal = nullptr;
151109467b48Spatrick   ConstantInt *TheFalseVal = nullptr;
151209467b48Spatrick 
151309467b48Spatrick   // Basic type instances.
1514097a140dSpatrick   Type VoidTy, LabelTy, HalfTy, BFloatTy, FloatTy, DoubleTy, MetadataTy,
1515097a140dSpatrick       TokenTy;
151673471bf0Spatrick   Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy, X86_AMXTy;
151709467b48Spatrick   IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
151809467b48Spatrick 
1519*d415bd75Srobert   std::unique_ptr<ConstantTokenNone> TheNoneToken;
1520*d415bd75Srobert 
152109467b48Spatrick   BumpPtrAllocator Alloc;
152209467b48Spatrick   UniqueStringSaver Saver{Alloc};
152309467b48Spatrick 
152409467b48Spatrick   DenseMap<unsigned, IntegerType *> IntegerTypes;
152509467b48Spatrick 
152609467b48Spatrick   using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
152709467b48Spatrick   FunctionTypeSet FunctionTypes;
152809467b48Spatrick   using StructTypeSet = DenseSet<StructType *, AnonStructTypeKeyInfo>;
152909467b48Spatrick   StructTypeSet AnonStructTypes;
153009467b48Spatrick   StringMap<StructType *> NamedStructTypes;
153109467b48Spatrick   unsigned NamedStructTypesUniqueID = 0;
153209467b48Spatrick 
1533*d415bd75Srobert   using TargetExtTypeSet = DenseSet<TargetExtType *, TargetExtTypeKeyInfo>;
1534*d415bd75Srobert   TargetExtTypeSet TargetExtTypes;
1535*d415bd75Srobert 
153609467b48Spatrick   DenseMap<std::pair<Type *, uint64_t>, ArrayType *> ArrayTypes;
153709467b48Spatrick   DenseMap<std::pair<Type *, ElementCount>, VectorType *> VectorTypes;
153809467b48Spatrick   DenseMap<Type *, PointerType *> PointerTypes; // Pointers in AddrSpace = 0
153909467b48Spatrick   DenseMap<std::pair<Type *, unsigned>, PointerType *> ASPointerTypes;
1540*d415bd75Srobert   DenseMap<std::pair<Type *, unsigned>, TypedPointerType *> ASTypedPointerTypes;
154109467b48Spatrick 
154209467b48Spatrick   /// ValueHandles - This map keeps track of all of the value handles that are
154309467b48Spatrick   /// watching a Value*.  The Value::HasValueHandle bit is used to know
154409467b48Spatrick   /// whether or not a value has an entry in this map.
154509467b48Spatrick   using ValueHandlesTy = DenseMap<Value *, ValueHandleBase *>;
154609467b48Spatrick   ValueHandlesTy ValueHandles;
154709467b48Spatrick 
154809467b48Spatrick   /// CustomMDKindNames - Map to hold the metadata string to ID mapping.
154909467b48Spatrick   StringMap<unsigned> CustomMDKindNames;
155009467b48Spatrick 
155173471bf0Spatrick   /// Collection of metadata used in this context.
155273471bf0Spatrick   DenseMap<const Value *, MDAttachments> ValueMetadata;
155309467b48Spatrick 
1554*d415bd75Srobert   /// Map DIAssignID -> Instructions with that attachment.
1555*d415bd75Srobert   /// Managed by Instruction via Instruction::updateDIAssignIDMapping.
1556*d415bd75Srobert   /// Query using the at:: functions defined in DebugInfo.h.
1557*d415bd75Srobert   DenseMap<DIAssignID *, SmallVector<Instruction *, 1>> AssignmentIDToInstrs;
1558*d415bd75Srobert 
155909467b48Spatrick   /// Collection of per-GlobalObject sections used in this context.
156009467b48Spatrick   DenseMap<const GlobalObject *, StringRef> GlobalObjectSections;
156109467b48Spatrick 
156209467b48Spatrick   /// Collection of per-GlobalValue partitions used in this context.
156309467b48Spatrick   DenseMap<const GlobalValue *, StringRef> GlobalValuePartitions;
156409467b48Spatrick 
1565*d415bd75Srobert   DenseMap<const GlobalValue *, GlobalValue::SanitizerMetadata>
1566*d415bd75Srobert       GlobalValueSanitizerMetadata;
1567*d415bd75Srobert 
156809467b48Spatrick   /// DiscriminatorTable - This table maps file:line locations to an
156909467b48Spatrick   /// integer representing the next DWARF path discriminator to assign to
157009467b48Spatrick   /// instructions in different blocks at the same location.
157109467b48Spatrick   DenseMap<std::pair<const char *, unsigned>, unsigned> DiscriminatorTable;
157209467b48Spatrick 
157309467b48Spatrick   /// A set of interned tags for operand bundles.  The StringMap maps
157409467b48Spatrick   /// bundle tags to their IDs.
157509467b48Spatrick   ///
157609467b48Spatrick   /// \see LLVMContext::getOperandBundleTagID
157709467b48Spatrick   StringMap<uint32_t> BundleTagCache;
157809467b48Spatrick 
157909467b48Spatrick   StringMapEntry<uint32_t> *getOrInsertBundleTag(StringRef Tag);
158009467b48Spatrick   void getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const;
158109467b48Spatrick   uint32_t getOperandBundleTagID(StringRef Tag) const;
158209467b48Spatrick 
158309467b48Spatrick   /// A set of interned synchronization scopes.  The StringMap maps
158409467b48Spatrick   /// synchronization scope names to their respective synchronization scope IDs.
158509467b48Spatrick   StringMap<SyncScope::ID> SSC;
158609467b48Spatrick 
158709467b48Spatrick   /// getOrInsertSyncScopeID - Maps synchronization scope name to
158809467b48Spatrick   /// synchronization scope ID.  Every synchronization scope registered with
158909467b48Spatrick   /// LLVMContext has unique ID except pre-defined ones.
159009467b48Spatrick   SyncScope::ID getOrInsertSyncScopeID(StringRef SSN);
159109467b48Spatrick 
159209467b48Spatrick   /// getSyncScopeNames - Populates client supplied SmallVector with
159309467b48Spatrick   /// synchronization scope names registered with LLVMContext.  Synchronization
159409467b48Spatrick   /// scope names are ordered by increasing synchronization scope IDs.
159509467b48Spatrick   void getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const;
159609467b48Spatrick 
159709467b48Spatrick   /// Maintain the GC name for each function.
159809467b48Spatrick   ///
159909467b48Spatrick   /// This saves allocating an additional word in Function for programs which
160009467b48Spatrick   /// do not use GC (i.e., most programs) at the cost of increased overhead for
160109467b48Spatrick   /// clients which do use GC.
160209467b48Spatrick   DenseMap<const Function *, std::string> GCNames;
160309467b48Spatrick 
160409467b48Spatrick   /// Flag to indicate if Value (other than GlobalValue) retains their name or
160509467b48Spatrick   /// not.
160609467b48Spatrick   bool DiscardValueNames = false;
160709467b48Spatrick 
160809467b48Spatrick   LLVMContextImpl(LLVMContext &C);
160909467b48Spatrick   ~LLVMContextImpl();
161009467b48Spatrick 
161109467b48Spatrick   /// Destroy the ConstantArrays if they are not used.
161209467b48Spatrick   void dropTriviallyDeadConstantArrays();
161309467b48Spatrick 
161409467b48Spatrick   mutable OptPassGate *OPG = nullptr;
161509467b48Spatrick 
161609467b48Spatrick   /// Access the object which can disable optional passes and individual
161709467b48Spatrick   /// optimizations at compile time.
161809467b48Spatrick   OptPassGate &getOptPassGate() const;
161909467b48Spatrick 
162009467b48Spatrick   /// Set the object which can disable optional passes and individual
162109467b48Spatrick   /// optimizations at compile time.
162209467b48Spatrick   ///
162309467b48Spatrick   /// The lifetime of the object must be guaranteed to extend as long as the
162409467b48Spatrick   /// LLVMContext is used by compilation.
162509467b48Spatrick   void setOptPassGate(OptPassGate &);
1626*d415bd75Srobert 
1627*d415bd75Srobert   // TODO: clean up the following after we no longer support non-opaque pointer
1628*d415bd75Srobert   // types.
1629*d415bd75Srobert   bool getOpaquePointers();
1630*d415bd75Srobert   void setOpaquePointers(bool OP);
1631*d415bd75Srobert 
1632*d415bd75Srobert private:
1633*d415bd75Srobert   std::optional<bool> OpaquePointers;
163409467b48Spatrick };
163509467b48Spatrick 
163609467b48Spatrick } // end namespace llvm
163709467b48Spatrick 
163809467b48Spatrick #endif // LLVM_LIB_IR_LLVMCONTEXTIMPL_H
1639